Spaces:
Sleeping
Sleeping
| import { useEffect, useState } from 'react' | |
| import { getSession, type CollabSession } from './store' | |
| import type { CollabUser } from './user' | |
| export type ConnStatus = 'connecting' | 'connected' | 'disconnected' | |
| export interface CollabState { | |
| session: CollabSession | |
| status: ConnStatus | |
| peers: CollabUser[] | |
| synced: boolean | |
| } | |
| export function useCollab(deckId: string, user: CollabUser, token?: string): CollabState { | |
| const session = getSession(deckId, token) | |
| const [status, setStatus] = useState<ConnStatus>('connecting') | |
| const [peers, setPeers] = useState<CollabUser[]>([]) | |
| const [synced, setSynced] = useState<boolean>(Boolean(session.provider.isSynced)) | |
| useEffect(() => { | |
| const { provider } = session | |
| const aw = provider.awareness | |
| aw?.setLocalStateField('user', user) | |
| const onStatus = (e: { status: ConnStatus }) => setStatus(e.status) | |
| provider.on('status', onStatus) | |
| setStatus((provider.status as ConnStatus) ?? 'connecting') | |
| const onSynced = () => setSynced(true) | |
| provider.on('synced', onSynced) | |
| if (provider.isSynced) setSynced(true) | |
| const updatePeers = () => { | |
| if (!aw) return | |
| const users: CollabUser[] = [] | |
| aw.getStates().forEach((st) => { | |
| const u = (st as { user?: CollabUser }).user | |
| if (u) users.push(u) | |
| }) | |
| setPeers(users) | |
| } | |
| aw?.on('change', updatePeers) | |
| updatePeers() | |
| return () => { | |
| provider.off('status', onStatus) | |
| provider.off('synced', onSynced) | |
| aw?.off('change', updatePeers) | |
| } | |
| }, [session, user]) | |
| return { session, status, peers, synced } | |
| } | |