mirror of
https://github.com/suitenumerique/meet.git
synced 2026-07-26 11:58:53 +00:00
⚡️(frontend) minimize observables consumed by useRaisedHandPosition
useRaisedHandPosition is called on every participant tile, so any unnecessary subscription in it multiplies re-renders across the whole conference. Reduce the number of events subscribed to for remote participants to the strict minimum, while keeping the subscription to the relevant attributes of the local participant intact.
This commit is contained in:
@@ -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<string, number>()
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user