From 5d81ba1e208468dc270722810850b48bb398f39d Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 5 Mar 2025 19:26:58 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8(frontend)=20enhance=20waiting=20no?= =?UTF-8?q?tification=20with=20temporary=20quick=20actions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add adaptive content to existing notification that displays quick approval action for the first 10 seconds when new participants request entry. Makes room access management more efficient without requiring admin to open the participant panel. This approach could be apply to the two first participants waiting. Let's discuss it with the designer. --- .../WaitingParticipantNotification.tsx | 257 +++++++++++++----- .../src/locales/de/notifications.json | 3 +- .../src/locales/en/notifications.json | 3 +- .../src/locales/fr/notifications.json | 3 +- 4 files changed, 190 insertions(+), 76 deletions(-) diff --git a/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx b/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx index fc9fd3f0..e916645d 100644 --- a/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx +++ b/src/frontend/src/features/notifications/components/WaitingParticipantNotification.tsx @@ -1,100 +1,211 @@ -import { useListWaitingParticipants } from '@/features/rooms/api/listWaitingParticipants' -import { useRoomData } from '@/features/rooms/livekit/hooks/useRoomData' import { StyledToastContainer } from './Toast' -import { HStack } from '@/styled-system/jsx' +import { HStack, VStack } from '@/styled-system/jsx' import { Avatar } from '@/components/Avatar' -import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel' import { Button, Text } from '@/primitives' import { css } from '@/styled-system/css' import { RiInfinityLine } from '@remixicon/react' import { useTranslation } from 'react-i18next' +import { useEffect, useRef, useState } from 'react' +import { usePrevious } from '@/hooks/usePrevious' +import { WaitingParticipant } from '@/features/rooms/api/listWaitingParticipants' +import { useWaitingParticipants } from '@/features/rooms/hooks/useWaitingParticipants' +import { useSidePanel } from '@/features/rooms/livekit/hooks/useSidePanel' + +export const NOTIFICATION_DISPLAY_DURATION = 10000 export const WaitingParticipantNotification = () => { - const data = useRoomData() const { t } = useTranslation('notifications', { keyPrefix: 'waitingParticipants', }) + + const timerRef = useRef(null) const { isParticipantsOpen, toggleParticipants } = useSidePanel() - const { data: readOnlyData } = useListWaitingParticipants(data!.id, { - retry: false, - enabled: false, - }) - const participants = readOnlyData?.participants || [] - if (!participants.length) return + const [showQuickActionsMessage, setShowQuickActionsMessage] = useState(false) + const { waitingParticipants, handleParticipantEntry } = + useWaitingParticipants() + const prevWaitingParticipant = usePrevious( + waitingParticipants + ) + + const isParticipantListEmpty = (p?: WaitingParticipant[]) => p?.length == 0 + + useEffect(() => { + // Show notification when the first participant enters the waiting room + if ( + !isParticipantListEmpty(waitingParticipants) && + isParticipantListEmpty(prevWaitingParticipant) && + !isParticipantsOpen + ) { + setShowQuickActionsMessage(true) + if (timerRef.current !== null) { + clearTimeout(timerRef.current) + } + timerRef.current = setTimeout(() => { + setShowQuickActionsMessage(false) + timerRef.current = null // Clear the ref when timeout completes + }, NOTIFICATION_DISPLAY_DURATION) + } else if (waitingParticipants.length !== prevWaitingParticipant?.length) { + // Hide notification when the participant count changes + setShowQuickActionsMessage(false) + } + }, [waitingParticipants, prevWaitingParticipant, isParticipantsOpen]) + + useEffect(() => { + // This cleanup function will only run when the component unmounts + return () => { + if (timerRef.current !== null) { + clearTimeout(timerRef.current) + } + } + }, []) + + useEffect(() => { + // Hide notification when participants panel is opened + if (isParticipantsOpen) { + setShowQuickActionsMessage(false) + } + }, [isParticipantsOpen]) + + if (!waitingParticipants.length) return null + return ( 1 ? t('several') : t('one')} + aria-label={waitingParticipants.length > 1 ? t('several') : t('one')} aria-modal={false} > - - - {participants.length > 1 && ( - + - )} - {participants.length > 2 && ( - - {participants.length < 102 ? ( -

+{participants.length - 2}

- ) : ( - + {t('one')} +
+ + + + {waitingParticipants[0].username} + + + + + + + + ) : ( + <> + + + {waitingParticipants.length > 1 && ( + )} - - )} - - - {participants.length > 1 ? t('several') : t('one')} - - {!isParticipantsOpen && ( - + {waitingParticipants.length > 2 && ( + + {waitingParticipants.length < 102 ? ( +

+{waitingParticipants.length - 2}

+ ) : ( + + )} +
+ )} +
+ + {waitingParticipants.length > 1 ? t('several') : t('one')} + + {!isParticipantsOpen && ( + + )} + )}
diff --git a/src/frontend/src/locales/de/notifications.json b/src/frontend/src/locales/de/notifications.json index aa8c1508..0ef15bf3 100644 --- a/src/frontend/src/locales/de/notifications.json +++ b/src/frontend/src/locales/de/notifications.json @@ -19,6 +19,7 @@ "waitingParticipants": { "one": "", "several": "", - "open": "" + "open": "", + "accept": "" } } diff --git a/src/frontend/src/locales/en/notifications.json b/src/frontend/src/locales/en/notifications.json index 44f45cdf..45e55c27 100644 --- a/src/frontend/src/locales/en/notifications.json +++ b/src/frontend/src/locales/en/notifications.json @@ -19,6 +19,7 @@ "waitingParticipants": { "one": "One person wants to join this call.", "several": "Several people want to join this call.", - "open": "Open" + "open": "Open", + "accept": "Accept" } } diff --git a/src/frontend/src/locales/fr/notifications.json b/src/frontend/src/locales/fr/notifications.json index af88f072..9a0cef3d 100644 --- a/src/frontend/src/locales/fr/notifications.json +++ b/src/frontend/src/locales/fr/notifications.json @@ -19,6 +19,7 @@ "waitingParticipants": { "one": "Une personne souhaite participer à cet appel.", "several": "Plusieurs personnes souhaitent participer à cet appel.", - "open": "Afficher" + "open": "Afficher", + "accept": "Accepter" } }