♻️(frontend) refactor ParticipantName component for internationalization

Component now supports i18n. The participant tile needs further refactoring as
it still mixes LiveKit CSS with custom styling.
This commit is contained in:
lebaudantoine
2025-04-28 16:03:01 +02:00
committed by aleb_the_flash
parent e519f00342
commit bc76c44fe9
6 changed files with 94 additions and 33 deletions

View File

@@ -0,0 +1,42 @@
import { Text } from '@/primitives'
import { useTranslation } from 'react-i18next'
import { useParticipantInfo } from '@livekit/components-react'
import { Participant } from 'livekit-client'
export const ParticipantName = ({
participant,
isScreenShare = false,
}: {
participant: Participant
isScreenShare: boolean
}) => {
const { t } = useTranslation('rooms', { keyPrefix: 'participantTile' })
const { identity, name } = useParticipantInfo({ participant })
const displayedName = name != '' ? name : identity
if (isScreenShare) {
return (
<Text
variant="sm"
style={{
paddingBottom: '0.1rem',
marginLeft: '0.4rem',
}}
>
{t('screenShare', { name: displayedName })}
</Text>
)
}
return (
<Text
variant="sm"
style={{
paddingBottom: '0.1rem',
}}
>
{displayedName}
</Text>
)
}

View File

@@ -2,7 +2,6 @@ import {
AudioTrack,
ConnectionQualityIndicator,
LockLockedIcon,
ParticipantName,
ParticipantTileProps,
ScreenShareIcon,
useEnsureTrackRef,
@@ -29,6 +28,7 @@ import { MutedMicIndicator } from './MutedMicIndicator'
import { ParticipantPlaceholder } from './ParticipantPlaceholder'
import { ParticipantTileFocus } from './ParticipantTileFocus'
import { FullScreenShareWarning } from './FullScreenShareWarning'
import { ParticipantName } from './ParticipantName'
export function TrackRefContextIfNeeded(
props: React.PropsWithChildren<{
@@ -97,6 +97,8 @@ export const ParticipantTile: (
participant: trackReference.participant,
})
const isScreenShare = trackReference.source != Track.Source.Camera
return (
<div ref={ref} style={{ position: 'relative' }} {...elementProps}>
<TrackRefContextIfNeeded trackRef={trackReference}>
@@ -129,45 +131,50 @@ export const ParticipantTile: (
{!disableMetadata && (
<div className="lk-participant-metadata">
<HStack gap={0.25}>
<MutedMicIndicator
participant={trackReference.participant}
/>
{!isScreenShare && (
<MutedMicIndicator
participant={trackReference.participant}
/>
)}
<div
className="lk-participant-metadata-item"
style={{
minHeight: '24px',
backgroundColor: isHandRaised ? 'white' : undefined,
color: isHandRaised ? 'black' : undefined,
padding: '0.1rem 0.25rem',
backgroundColor:
isHandRaised && !isScreenShare ? 'white' : undefined,
color:
isHandRaised && !isScreenShare ? 'black' : undefined,
transition: 'background 200ms ease, color 400ms ease',
}}
>
{trackReference.source === Track.Source.Camera ? (
<>
{isHandRaised && (
<RiHand
color="black"
size={16}
style={{
marginInlineEnd: '.25rem', // fixme - match TrackMutedIndicator styling
animationDuration: '300ms',
animationName: 'wave_hand',
animationIterationCount: '2',
}}
/>
)}
{isEncrypted && (
<LockLockedIcon
style={{ marginRight: '0.25rem' }}
/>
)}
<ParticipantName />
</>
) : (
<>
<ScreenShareIcon style={{ marginRight: '0.25rem' }} />
<ParticipantName>&apos;s screen</ParticipantName>
</>
{isHandRaised && !isScreenShare && (
<RiHand
color="black"
size={16}
style={{
marginRight: '0.4rem',
minWidth: '16px',
animationDuration: '300ms',
animationName: 'wave_hand',
animationIterationCount: '2',
}}
/>
)}
{isScreenShare && (
<ScreenShareIcon
style={{
maxWidth: '20px',
width: '100%',
}}
/>
)}
{isEncrypted && !isScreenShare && (
<LockLockedIcon style={{ marginRight: '0.25rem' }} />
)}
<ParticipantName
isScreenShare={isScreenShare}
participant={trackReference.participant}
/>
</div>
</HStack>
<ConnectionQualityIndicator className="lk-participant-metadata-item" />

View File

@@ -363,5 +363,8 @@
"message": "",
"stop": "",
"ignore": ""
},
"participantTile": {
"screenShare": ""
}
}

View File

@@ -364,5 +364,8 @@
"message": "To avoid infinite loop display, do not share your entire screen. Instead, share a tab or another window.",
"stop": "Stop presenting",
"ignore": "Ignore"
},
"participantTile": {
"screenShare": "{{name}}'s screen"
}
}

View File

@@ -364,5 +364,8 @@
"message": "Pour éviter l'affichage en boucle infinie, ne partagez pas l'intégralité de votre écran. Partagez plutôt un onglet ou une autre fenêtre.",
"stop": "Arrêter la présentation",
"ignore": "Ignorer"
},
"participantTile": {
"screenShare": "Écran de {{name}}"
}
}

View File

@@ -364,5 +364,8 @@
"message": "Om niet oneindige uw scherm in zichzelf te delen, kunt u beter niet het hele scherm delen. Deel in plaats daarvan een tab of een ander venster.",
"stop": "Stop met presenteren",
"ignore": "Negeren"
},
"participantTile": {
"screenShare": "{{name}} scherm"
}
}