Initial commit: FunConnect project with server, relay, client and admin panel
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
147
client/ui/src/hooks/useWebSocket.ts
Normal file
147
client/ui/src/hooks/useWebSocket.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
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]);
|
||||
}
|
||||
Reference in New Issue
Block a user