From ff09c3d969cfd934d8b130b032a782c616806e87 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Thu, 10 Apr 2025 19:17:42 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(frontend)=20factorize=20noti?= =?UTF-8?q?fyParticipants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract notifyParticipants in a proper hook to avoid duplication. --- .../hooks/useNotifyParticipants.ts | 37 +++++++++++++++++++ .../src/features/notifications/index.ts | 2 + .../rooms/livekit/api/muteParticipant.ts | 25 +++++-------- .../livekit/components/ScreenRecording.tsx | 28 +++++++------- .../rooms/livekit/components/Transcript.tsx | 27 ++++++-------- 5 files changed, 73 insertions(+), 46 deletions(-) create mode 100644 src/frontend/src/features/notifications/hooks/useNotifyParticipants.ts create mode 100644 src/frontend/src/features/notifications/index.ts diff --git a/src/frontend/src/features/notifications/hooks/useNotifyParticipants.ts b/src/frontend/src/features/notifications/hooks/useNotifyParticipants.ts new file mode 100644 index 00000000..9ac5d882 --- /dev/null +++ b/src/frontend/src/features/notifications/hooks/useNotifyParticipants.ts @@ -0,0 +1,37 @@ +import { useRoomContext } from '@livekit/components-react' +import { NotificationType } from '../NotificationType' +import { NotificationPayload } from '../NotificationPayload' + +export const useNotifyParticipants = () => { + const room = useRoomContext() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const notifyParticipants = async >(options: { + type: NotificationType + destinationIdentities?: string[] + additionalData?: T + reliable?: boolean + }): Promise => { + const { + type, + destinationIdentities, + additionalData = {} as T, + reliable = true, + } = options + + const payload: NotificationPayload & T = { + type, + ...additionalData, + } + + const encoder = new TextEncoder() + const data = encoder.encode(JSON.stringify(payload)) + + await room.localParticipant.publishData(data, { + reliable, + destinationIdentities, + }) + } + + return { notifyParticipants } +} diff --git a/src/frontend/src/features/notifications/index.ts b/src/frontend/src/features/notifications/index.ts new file mode 100644 index 00000000..ffe15d4b --- /dev/null +++ b/src/frontend/src/features/notifications/index.ts @@ -0,0 +1,2 @@ +export { useNotifyParticipants } from './hooks/useNotifyParticipants' +export { NotificationType } from './NotificationType' diff --git a/src/frontend/src/features/rooms/livekit/api/muteParticipant.ts b/src/frontend/src/features/rooms/livekit/api/muteParticipant.ts index a25f6718..310f9a26 100644 --- a/src/frontend/src/features/rooms/livekit/api/muteParticipant.ts +++ b/src/frontend/src/features/rooms/livekit/api/muteParticipant.ts @@ -3,25 +3,15 @@ import Source = Track.Source import { fetchServerApi } from './fetchServerApi' import { buildServerApiUrl } from './buildServerApiUrl' import { useRoomData } from '../hooks/useRoomData' -import { useRoomContext } from '@livekit/components-react' -import { NotificationType } from '@/features/notifications/NotificationType' -import { NotificationPayload } from '@/features/notifications/NotificationPayload' +import { + useNotifyParticipants, + NotificationType, +} from '@/features/notifications' export const useMuteParticipant = () => { const data = useRoomData() - const room = useRoomContext() - const notifyParticipant = async (participant: Participant) => { - const encoder = new TextEncoder() - const payload: NotificationPayload = { - type: NotificationType.ParticipantMuted, - } - const data = encoder.encode(JSON.stringify(payload)) - await room.localParticipant.publishData(data, { - reliable: true, - destinationIdentities: [participant.identity], - }) - } + const { notifyParticipants } = useNotifyParticipants() const muteParticipant = async (participant: Participant) => { if (!data || !data?.livekit) { @@ -53,7 +43,10 @@ export const useMuteParticipant = () => { } ) - await notifyParticipant(participant) + await notifyParticipants({ + type: NotificationType.ParticipantMuted, + destinationIdentities: [participant.identity], + }) return response } catch (error) { diff --git a/src/frontend/src/features/rooms/livekit/components/ScreenRecording.tsx b/src/frontend/src/features/rooms/livekit/components/ScreenRecording.tsx index 3310279e..727bce71 100644 --- a/src/frontend/src/features/rooms/livekit/components/ScreenRecording.tsx +++ b/src/frontend/src/features/rooms/livekit/components/ScreenRecording.tsx @@ -12,8 +12,6 @@ import { import { useEffect, useMemo, useState } from 'react' import { RoomEvent } from 'livekit-client' import { useTranslation } from 'react-i18next' -import { NotificationPayload } from '@/features/notifications/NotificationPayload' -import { NotificationType } from '@/features/notifications/NotificationType' import { RecordingStatus, recordingStore } from '@/stores/recording' import { CRISP_HELP_ARTICLE_RECORDING } from '@/utils/constants' import { @@ -22,10 +20,17 @@ import { useIsTranscriptStarted, } from '@/features/recording' +import { + useNotifyParticipants, + NotificationType, +} from '@/features/notifications' + export const ScreenRecording = () => { const [isLoading, setIsLoading] = useState(false) const { t } = useTranslation('rooms', { keyPrefix: 'screenRecording' }) + const { notifyParticipants } = useNotifyParticipants() + const roomId = useRoomId() const { mutateAsync: startRecordingRoom } = useStartRecording() @@ -47,17 +52,6 @@ export const ScreenRecording = () => { } }, [room]) - const notifyParticipant = async (status: NotificationType) => { - const encoder = new TextEncoder() - const payload: NotificationPayload = { - type: status, - } - const data = encoder.encode(JSON.stringify(payload)) - await room.localParticipant.publishData(data, { - reliable: true, - }) - } - const handleScreenRecording = async () => { if (!roomId) { console.warn('No room ID found') @@ -67,15 +61,19 @@ export const ScreenRecording = () => { setIsLoading(true) if (room.isRecording) { await stopRecordingRoom({ id: roomId }) - await notifyParticipant(NotificationType.ScreenRecordingStopped) recordingStore.status = RecordingStatus.SCREEN_RECORDING_STOPPING + await notifyParticipants({ + type: NotificationType.ScreenRecordingStopped, + }) } else { await startRecordingRoom({ id: roomId, mode: RecordingMode.ScreenRecording, }) - await notifyParticipant(NotificationType.ScreenRecordingStarted) recordingStore.status = RecordingStatus.SCREEN_RECORDING_STARTING + await notifyParticipants({ + type: NotificationType.ScreenRecordingStarted, + }) } } catch (error) { console.error('Failed to handle transcript:', error) diff --git a/src/frontend/src/features/rooms/livekit/components/Transcript.tsx b/src/frontend/src/features/rooms/livekit/components/Transcript.tsx index c7039d75..16c8de1a 100644 --- a/src/frontend/src/features/rooms/livekit/components/Transcript.tsx +++ b/src/frontend/src/features/rooms/livekit/components/Transcript.tsx @@ -16,19 +16,23 @@ import { import { useEffect, useMemo, useState } from 'react' import { RoomEvent } from 'livekit-client' import { useTranslation } from 'react-i18next' -import { NotificationPayload } from '@/features/notifications/NotificationPayload' -import { NotificationType } from '@/features/notifications/NotificationType' import { RecordingStatus, recordingStore } from '@/stores/recording' import { BETA_USERS_FORM_URL, CRISP_HELP_ARTICLE_TRANSCRIPT, } from '@/utils/constants' import { FeatureFlags } from '@/features/analytics/enums' +import { + useNotifyParticipants, + NotificationType, +} from '@/features/notifications' export const Transcript = () => { const [isLoading, setIsLoading] = useState(false) const { t } = useTranslation('rooms', { keyPrefix: 'transcript' }) + const { notifyParticipants } = useNotifyParticipants() + const hasTranscriptAccess = useHasRecordingAccess( RecordingMode.Transcript, FeatureFlags.Transcript @@ -54,17 +58,6 @@ export const Transcript = () => { } }, [room]) - const notifyParticipant = async (status: NotificationType) => { - const encoder = new TextEncoder() - const payload: NotificationPayload = { - type: status, - } - const data = encoder.encode(JSON.stringify(payload)) - await room.localParticipant.publishData(data, { - reliable: true, - }) - } - const handleTranscript = async () => { if (!roomId) { console.warn('No room ID found') @@ -74,12 +67,16 @@ export const Transcript = () => { setIsLoading(true) if (room.isRecording) { await stopRecordingRoom({ id: roomId }) - await notifyParticipant(NotificationType.TranscriptionStopped) recordingStore.status = RecordingStatus.TRANSCRIPT_STOPPING + await notifyParticipants({ + type: NotificationType.TranscriptionStopped, + }) } else { await startRecordingRoom({ id: roomId, mode: RecordingMode.Transcript }) - await notifyParticipant(NotificationType.TranscriptionStarted) recordingStore.status = RecordingStatus.TRANSCRIPT_STARTING + await notifyParticipants({ + type: NotificationType.TranscriptionStarted, + }) } } catch (error) { console.error('Failed to handle transcript:', error)