🚸(frontend) enhance mic indicator in participant list

The Gmeet-inspired indicator was misleading for users,
at least those not used to GSuite products.

They didn't understand how to mute a participant.

Plus, having the button disabled for the local participant,
was creating confusion. To simplify the UX, have all
the buttons enabled is simpler to understand.

Empirical observations with a few number of users, should be
enhance and challenge in the long run.
This commit is contained in:
lebaudantoine
2024-09-05 19:17:15 +02:00
committed by aleb_the_flash
parent aaf6b03a25
commit c5ce32ef79
5 changed files with 33 additions and 12 deletions

View File

@@ -81,6 +81,11 @@ const config: Config = {
'80%': { transform: 'rotate(20deg)' },
'100%': { transform: 'rotate(0)' },
},
pulse_mic: {
'0%': { color: 'primary', opacity: '1' },
'50%': { color: 'primary', opacity: '0.8' },
'100%': { color: 'primary', opacity: '1' },
},
},
tokens: defineTokens({
/* we take a few things from the panda preset but for now we clear out some stuff.

View File

@@ -13,7 +13,12 @@ import {
useTrackMutedIndicator,
} from '@livekit/components-react'
import Source = Track.Source
import { RiMicOffLine } from '@remixicon/react'
import {
RiMicFill,
RiMicLine,
RiMicOffFill,
RiMicOffLine,
} from '@remixicon/react'
import { Button, Dialog, P } from '@/primitives'
import { useState } from 'react'
import { useMuteParticipant } from '@/features/rooms/livekit/api/muteParticipant'
@@ -57,10 +62,7 @@ const MicIndicator = ({ participant }: MicIndicatorProps) => {
source: Source.Microphone,
})
const isSpeaking = useIsSpeaking(participant)
const isDisabled = isLocal(participant) || (!isLocal(participant) && isMuted)
const [isAlertOpen, setIsAlertOpen] = useState(false)
const name = participant.name || participant.identity
return (
@@ -69,16 +71,28 @@ const MicIndicator = ({ participant }: MicIndicatorProps) => {
square
invisible
size="sm"
tooltip={t('participants.muteParticipant', {
name,
})}
isDisabled={isDisabled}
onPress={() => !isMuted && setIsAlertOpen(true)}
tooltip={
isLocal(participant)
? t('participants.muteYourself')
: t('participants.muteParticipant', {
name,
})
}
isDisabled={isMuted}
onPress={() =>
!isMuted && isLocal(participant)
? muteParticipant(participant)
: setIsAlertOpen(true)
}
>
{isMuted ? (
<RiMicOffLine color="gray" />
<RiMicOffFill color={'gray'} />
) : (
<ActiveSpeaker isSpeaking={isSpeaking} />
<RiMicFill
style={{
animation: isSpeaking ? 'pulse_mic 800ms infinite' : undefined,
}}
/>
)}
</Button>
<MuteAlertDialog
@@ -102,7 +116,6 @@ export const ParticipantListItem = ({
}: ParticipantListItemProps) => {
const { t } = useTranslation('rooms')
const name = participant.name || participant.identity
return (
<HStack
role="listitem"

View File

@@ -61,6 +61,7 @@
"close": ""
},
"you": "",
"muteYourself": "",
"muteParticipant": "",
"muteParticipantAlert": {
"description": "",

View File

@@ -61,6 +61,7 @@
"open": "Open {{name}} list",
"close": "Close {{name}} list"
},
"muteYourself": "Close your mic",
"muteParticipant": "Close the mic of {{name}}",
"muteParticipantAlert": {
"description": "Mute {{name}} for all participants? {{name}} is the only person who can unmute themselves.",

View File

@@ -61,6 +61,7 @@
"open": "Ouvrir la liste {{name}}",
"close": "Fermer la liste {{name}}"
},
"muteYourself": "Couper votre micro",
"muteParticipant": "Couper le micro de {{name}}",
"muteParticipantAlert": {
"description": "Couper le micro de {{name}} pour tous les participants ? {{name}} est la seule personne habilitée à réactiver son micro",