marp-share / client /src /collab /useCollab.ts
Nipun's picture
Fix only-first-slide: gate preview on realtime sync (loading state)
3f7565e verified
Raw
History Blame Contribute Delete
1.61 kB
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 }
}