(frontend) allow lowering all hands at once

Inspired from Gmeet. Add a button to lower all hands at once.
It should be quite useful for room moderator/admin.

The UX might feel strange, having this action button at the top of
the list, but I could not figure out a better layout. In terms of
UX I feel this is the best we can provide. However, the UI should
definitely be improved.
This commit is contained in:
lebaudantoine
2024-09-03 11:25:35 +02:00
committed by aleb_the_flash
parent 584be7e65b
commit c8023573c6
7 changed files with 57 additions and 3 deletions

View File

@@ -0,0 +1,18 @@
import { Participant } from 'livekit-client'
import { useLowerHandParticipant } from '@/features/rooms/livekit/api/lowerHandParticipant'
export const useLowerHandParticipants = () => {
const { lowerHandParticipant } = useLowerHandParticipant()
const lowerHandParticipants = (participants: Array<Participant>) => {
try {
const promises = participants.map((participant) =>
lowerHandParticipant(participant)
)
return Promise.all(promises)
} catch (error) {
throw new Error('An error occurred while lowering hands.')
}
}
return { lowerHandParticipants }
}

View File

@@ -0,0 +1,26 @@
import { Button } from '@/primitives'
import { useLowerHandParticipants } from '@/features/rooms/livekit/api/lowerHandParticipants'
import { useTranslation } from 'react-i18next'
import { Participant } from 'livekit-client'
type LowerAllHandsButtonProps = {
participants: Array<Participant>
}
export const LowerAllHandsButton = ({
participants,
}: LowerAllHandsButtonProps) => {
const { lowerHandParticipants } = useLowerHandParticipants()
const { t } = useTranslation('rooms')
return (
<Button
aria-label={t('participants.lowerParticipantsHand')}
size="sm"
fullWidth
invisible
onPress={() => lowerHandParticipants(participants)}
>
{t('participants.lowerParticipantsHand')}
</Button>
)
}

View File

@@ -50,12 +50,14 @@ type ParticipantsCollapsableListProps = {
heading: string heading: string
participants: Array<Participant> participants: Array<Participant>
renderParticipant: (participant: Participant) => JSX.Element renderParticipant: (participant: Participant) => JSX.Element
action?: () => JSX.Element
} }
export const ParticipantsCollapsableList = ({ export const ParticipantsCollapsableList = ({
heading, heading,
participants, participants,
renderParticipant, renderParticipant,
action,
}: ParticipantsCollapsableListProps) => { }: ParticipantsCollapsableListProps) => {
const { t } = useTranslation('rooms') const { t } = useTranslation('rooms')
const [isOpen, setIsOpen] = useState(true) const [isOpen, setIsOpen] = useState(true)
@@ -98,6 +100,7 @@ export const ParticipantsCollapsableList = ({
</ToggleHeader> </ToggleHeader>
{isOpen && ( {isOpen && (
<ListContainer> <ListContainer>
{action && action()}
{participants.map((participant) => renderParticipant(participant))} {participants.map((participant) => renderParticipant(participant))}
</ListContainer> </ListContainer>
)} )}

View File

@@ -11,6 +11,7 @@ import { allParticipantRoomEvents } from '@/features/rooms/livekit/constants/eve
import { ParticipantListItem } from '@/features/rooms/livekit/components/controls/Participants/ParticipantListItem' import { ParticipantListItem } from '@/features/rooms/livekit/components/controls/Participants/ParticipantListItem'
import { ParticipantsCollapsableList } from '@/features/rooms/livekit/components/controls/Participants/ParticipantsCollapsableList' import { ParticipantsCollapsableList } from '@/features/rooms/livekit/components/controls/Participants/ParticipantsCollapsableList'
import { HandRaisedListItem } from '@/features/rooms/livekit/components/controls/Participants/HandRaisedListItem' import { HandRaisedListItem } from '@/features/rooms/livekit/components/controls/Participants/HandRaisedListItem'
import { LowerAllHandsButton } from '@/features/rooms/livekit/components/controls/Participants/LowerAllHandsButton'
// 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 = () => {
@@ -101,6 +102,9 @@ export const ParticipantsList = () => {
renderParticipant={(participant) => ( renderParticipant={(participant) => (
<HandRaisedListItem participant={participant} /> <HandRaisedListItem participant={participant} />
)} )}
action={() => (
<LowerAllHandsButton participants={raisedHandParticipants} />
)}
/> />
</div> </div>
)} )}

View File

@@ -68,6 +68,7 @@
"cancel": "" "cancel": ""
}, },
"raisedHands": "", "raisedHands": "",
"lowerParticipantHand": "" "lowerParticipantHand": "",
"lowerParticipantsHand": ""
} }
} }

View File

@@ -68,6 +68,7 @@
"cancel": "Cancel" "cancel": "Cancel"
}, },
"raisedHands": "Raised hands", "raisedHands": "Raised hands",
"lowerParticipantHand": "Lower {{name}}'s hand" "lowerParticipantHand": "Lower {{name}}'s hand",
"lowerParticipantsHand": "Lower all hands"
} }
} }

View File

@@ -68,6 +68,7 @@
"cancel": "Annuler" "cancel": "Annuler"
}, },
"raisedHands": "Mains levées", "raisedHands": "Mains levées",
"lowerParticipantHand": "Baisser la main de {{name}}" "lowerParticipantHand": "Baisser la main de {{name}}",
"lowerParticipantsHand": "Baisser la main de tous les participants"
} }
} }