✨(frontend) customize avatar's color to each participant
Default 'transparent' value avoid showing the avatar when participant's info are not yet available. Might be a bad design if we follow the single responsability pattern. Please feel free to refactor it.
This commit is contained in:
committed by
aleb_the_flash
parent
3dda12ada6
commit
98ae9af84a
@@ -11,14 +11,14 @@ export type AvatarProps = React.HTMLAttributes<HTMLSpanElement> & {
|
|||||||
export const Avatar = ({
|
export const Avatar = ({
|
||||||
name,
|
name,
|
||||||
size = 32,
|
size = 32,
|
||||||
bgColor = '#3498db',
|
bgColor,
|
||||||
textColor = 'white',
|
textColor = 'white',
|
||||||
}: AvatarProps) => {
|
}: AvatarProps) => {
|
||||||
const initial = name?.trim()?.charAt(0).toUpperCase() || ''
|
const initial = name?.trim()?.charAt(0).toUpperCase() || ''
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={css({
|
className={css({
|
||||||
backgroundColor: bgColor,
|
backgroundColor: 'transparent',
|
||||||
color: textColor,
|
color: textColor,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
@@ -33,6 +33,7 @@ export const Avatar = ({
|
|||||||
width: `${size}px`,
|
width: `${size}px`,
|
||||||
height: `${size}px`,
|
height: `${size}px`,
|
||||||
fontSize: `${size * 0.4}px`,
|
fontSize: `${size * 0.4}px`,
|
||||||
|
backgroundColor: bgColor,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{initial}
|
{initial}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Participant } from 'livekit-client'
|
|||||||
import { styled } from '@/styled-system/jsx'
|
import { styled } from '@/styled-system/jsx'
|
||||||
import { Avatar } from '@/components/Avatar'
|
import { Avatar } from '@/components/Avatar'
|
||||||
import { useIsSpeaking } from '@livekit/components-react'
|
import { useIsSpeaking } from '@livekit/components-react'
|
||||||
|
import { getParticipantColor } from '@/features/rooms/utils/getParticipantColor'
|
||||||
|
|
||||||
const StyledParticipantPlaceHolder = styled('div', {
|
const StyledParticipantPlaceHolder = styled('div', {
|
||||||
base: {
|
base: {
|
||||||
@@ -22,7 +23,7 @@ export const ParticipantPlaceholder = ({
|
|||||||
participant,
|
participant,
|
||||||
}: ParticipantPlaceholderProps) => {
|
}: ParticipantPlaceholderProps) => {
|
||||||
const isSpeaking = useIsSpeaking(participant)
|
const isSpeaking = useIsSpeaking(participant)
|
||||||
|
const participantColor = getParticipantColor(participant)
|
||||||
return (
|
return (
|
||||||
<StyledParticipantPlaceHolder>
|
<StyledParticipantPlaceHolder>
|
||||||
<div
|
<div
|
||||||
@@ -31,7 +32,7 @@ export const ParticipantPlaceholder = ({
|
|||||||
animation: isSpeaking ? 'pulse 1s infinite' : undefined,
|
animation: isSpeaking ? 'pulse 1s infinite' : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Avatar name={participant.name} />
|
<Avatar name={participant.name} bgColor={participantColor} />
|
||||||
</div>
|
</div>
|
||||||
</StyledParticipantPlaceHolder>
|
</StyledParticipantPlaceHolder>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { participantsStore } from '@/stores/participants'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { allParticipantRoomEvents } from '@/features/rooms/livekit/constants/events'
|
import { allParticipantRoomEvents } from '@/features/rooms/livekit/constants/events'
|
||||||
import { Avatar } from '@/components/Avatar'
|
import { Avatar } from '@/components/Avatar'
|
||||||
|
import { getParticipantColor } from '@/features/rooms/utils/getParticipantColor'
|
||||||
|
|
||||||
// TODO: Optimize rendering performance, especially for longer participant lists, even though they are generally short.
|
// TODO: Optimize rendering performance, especially for longer participant lists, even though they are generally short.
|
||||||
export const ParticipantsList = () => {
|
export const ParticipantsList = () => {
|
||||||
@@ -26,6 +27,7 @@ export const ParticipantsList = () => {
|
|||||||
const formattedParticipants = participants.map((participant) => ({
|
const formattedParticipants = participants.map((participant) => ({
|
||||||
name: participant.name || participant.identity,
|
name: participant.name || participant.identity,
|
||||||
id: participant.identity,
|
id: participant.identity,
|
||||||
|
color: getParticipantColor(participant),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const sortedRemoteParticipants = formattedParticipants
|
const sortedRemoteParticipants = formattedParticipants
|
||||||
@@ -94,7 +96,7 @@ export const ParticipantsList = () => {
|
|||||||
padding: '0.25rem 0',
|
padding: '0.25rem 0',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Avatar name={participant.name} />
|
<Avatar name={participant.name} bgColor={participant.color} />
|
||||||
<Text
|
<Text
|
||||||
variant={'sm'}
|
variant={'sm'}
|
||||||
className={css({
|
className={css({
|
||||||
|
|||||||
11
src/frontend/src/features/rooms/utils/getParticipantColor.ts
Normal file
11
src/frontend/src/features/rooms/utils/getParticipantColor.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Participant } from 'livekit-client'
|
||||||
|
|
||||||
|
export const getParticipantColor = (
|
||||||
|
participant: Participant
|
||||||
|
): undefined | string => {
|
||||||
|
const { metadata } = participant
|
||||||
|
if (!metadata) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return JSON.parse(metadata)['color']
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user