diff --git a/src/frontend/src/features/rooms/livekit/hooks/useRaisedHand.ts b/src/frontend/src/features/rooms/livekit/hooks/useRaisedHand.ts index dd77ef7a..01612abc 100644 --- a/src/frontend/src/features/rooms/livekit/hooks/useRaisedHand.ts +++ b/src/frontend/src/features/rooms/livekit/hooks/useRaisedHand.ts @@ -1,7 +1,9 @@ -import type { Participant } from 'livekit-client' +import { Participant, RoomEvent } from 'livekit-client' import { + useRoomContext, useParticipantAttribute, - useParticipants, + useParticipantInfo, + useRemoteParticipants, } from '@livekit/components-react' import { isLocal } from '@/utils/livekit' import { useMemo } from 'react' @@ -12,28 +14,55 @@ type useRaisedHandProps = { } export function useRaisedHandPosition({ participant }: useRaisedHandProps) { - const { isHandRaised } = useRaisedHand({ participant }) + const room = useRoomContext() + const { identity } = useParticipantInfo({ participant }) + const localIdentity = room.localParticipant.identity - const participants = useParticipants() + const localHandRaisedAt = useParticipantAttribute('handRaisedAt', { + participant: room.localParticipant, + }) + + const remoteParticipants = useRemoteParticipants({ + updateOnlyOn: [RoomEvent.ParticipantAttributesChanged], + }) + + const raisedHands = useMemo(() => { + const byIdentity = new Map() + + const add = (id: string, value?: string) => { + const time = new Date(value ?? '').getTime() + if (Number.isNaN(time)) return + const existing = byIdentity.get(id) + if (existing === undefined || time < existing) byIdentity.set(id, time) + } + + if (localIdentity) add(localIdentity, localHandRaisedAt) + + remoteParticipants.forEach((p) => + add(p.identity, p.attributes.handRaisedAt) + ) + + return byIdentity + }, [remoteParticipants, localIdentity, localHandRaisedAt]) + + const sortedHands = useMemo( + () => + [...raisedHands.entries()] + .map(([identity, time]) => ({ identity, time })) + .sort( + (a, b) => a.time - b.time || a.identity.localeCompare(b.identity) + ), + [raisedHands] + ) const positionInQueue = useMemo(() => { - if (!isHandRaised) return - - return ( - participants - .filter((p) => !!p.attributes.handRaisedAt) - .sort((a, b) => { - const dateA = new Date(a.attributes.handRaisedAt) - const dateB = new Date(b.attributes.handRaisedAt) - return dateA.getTime() - dateB.getTime() - }) - .findIndex((p) => p.identity === participant.identity) + 1 - ) - }, [participants, participant, isHandRaised]) + const index = sortedHands.findIndex((h) => h.identity === identity) + return index === -1 ? undefined : index + 1 + }, [sortedHands, identity]) return { positionInQueue, - firstInQueue: positionInQueue == 1, + firstInQueue: positionInQueue === 1, } }