import { ref, onMounted, onUnmounted } from 'vue' export function useExtension() { const isExtensionReady = ref(false) const isListening = ref(false) const lastClipboardText = ref('') let extensionCheckInterval = null let lastPongTime = Date.now() const PING_INTERVAL = 200 const TIMEOUT_THRESHOLD = 1000 const handleMessage = (event) => { if (event.source !== window) return if (event.data.type === 'TOOLS_APP_EXTENSION_READY' || event.data.type === 'TOOLS_APP_PONG') { isExtensionReady.value = true lastPongTime = Date.now() } if (event.data.type === 'TOOLS_APP_CLIPBOARD_UPDATE') { const text = event.data.content // Only update if listening if (isListening.value && text) { lastClipboardText.value = text } } } const startWatchdog = () => { extensionCheckInterval = setInterval(() => { window.postMessage({ type: 'TOOLS_APP_PING' }, '*') if (Date.now() - lastPongTime > TIMEOUT_THRESHOLD) { isExtensionReady.value = false } }, PING_INTERVAL) } const startListening = () => { window.postMessage({ type: 'TOOLS_APP_START_SNIFFING' }, '*') isListening.value = true } const stopListening = () => { window.postMessage({ type: 'TOOLS_APP_STOP_SNIFFING' }, '*') isListening.value = false } const writeClipboard = (text) => { // Send to extension (background -> offscreen -> clipboard) window.postMessage({ type: 'TOOLS_APP_CLIPBOARD_WRITE', content: text }, '*') // Update local state to avoid echo loop if we are listening lastClipboardText.value = text } onMounted(() => { window.addEventListener('message', handleMessage) // Initial check window.postMessage({ type: 'TOOLS_APP_INIT' }, '*') startWatchdog() }) onUnmounted(() => { if (isListening.value) { stopListening() } if (extensionCheckInterval) clearInterval(extensionCheckInterval) window.removeEventListener('message', handleMessage) }) return { isExtensionReady, isListening, lastClipboardText, startListening, stopListening, writeClipboard } }