diff --git a/src/frontend/src/features/rooms/api/muteParticipants.ts b/src/frontend/src/features/rooms/api/muteParticipants.ts new file mode 100644 index 00000000..6a12a689 --- /dev/null +++ b/src/frontend/src/features/rooms/api/muteParticipants.ts @@ -0,0 +1,19 @@ +import { Participant } from 'livekit-client' +import { useMuteParticipant } from './muteParticipant' + +export const useMuteParticipants = () => { + const { muteParticipant } = useMuteParticipant() + + const muteParticipants = (participants: Array) => { + try { + const promises = participants.map((participant) => + muteParticipant(participant) + ) + return Promise.all(promises) + } catch (error) { + console.error('An error occurred while muting participants :', error) + throw new Error('An error occurred while muting participants.') + } + } + return { muteParticipants } +} diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Participants/LowerAllHandsButton.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Participants/LowerAllHandsButton.tsx index 1ab05e4d..571439c7 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/Participants/LowerAllHandsButton.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/Participants/LowerAllHandsButton.tsx @@ -3,6 +3,8 @@ import { useTranslation } from 'react-i18next' import { Participant } from 'livekit-client' import { useLowerHandParticipants } from '@/features/rooms/api/lowerHandParticipants' import { useIsAdminOrOwner } from '@/features/rooms/livekit/hooks/useIsAdminOrOwner' +import { css } from '@/styled-system/css' +import { RiHand } from '@remixicon/react' type LowerAllHandsButtonProps = { participants: Array @@ -22,10 +24,14 @@ export const LowerAllHandsButton = ({ aria-label={t('participants.lowerParticipantsHand')} size="sm" fullWidth - variant="text" + variant="tertiary" onPress={() => lowerHandParticipants(participants)} data-attr="participants-lower-hands" + className={css({ + marginBottom: '0.5rem', + })} > + {t('participants.lowerParticipantsHand')} ) diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Participants/MuteEveryoneButton.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Participants/MuteEveryoneButton.tsx new file mode 100644 index 00000000..e0a39a56 --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/controls/Participants/MuteEveryoneButton.tsx @@ -0,0 +1,38 @@ +import { Button } from '@/primitives' +import { useTranslation } from 'react-i18next' +import { Participant } from 'livekit-client' +import { useIsAdminOrOwner } from '@/features/rooms/livekit/hooks/useIsAdminOrOwner' +import { useMuteParticipants } from '@/features/rooms/api/muteParticipants' +import { RiMicOffLine } from '@remixicon/react' +import { css } from '@/styled-system/css' + +type MuteEveryoneButtonProps = { + participants: Array +} + +export const MuteEveryoneButton = ({ + participants, +}: MuteEveryoneButtonProps) => { + const { muteParticipants } = useMuteParticipants() + const { t } = useTranslation('rooms') + + const isAdminOrOwner = useIsAdminOrOwner() + if (!isAdminOrOwner || !participants.length) return null + + return ( + + ) +} diff --git a/src/frontend/src/features/rooms/livekit/components/controls/Participants/ParticipantsList.tsx b/src/frontend/src/features/rooms/livekit/components/controls/Participants/ParticipantsList.tsx index 8aa63f60..340d9cb3 100644 --- a/src/frontend/src/features/rooms/livekit/components/controls/Participants/ParticipantsList.tsx +++ b/src/frontend/src/features/rooms/livekit/components/controls/Participants/ParticipantsList.tsx @@ -11,6 +11,7 @@ import { WaitingParticipantListItem } from './WaitingParticipantListItem' import { useWaitingParticipants } from '@/features/rooms/hooks/useWaitingParticipants' import { Participant } from 'livekit-client' import { WaitingParticipant } from '@/features/rooms/api/listWaitingParticipants' +import { MuteEveryoneButton } from './MuteEveryoneButton' // TODO: Optimize rendering performance, especially for longer participant lists, even though they are generally short. export const ParticipantsList = () => { @@ -104,6 +105,9 @@ export const ParticipantsList = () => { participant={participant} /> )} + action={() => ( + + )} /> ) diff --git a/src/frontend/src/locales/de/rooms.json b/src/frontend/src/locales/de/rooms.json index 1a8db979..6e56c60b 100644 --- a/src/frontend/src/locales/de/rooms.json +++ b/src/frontend/src/locales/de/rooms.json @@ -443,6 +443,7 @@ "raisedHands": "Meldungen", "lowerParticipantHand": "{{name}}’s Hand senken", "lowerParticipantsHand": "Alle Hände senken", + "muteParticipants": "Alle Mikrofone stummschalten", "waiting": { "title": "Warteraum", "accept": { diff --git a/src/frontend/src/locales/en/rooms.json b/src/frontend/src/locales/en/rooms.json index fd401d7c..473897b8 100644 --- a/src/frontend/src/locales/en/rooms.json +++ b/src/frontend/src/locales/en/rooms.json @@ -443,6 +443,7 @@ "raisedHands": "Raised hands", "lowerParticipantHand": "Lower {{name}}'s hand", "lowerParticipantsHand": "Lower all hands", + "muteParticipants": "Mute all microphones", "waiting": { "title": "Lobby", "accept": { diff --git a/src/frontend/src/locales/fr/rooms.json b/src/frontend/src/locales/fr/rooms.json index ebc1bd48..2d478cce 100644 --- a/src/frontend/src/locales/fr/rooms.json +++ b/src/frontend/src/locales/fr/rooms.json @@ -442,7 +442,8 @@ }, "raisedHands": "Mains levées", "lowerParticipantHand": "Baisser la main de {{name}}", - "lowerParticipantsHand": "Baisser la main de tous les participants", + "lowerParticipantsHand": "Baisser toutes les mains", + "muteParticipants": "Couper tous les micros", "waiting": { "title": "Salle d'attente", "accept": { diff --git a/src/frontend/src/locales/nl/rooms.json b/src/frontend/src/locales/nl/rooms.json index b44d56a1..ca21c9eb 100644 --- a/src/frontend/src/locales/nl/rooms.json +++ b/src/frontend/src/locales/nl/rooms.json @@ -443,6 +443,7 @@ "raisedHands": "Opgestoken handen", "lowerParticipantHand": "Laat {{name}}'s hand zakken", "lowerParticipantsHand": "Laat alle handen zakken", + "muteParticipants": "Alle microfoons dempen", "waiting": { "title": "Wachtkamer", "accept": {