import { useEffect, useRef, useCallback, useState } from 'react'; import { listen } from '@tauri-apps/api/event'; import { useAuthStore } from '../stores/authStore'; type SignalingEvent = | 'friend:request_received' | 'friend:request_accepted' | 'friend:online' | 'friend:offline' | 'room:invite_received' | 'room:member_joined' | 'room:member_left' | 'network:signaling' | 'network:status_changed'; interface EventHandler { event: SignalingEvent; handler: (payload: T) => void; } export function useSignalingEvents(handlers: EventHandler[]) { useEffect(() => { const unsubscribes: (() => void)[] = []; for (const { event, handler } of handlers) { listen(event, (e) => handler(e.payload)).then((unsub) => { unsubscribes.push(unsub); }); } return () => { unsubscribes.forEach((unsub) => unsub()); }; }, [handlers]); } export function useNetworkStatus() { const [status, setStatus] = useState<{ type: 'p2p' | 'relay' | 'disconnected'; port?: number; connectAddr?: string; }>({ type: 'disconnected' }); useEffect(() => { const unsub = listen<{ type: string; port?: number; connect_addr?: string }>( 'network:status_changed', (event) => { setStatus({ type: event.payload.type as 'p2p' | 'relay' | 'disconnected', port: event.payload.port, connectAddr: event.payload.connect_addr, }); } ); return () => { unsub.then((fn) => fn()); }; }, []); return status; } export function useFriendEvents( onRequest?: (from: string, username: string) => void, onAccepted?: (from: string, username: string) => void, onOnline?: (userId: string) => void, onOffline?: (userId: string) => void ) { useEffect(() => { const unsubscribes: Promise<() => void>[] = []; if (onRequest) { unsubscribes.push( listen<{ from: string; username: string }>('friend:request_received', (e) => { onRequest(e.payload.from, e.payload.username); }) ); } if (onAccepted) { unsubscribes.push( listen<{ from: string; username: string }>('friend:request_accepted', (e) => { onAccepted(e.payload.from, e.payload.username); }) ); } if (onOnline) { unsubscribes.push( listen<{ user_id: string }>('friend:online', (e) => { onOnline(e.payload.user_id); }) ); } if (onOffline) { unsubscribes.push( listen<{ user_id: string }>('friend:offline', (e) => { onOffline(e.payload.user_id); }) ); } return () => { unsubscribes.forEach((p) => p.then((fn) => fn())); }; }, [onRequest, onAccepted, onOnline, onOffline]); } export function useRoomEvents( onInvite?: (from: string, roomId: string, roomName: string) => void, onMemberJoined?: (roomId: string, userId: string, username: string) => void, onMemberLeft?: (roomId: string, userId: string) => void ) { useEffect(() => { const unsubscribes: Promise<() => void>[] = []; if (onInvite) { unsubscribes.push( listen<{ from: string; room_id: string; room_name: string }>('room:invite_received', (e) => { onInvite(e.payload.from, e.payload.room_id, e.payload.room_name); }) ); } if (onMemberJoined) { unsubscribes.push( listen<{ room_id: string; user_id: string; username: string }>('room:member_joined', (e) => { onMemberJoined(e.payload.room_id, e.payload.user_id, e.payload.username); }) ); } if (onMemberLeft) { unsubscribes.push( listen<{ room_id: string; user_id: string }>('room:member_left', (e) => { onMemberLeft(e.payload.room_id, e.payload.user_id); }) ); } return () => { unsubscribes.forEach((p) => p.then((fn) => fn())); }; }, [onInvite, onMemberJoined, onMemberLeft]); }