mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-29 11:47:15 +00:00
⚡️(frontend) optimize participant metadata rendering on raised hand
Push state down into the participant metadata subtree so a raised hand change no longer re-renders the whole metadata block. Use the children-as-props pattern so only the item actually related to the raised hand re-renders when its state changes. This also better encapsulates the color-update logic tied to the raised-hand state.
This commit is contained in:
committed by
aleb_the_flash
parent
5f52fa8d8d
commit
f21c4c91ed
@@ -1,7 +1,3 @@
|
|||||||
import {
|
|
||||||
useRaisedHand,
|
|
||||||
useRaisedHandPosition,
|
|
||||||
} from '@/features/rooms/livekit/hooks/useRaisedHand'
|
|
||||||
import {
|
import {
|
||||||
ConnectionQualityIndicator,
|
ConnectionQualityIndicator,
|
||||||
LockLockedIcon,
|
LockLockedIcon,
|
||||||
@@ -12,8 +8,8 @@ import {
|
|||||||
import { HStack } from '@/styled-system/jsx'
|
import { HStack } from '@/styled-system/jsx'
|
||||||
import { Participant } from 'livekit-client'
|
import { Participant } from 'livekit-client'
|
||||||
import { MutedMicIndicator } from './MutedMicIndicator'
|
import { MutedMicIndicator } from './MutedMicIndicator'
|
||||||
import { RiHand } from '@remixicon/react'
|
|
||||||
import { ParticipantName } from './ParticipantName'
|
import { ParticipantName } from './ParticipantName'
|
||||||
|
import { RaisedHandMetadataWrapper } from './RaisedHandMetadataWrapper'
|
||||||
|
|
||||||
export const ParticipantMetadata = ({
|
export const ParticipantMetadata = ({
|
||||||
participant,
|
participant,
|
||||||
@@ -24,52 +20,15 @@ export const ParticipantMetadata = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { identity, name } = useParticipantInfo({ participant })
|
const { identity, name } = useParticipantInfo({ participant })
|
||||||
const isEncrypted = useIsEncrypted(participant)
|
const isEncrypted = useIsEncrypted(participant)
|
||||||
const { isHandRaised } = useRaisedHand({ participant })
|
|
||||||
const { positionInQueue, firstInQueue } = useRaisedHandPosition({
|
|
||||||
participant,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="lk-participant-metadata">
|
<div className="lk-participant-metadata">
|
||||||
<HStack gap={0.25}>
|
<HStack gap={0.25}>
|
||||||
{!isScreenShare && <MutedMicIndicator participant={participant} />}
|
{!isScreenShare && <MutedMicIndicator participant={participant} />}
|
||||||
<div
|
<RaisedHandMetadataWrapper
|
||||||
className="lk-participant-metadata-item"
|
participant={participant}
|
||||||
style={{
|
enabled={!isScreenShare}
|
||||||
padding: '0.1rem 0.25rem',
|
|
||||||
backgroundColor:
|
|
||||||
isHandRaised && !isScreenShare
|
|
||||||
? firstInQueue
|
|
||||||
? '#fde047'
|
|
||||||
: 'white'
|
|
||||||
: undefined,
|
|
||||||
color: isHandRaised && !isScreenShare ? 'black' : undefined,
|
|
||||||
transition: 'background 200ms ease, color 400ms ease',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{isHandRaised && !isScreenShare && (
|
|
||||||
<span
|
|
||||||
style={{
|
|
||||||
display: 'inline-flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
gap: '0.1rem',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>{positionInQueue}</span>
|
|
||||||
<RiHand
|
|
||||||
color="black"
|
|
||||||
size={16}
|
|
||||||
style={{
|
|
||||||
marginRight: '0.4rem',
|
|
||||||
marginLeft: '0.1rem',
|
|
||||||
minWidth: '16px',
|
|
||||||
animationDuration: '300ms',
|
|
||||||
animationName: 'wave_hand',
|
|
||||||
animationIterationCount: '2',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{isScreenShare && (
|
{isScreenShare && (
|
||||||
<ScreenShareIcon
|
<ScreenShareIcon
|
||||||
style={{
|
style={{
|
||||||
@@ -87,7 +46,7 @@ export const ParticipantMetadata = ({
|
|||||||
isScreenShare={isScreenShare}
|
isScreenShare={isScreenShare}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</RaisedHandMetadataWrapper>
|
||||||
</HStack>
|
</HStack>
|
||||||
<ConnectionQualityIndicator className="lk-participant-metadata-item" />
|
<ConnectionQualityIndicator className="lk-participant-metadata-item" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import React, { ReactNode, RefObject, useEffect, useRef } from 'react'
|
||||||
|
import {
|
||||||
|
useRaisedHand,
|
||||||
|
useRaisedHandPosition,
|
||||||
|
} from '@/features/rooms/livekit/hooks/useRaisedHand'
|
||||||
|
import { Participant } from 'livekit-client'
|
||||||
|
import { RiHand } from '@remixicon/react'
|
||||||
|
|
||||||
|
const PositionInQueue = React.memo(
|
||||||
|
({ positionInQueue }: { positionInQueue?: number }) => {
|
||||||
|
if (!positionInQueue) return
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.1rem' }}
|
||||||
|
>
|
||||||
|
<span>{positionInQueue}</span>
|
||||||
|
<RiHand
|
||||||
|
color="black"
|
||||||
|
size={16}
|
||||||
|
style={{
|
||||||
|
marginRight: '0.4rem',
|
||||||
|
marginLeft: '0.1rem',
|
||||||
|
minWidth: '16px',
|
||||||
|
animationDuration: '300ms',
|
||||||
|
animationName: 'wave_hand',
|
||||||
|
animationIterationCount: '2',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
PositionInQueue.displayName = 'PositionInQueue'
|
||||||
|
|
||||||
|
const RaisedHandActiveItem = ({
|
||||||
|
participant,
|
||||||
|
targetRef,
|
||||||
|
}: {
|
||||||
|
participant: Participant
|
||||||
|
targetRef: RefObject<HTMLElement | null>
|
||||||
|
}) => {
|
||||||
|
const { positionInQueue, firstInQueue } = useRaisedHandPosition({
|
||||||
|
participant,
|
||||||
|
})
|
||||||
|
useEffect(() => {
|
||||||
|
const el = targetRef.current
|
||||||
|
if (!el) return
|
||||||
|
|
||||||
|
el.style.backgroundColor = firstInQueue ? '#fde047' : 'white'
|
||||||
|
el.style.color = 'black'
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
el.style.backgroundColor = ''
|
||||||
|
el.style.color = ''
|
||||||
|
}
|
||||||
|
}, [targetRef, firstInQueue])
|
||||||
|
|
||||||
|
return <PositionInQueue positionInQueue={positionInQueue} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RaisedHandMetadataWrapper = ({
|
||||||
|
participant,
|
||||||
|
enabled = true,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
participant: Participant
|
||||||
|
enabled?: boolean
|
||||||
|
children: ReactNode
|
||||||
|
}) => {
|
||||||
|
const ref = useRef(null)
|
||||||
|
|
||||||
|
const { isHandRaised } = useRaisedHand({ participant })
|
||||||
|
const showHand = isHandRaised && enabled
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className="lk-participant-metadata-item"
|
||||||
|
style={{
|
||||||
|
padding: '0.1rem 0.25rem',
|
||||||
|
transition: 'background 200ms ease',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{showHand && (
|
||||||
|
<RaisedHandActiveItem participant={participant} targetRef={ref} />
|
||||||
|
)}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user