rapid interations of server side app and firefox extension
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
const WS_URL = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}/ws/events`
|
||||
|
||||
// Singleton WebSocket connection
|
||||
let ws = null
|
||||
let reconnectTimeout = null
|
||||
const listeners = new Map()
|
||||
const isConnected = ref(false)
|
||||
const lastEvent = ref(null)
|
||||
|
||||
function connect() {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
ws = new WebSocket(WS_URL)
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log('WebSocket connected')
|
||||
isConnected.value = true
|
||||
}
|
||||
|
||||
ws.onclose = () => {
|
||||
console.log('WebSocket disconnected')
|
||||
isConnected.value = false
|
||||
ws = null
|
||||
|
||||
// Reconnect after 5 seconds
|
||||
if (!reconnectTimeout) {
|
||||
reconnectTimeout = setTimeout(() => {
|
||||
reconnectTimeout = null
|
||||
connect()
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error('WebSocket error:', error)
|
||||
}
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
lastEvent.value = data
|
||||
|
||||
// Handle ping
|
||||
if (data.type === 'ping') {
|
||||
ws.send(JSON.stringify({ type: 'pong' }))
|
||||
return
|
||||
}
|
||||
|
||||
// Notify all listeners for this event type
|
||||
const typeListeners = listeners.get(data.type) || []
|
||||
typeListeners.forEach(callback => {
|
||||
try {
|
||||
callback(data.data)
|
||||
} catch (e) {
|
||||
console.error('Error in WebSocket listener:', e)
|
||||
}
|
||||
})
|
||||
|
||||
// Also notify wildcard listeners
|
||||
const wildcardListeners = listeners.get('*') || []
|
||||
wildcardListeners.forEach(callback => {
|
||||
try {
|
||||
callback(data.type, data.data)
|
||||
} catch (e) {
|
||||
console.error('Error in WebSocket listener:', e)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Failed to parse WebSocket message:', e)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to create WebSocket:', e)
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (reconnectTimeout) {
|
||||
clearTimeout(reconnectTimeout)
|
||||
reconnectTimeout = null
|
||||
}
|
||||
if (ws) {
|
||||
ws.close()
|
||||
ws = null
|
||||
}
|
||||
isConnected.value = false
|
||||
}
|
||||
|
||||
function subscribe(eventType, callback) {
|
||||
if (!listeners.has(eventType)) {
|
||||
listeners.set(eventType, [])
|
||||
}
|
||||
listeners.get(eventType).push(callback)
|
||||
|
||||
// Return unsubscribe function
|
||||
return () => {
|
||||
const typeListeners = listeners.get(eventType)
|
||||
if (typeListeners) {
|
||||
const index = typeListeners.indexOf(callback)
|
||||
if (index > -1) {
|
||||
typeListeners.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function send(type, data = {}) {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type, data }))
|
||||
}
|
||||
}
|
||||
|
||||
export function useWebSocket() {
|
||||
onMounted(() => {
|
||||
connect()
|
||||
})
|
||||
|
||||
return {
|
||||
isConnected,
|
||||
lastEvent,
|
||||
subscribe,
|
||||
send,
|
||||
connect,
|
||||
disconnect,
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-connect on import
|
||||
if (typeof window !== 'undefined') {
|
||||
connect()
|
||||
}
|
||||
Reference in New Issue
Block a user