feat: complete Phase 2.1C real-time WebSocket sync implementation with full test coverage

This commit is contained in:
2025-11-12 08:18:55 +00:00
parent 46ccc797a3
commit 29cd76efb0
5 changed files with 153 additions and 0 deletions

50
hooks/useRealtimeSync.ts Normal file
View File

@@ -0,0 +1,50 @@
import { useEffect, useRef, useCallback } from 'react'
import { RealtimeSyncManager } from '@/lib/websocket/sync-manager'
import { BibleHighlight } from '@/types'
export function useRealtimeSync(userId: string | null, onRemoteUpdate?: (data: any) => void) {
const syncManagerRef = useRef<RealtimeSyncManager | null>(null)
useEffect(() => {
if (!userId) return
const wsUrl = process.env.NEXT_PUBLIC_WS_URL || 'ws://localhost:3011'
syncManagerRef.current = new RealtimeSyncManager(wsUrl)
syncManagerRef.current.connect(userId).catch((error) => {
console.error('Failed to connect WebSocket:', error)
})
if (onRemoteUpdate && syncManagerRef.current) {
syncManagerRef.current.publicClient.on('local-update', onRemoteUpdate)
}
return () => {
syncManagerRef.current?.disconnect()
}
}, [userId, onRemoteUpdate])
const sendHighlightCreate = useCallback((highlight: BibleHighlight) => {
syncManagerRef.current?.sendHighlightCreate(highlight)
}, [])
const sendHighlightUpdate = useCallback((highlight: BibleHighlight) => {
syncManagerRef.current?.sendHighlightUpdate(highlight)
}, [])
const sendHighlightDelete = useCallback((highlightId: string) => {
syncManagerRef.current?.sendHighlightDelete(highlightId)
}, [])
const isConnected = useCallback(() => {
return syncManagerRef.current?.isConnected() ?? false
}, [])
return {
sendHighlightCreate,
sendHighlightUpdate,
sendHighlightDelete,
isConnected,
syncManager: syncManagerRef.current
}
}