Files
tools-app/src/composables/useExtension.js

80 lines
2.1 KiB
JavaScript

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
}
}