update
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, nextTick } from 'vue'
|
import { computed, ref, nextTick, onMounted, onUnmounted } from 'vue'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
import DOMPurify from 'dompurify'
|
import DOMPurify from 'dompurify'
|
||||||
import { htmlUrl, chatGuide, fetchProgress, setProgress } from '../api.js'
|
import { htmlUrl, chatGuide, fetchProgress, setProgress } from '../api.js'
|
||||||
@@ -25,6 +25,12 @@ function onFrameLoad(e) {
|
|||||||
if (!doc) return
|
if (!doc) return
|
||||||
injectStyles(doc)
|
injectStyles(doc)
|
||||||
setupProgress(doc)
|
setupProgress(doc)
|
||||||
|
// Klicks im iframe blubbern nicht zum Eltern-document → eigener Listener (same-origin)
|
||||||
|
doc.addEventListener('mousedown', onFrameMouseDown)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFrameMouseDown() {
|
||||||
|
if (chatOpen.value) closeChat()
|
||||||
}
|
}
|
||||||
|
|
||||||
function injectStyles(doc) {
|
function injectStyles(doc) {
|
||||||
@@ -113,6 +119,7 @@ const input = ref('')
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const messagesEl = ref(null)
|
const messagesEl = ref(null)
|
||||||
const inputEl = ref(null)
|
const inputEl = ref(null)
|
||||||
|
const panelEl = ref(null)
|
||||||
|
|
||||||
function openChat() {
|
function openChat() {
|
||||||
chatOpen.value = true
|
chatOpen.value = true
|
||||||
@@ -125,6 +132,36 @@ function closeChat() {
|
|||||||
input.value = ''
|
input.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Klicks außerhalb des iframes (Sidebar, Ränder) — mousedown vermeidet die Open/Close-Race beim FAB
|
||||||
|
function onDocMouseDown(e) {
|
||||||
|
if (!chatOpen.value) return
|
||||||
|
if (panelEl.value && panelEl.value.contains(e.target)) return
|
||||||
|
closeChat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter öffnet den Chat (wenn zu, nicht in Eingabefeld); ESC schließt ihn
|
||||||
|
function onDocKeyDown(e) {
|
||||||
|
if (e.key === 'Escape' && chatOpen.value) {
|
||||||
|
e.preventDefault()
|
||||||
|
closeChat()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (e.key !== 'Enter' || chatOpen.value || !props.previewGuide) return
|
||||||
|
const tag = document.activeElement?.tagName
|
||||||
|
if (tag === 'INPUT' || tag === 'TEXTAREA') return
|
||||||
|
e.preventDefault()
|
||||||
|
openChat()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener('mousedown', onDocMouseDown, true)
|
||||||
|
document.addEventListener('keydown', onDocKeyDown)
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener('mousedown', onDocMouseDown, true)
|
||||||
|
document.removeEventListener('keydown', onDocKeyDown)
|
||||||
|
})
|
||||||
|
|
||||||
function extractContext() {
|
function extractContext() {
|
||||||
try {
|
try {
|
||||||
const doc = frameEl.value?.contentDocument
|
const doc = frameEl.value?.contentDocument
|
||||||
@@ -199,7 +236,7 @@ async function send() {
|
|||||||
|
|
||||||
<button v-if="previewGuide && !chatOpen" class="chat-fab" title="Fragen zum Guide" @click="openChat">💬</button>
|
<button v-if="previewGuide && !chatOpen" class="chat-fab" title="Fragen zum Guide" @click="openChat">💬</button>
|
||||||
|
|
||||||
<div v-if="previewGuide && chatOpen" class="chat-panel">
|
<div v-if="previewGuide && chatOpen" ref="panelEl" class="chat-panel">
|
||||||
<header class="chat-header">
|
<header class="chat-header">
|
||||||
<span>Fragen zum Guide</span>
|
<span>Fragen zum Guide</span>
|
||||||
<button class="chat-close" title="Chat beenden" @click="closeChat">×</button>
|
<button class="chat-close" title="Chat beenden" @click="closeChat">×</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user