148 lines
3.9 KiB
TypeScript
148 lines
3.9 KiB
TypeScript
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<T = unknown> {
|
|
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]);
|
|
}
|