♻️(frontend) introduce a recording mutation hook
Mutualize and factorize the recording API error modal in a single place, and extract all recording mutations into a dedicated hook exposing both start and stop actions. This hook is responsible for interacting with the API error dialog when needed. Previously, this logic was duplicated across each side panel; centralizing it clarifies responsibilities and reduces duplication.
This commit is contained in:
committed by
aleb_the_flash
parent
08f281e778
commit
9d69fe4f4f
@@ -0,0 +1,29 @@
|
||||
import { Button, Dialog, P } from '@/primitives'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { recordingStore } from '@/stores/recording'
|
||||
|
||||
export const ErrorAlertDialog = () => {
|
||||
const recordingSnap = useSnapshot(recordingStore)
|
||||
const { t } = useTranslation('rooms', {
|
||||
keyPrefix: 'errorRecordingAlertDialog',
|
||||
})
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isOpen={!!recordingSnap.isErrorDialogOpen}
|
||||
role="alertdialog"
|
||||
title={t('title')}
|
||||
aria-label={t('title')}
|
||||
>
|
||||
<P>{t(`body.${recordingSnap.isErrorDialogOpen}`)}</P>
|
||||
<Button
|
||||
variant="text"
|
||||
size="sm"
|
||||
onPress={() => (recordingStore.isErrorDialogOpen = '')}
|
||||
>
|
||||
{t('button')}
|
||||
</Button>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import { LimitReachedAlertDialog } from './LimitReachedAlertDialog'
|
||||
import { RecordingStateToast } from './RecordingStateToast'
|
||||
import { ErrorAlertDialog } from './ErrorAlertDialog'
|
||||
|
||||
export const RecordingProvider = () => {
|
||||
return (
|
||||
<>
|
||||
<RecordingStateToast />
|
||||
<LimitReachedAlertDialog />
|
||||
<ErrorAlertDialog />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { A, Button, Dialog, Div, H, P, Text } from '@/primitives'
|
||||
import { A, Div, H, Text } from '@/primitives'
|
||||
|
||||
import { css } from '@/styled-system/css'
|
||||
import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId'
|
||||
@@ -6,8 +6,6 @@ import { useRoomContext } from '@livekit/components-react'
|
||||
import {
|
||||
RecordingMode,
|
||||
useHasFeatureWithoutAdminRights,
|
||||
useStartRecording,
|
||||
useStopRecording,
|
||||
useHumanizeRecordingMaxDuration,
|
||||
useRecordingStatuses,
|
||||
} from '@/features/recording'
|
||||
@@ -28,6 +26,7 @@ import { RowWrapper } from './RowWrapper'
|
||||
import { VStack } from '@/styled-system/jsx'
|
||||
import { Checkbox } from '@/primitives/Checkbox'
|
||||
import { useTranscriptionLanguage } from '@/features/settings'
|
||||
import { useMutateRecording } from '../hooks/useMutateRecording'
|
||||
|
||||
export const ScreenRecordingSidePanel = () => {
|
||||
const { data } = useConfig()
|
||||
@@ -36,8 +35,6 @@ export const ScreenRecordingSidePanel = () => {
|
||||
const keyPrefix = 'screenRecording'
|
||||
const { t } = useTranslation('rooms', { keyPrefix })
|
||||
|
||||
const [isErrorDialogOpen, setIsErrorDialogOpen] = useState('')
|
||||
|
||||
const [includeTranscript, setIncludeTranscript] = useState(false)
|
||||
|
||||
const hasFeatureWithoutAdminRights = useHasFeatureWithoutAdminRights(
|
||||
@@ -51,14 +48,8 @@ export const ScreenRecordingSidePanel = () => {
|
||||
|
||||
const roomId = useRoomId()
|
||||
|
||||
const { mutateAsync: startRecordingRoom, isPending: isPendingToStart } =
|
||||
useStartRecording({
|
||||
onError: () => setIsErrorDialogOpen('start'),
|
||||
})
|
||||
const { mutateAsync: stopRecordingRoom, isPending: isPendingToStop } =
|
||||
useStopRecording({
|
||||
onError: () => setIsErrorDialogOpen('stop'),
|
||||
})
|
||||
const { startRecording, isPendingToStart, stopRecording, isPendingToStop } =
|
||||
useMutateRecording()
|
||||
|
||||
const statuses = useRecordingStatuses(RecordingMode.ScreenRecording)
|
||||
|
||||
@@ -72,7 +63,7 @@ export const ScreenRecordingSidePanel = () => {
|
||||
try {
|
||||
if (statuses.isStarted || statuses.isStarting) {
|
||||
setIncludeTranscript(false)
|
||||
await stopRecordingRoom({ id: roomId })
|
||||
await stopRecording({ id: roomId })
|
||||
|
||||
await notifyParticipants({
|
||||
type: NotificationType.ScreenRecordingStopped,
|
||||
@@ -89,7 +80,7 @@ export const ScreenRecordingSidePanel = () => {
|
||||
...(includeTranscript && { transcribe: true }),
|
||||
}
|
||||
|
||||
await startRecordingRoom({
|
||||
await startRecording({
|
||||
id: roomId,
|
||||
mode: RecordingMode.ScreenRecording,
|
||||
options: recordingOptions,
|
||||
@@ -194,20 +185,6 @@ export const ScreenRecordingSidePanel = () => {
|
||||
isPendingToStart={isPendingToStart}
|
||||
isPendingToStop={isPendingToStop}
|
||||
/>
|
||||
<Dialog
|
||||
isOpen={!!isErrorDialogOpen}
|
||||
role="alertdialog"
|
||||
aria-label={t('alert.title')}
|
||||
>
|
||||
<P>{t(`alert.body.${isErrorDialogOpen}`)}</P>
|
||||
<Button
|
||||
variant="text"
|
||||
size="sm"
|
||||
onPress={() => setIsErrorDialogOpen('')}
|
||||
>
|
||||
{t('alert.button')}
|
||||
</Button>
|
||||
</Dialog>
|
||||
</Div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { A, Button, Dialog, Div, H, P, Text } from '@/primitives'
|
||||
import { A, Button, Div, H, Text } from '@/primitives'
|
||||
|
||||
import { css } from '@/styled-system/css'
|
||||
import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId'
|
||||
@@ -6,8 +6,6 @@ import { useRoomContext } from '@livekit/components-react'
|
||||
import {
|
||||
RecordingMode,
|
||||
useHasRecordingAccess,
|
||||
useStartRecording,
|
||||
useStopRecording,
|
||||
useHasFeatureWithoutAdminRights,
|
||||
useHumanizeRecordingMaxDuration,
|
||||
useRecordingStatuses,
|
||||
@@ -33,6 +31,7 @@ import {
|
||||
import { NoAccessView } from './NoAccessView'
|
||||
import { ControlsButton } from './ControlsButton'
|
||||
import { RowWrapper } from './RowWrapper'
|
||||
import { useMutateRecording } from '../hooks/useMutateRecording'
|
||||
|
||||
export const TranscriptSidePanel = () => {
|
||||
const { data } = useConfig()
|
||||
@@ -41,7 +40,6 @@ export const TranscriptSidePanel = () => {
|
||||
const keyPrefix = 'transcript'
|
||||
const { t } = useTranslation('rooms', { keyPrefix })
|
||||
|
||||
const [isErrorDialogOpen, setIsErrorDialogOpen] = useState('')
|
||||
const [includeScreenRecording, setIncludeScreenRecording] = useState(false)
|
||||
|
||||
const { notifyParticipants } = useNotifyParticipants()
|
||||
@@ -62,15 +60,8 @@ export const TranscriptSidePanel = () => {
|
||||
|
||||
const roomId = useRoomId()
|
||||
|
||||
const { mutateAsync: startRecordingRoom, isPending: isPendingToStart } =
|
||||
useStartRecording({
|
||||
onError: () => setIsErrorDialogOpen('start'),
|
||||
})
|
||||
|
||||
const { mutateAsync: stopRecordingRoom, isPending: isPendingToStop } =
|
||||
useStopRecording({
|
||||
onError: () => setIsErrorDialogOpen('stop'),
|
||||
})
|
||||
const { startRecording, isPendingToStart, stopRecording, isPendingToStop } =
|
||||
useMutateRecording()
|
||||
|
||||
const statuses = useRecordingStatuses(RecordingMode.Transcript)
|
||||
|
||||
@@ -83,7 +74,7 @@ export const TranscriptSidePanel = () => {
|
||||
}
|
||||
try {
|
||||
if (statuses.isStarted || statuses.isStarting) {
|
||||
await stopRecordingRoom({ id: roomId })
|
||||
await stopRecording({ id: roomId })
|
||||
setIncludeScreenRecording(false)
|
||||
|
||||
await notifyParticipants({
|
||||
@@ -108,7 +99,7 @@ export const TranscriptSidePanel = () => {
|
||||
}),
|
||||
}
|
||||
|
||||
await startRecordingRoom({
|
||||
await startRecording({
|
||||
id: roomId,
|
||||
mode: recordingMode,
|
||||
options: recordingOptions,
|
||||
@@ -251,20 +242,6 @@ export const TranscriptSidePanel = () => {
|
||||
isPendingToStart={isPendingToStart}
|
||||
isPendingToStop={isPendingToStop}
|
||||
/>
|
||||
<Dialog
|
||||
isOpen={!!isErrorDialogOpen}
|
||||
role="alertdialog"
|
||||
aria-label={t('alert.title')}
|
||||
>
|
||||
<P>{t(`alert.body.${isErrorDialogOpen}`)}</P>
|
||||
<Button
|
||||
variant="text"
|
||||
size="sm"
|
||||
onPress={() => setIsErrorDialogOpen('')}
|
||||
>
|
||||
{t('alert.button')}
|
||||
</Button>
|
||||
</Dialog>
|
||||
</Div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { useStartRecording, useStopRecording } from '@/features/recording'
|
||||
import { recordingStore } from '@/stores/recording'
|
||||
|
||||
export const useMutateRecording = () => {
|
||||
const { mutateAsync: startRecording, isPending: isPendingToStart } =
|
||||
useStartRecording({
|
||||
onError: () => {
|
||||
recordingStore.isErrorDialogOpen = 'start'
|
||||
},
|
||||
})
|
||||
const { mutateAsync: stopRecording, isPending: isPendingToStop } =
|
||||
useStopRecording({
|
||||
onError: () => {
|
||||
recordingStore.isErrorDialogOpen = 'stop'
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
startRecording,
|
||||
isPendingToStart,
|
||||
stopRecording,
|
||||
isPendingToStop,
|
||||
}
|
||||
}
|
||||
@@ -344,14 +344,6 @@
|
||||
"heading": "Anmeldung erforderlich",
|
||||
"body": "Nur der Ersteller des Meetings oder ein Administrator kann die Transkription starten. Melden Sie sich an, um Ihre Berechtigungen zu überprüfen."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Transkription fehlgeschlagen",
|
||||
"body": {
|
||||
"stop": "Die Transkription konnte nicht gestoppt werden. Bitte versuche es in einem Moment erneut.",
|
||||
"start": "Die Transkription konnte nicht gestartet werden. Bitte versuche es in einem Moment erneut."
|
||||
},
|
||||
"button": "OK"
|
||||
}
|
||||
},
|
||||
"screenRecording": {
|
||||
@@ -381,16 +373,16 @@
|
||||
"body": "Nur der Ersteller der Besprechung oder ein Administrator kann die Aufzeichnung starten. Melden Sie sich an, um Ihre Berechtigungen zu überprüfen."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Aufzeichnung fehlgeschlagen",
|
||||
"body": {
|
||||
"stop": "Die Aufzeichnung konnte nicht gestoppt werden. Bitte versuche es in einem Moment erneut.",
|
||||
"start": "Die Aufzeichnung konnte nicht gestartet werden. Bitte versuche es in einem Moment erneut."
|
||||
},
|
||||
"button": "OK"
|
||||
},
|
||||
"durationMessage": "(begrenzt auf {{max_duration}})"
|
||||
},
|
||||
"errorRecordingAlertDialog": {
|
||||
"title": "Aufzeichnung fehlgeschlagen",
|
||||
"body": {
|
||||
"stop": "Die Aufzeichnung konnte nicht gestoppt werden. Bitte versuche es in einem Moment erneut.",
|
||||
"start": "Die Aufzeichnung konnte nicht gestartet werden. Bitte versuche es in einem Moment erneut."
|
||||
},
|
||||
"button": "OK"
|
||||
},
|
||||
"admin": {
|
||||
"description": "Diese Einstellungen für Organisatoren ermöglichen dir die Kontrolle über dein Meeting. Nur Organisatoren haben Zugriff auf diese Optionen.",
|
||||
"access": {
|
||||
|
||||
@@ -344,14 +344,6 @@
|
||||
"heading": "You are not logged in!",
|
||||
"body": "You must be logged in to use this feature. Please log in, then try again."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Transcription Failed",
|
||||
"body": {
|
||||
"stop": "We were unable to stop the transcription. Please try again in a moment.",
|
||||
"start": "We were unable to start the transcription. Please try again in a moment."
|
||||
},
|
||||
"button": "OK"
|
||||
}
|
||||
},
|
||||
"screenRecording": {
|
||||
@@ -381,16 +373,16 @@
|
||||
"body": "Only the meeting creator or an admin can start screen recording. Log in to verify your permissions."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Recording Failed",
|
||||
"body": {
|
||||
"stop": "We were unable to stop the recording. Please try again in a moment.",
|
||||
"start": "We were unable to start the recording. Please try again in a moment."
|
||||
},
|
||||
"button": "OK"
|
||||
},
|
||||
"durationMessage": "(limited to {{max_duration}}) "
|
||||
},
|
||||
"errorRecordingAlertDialog": {
|
||||
"title": "Recording Failed",
|
||||
"body": {
|
||||
"stop": "We were unable to stop the recording. Please try again in a moment.",
|
||||
"start": "We were unable to start the recording. Please try again in a moment."
|
||||
},
|
||||
"button": "OK"
|
||||
},
|
||||
"admin": {
|
||||
"description": "These organizer settings allow you to maintain control of your meeting. Only organizers can access these controls.",
|
||||
"access": {
|
||||
|
||||
@@ -344,14 +344,6 @@
|
||||
"heading": "Vous n'êtes pas connecté !",
|
||||
"body": "Vous devez être connecté pour utiliser cette fonctionnalité. Connectez-vous, puis réessayez."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Échec de transcription",
|
||||
"body": {
|
||||
"stop": "Nous n'avons pas pu stopper la transcription. Veuillez réessayer dans quelques instants.",
|
||||
"start": "Nous n'avons pas pu démarrer la transcription. Veuillez réessayer dans quelques instants."
|
||||
},
|
||||
"button": "OK"
|
||||
}
|
||||
},
|
||||
"screenRecording": {
|
||||
@@ -381,16 +373,16 @@
|
||||
"body": "Seul le créateur de la réunion ou un administrateur peut démarrer l'enregistrement. Connectez-vous pour vérifier vos autorisations."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Échec de l'enregistrement",
|
||||
"body": {
|
||||
"stop": "Nous n'avons pas pu stopper l'enregistrement. Veuillez réessayer dans quelques instants.",
|
||||
"start": "Nous n'avons pas pu démarrer l'enregistrement. Veuillez réessayer dans quelques instants."
|
||||
},
|
||||
"button": "OK"
|
||||
},
|
||||
"durationMessage": "(limité à {{max_duration}}) "
|
||||
},
|
||||
"errorRecordingAlertDialog": {
|
||||
"title": "Échec de l'enregistrement",
|
||||
"body": {
|
||||
"stop": "Nous n'avons pas pu stopper l'enregistrement. Veuillez réessayer dans quelques instants.",
|
||||
"start": "Nous n'avons pas pu démarrer l'enregistrement. Veuillez réessayer dans quelques instants."
|
||||
},
|
||||
"button": "OK"
|
||||
},
|
||||
"admin": {
|
||||
"description": "Ces paramètres organisateur vous permettent de garder le contrôle de votre réunion. Seuls les organisateurs peuvent accéder à ces commandes.",
|
||||
"access": {
|
||||
|
||||
@@ -344,14 +344,6 @@
|
||||
"heading": "Inloggen vereist",
|
||||
"body": "Alleen de maker van de vergadering of een beheerder kan de transcriptie starten. Log in om uw machtigingen te controleren."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Transcriptie mislukt",
|
||||
"body": {
|
||||
"stop": "We konden de transcriptie niet stoppen. Probeer het over enkele ogenblikken opnieuw.",
|
||||
"start": "We konden de transcriptie niet starten. Probeer het over enkele ogenblikken opnieuw."
|
||||
},
|
||||
"button": "Opnieuw proberen"
|
||||
}
|
||||
},
|
||||
"screenRecording": {
|
||||
@@ -381,16 +373,16 @@
|
||||
"body": "Alleen de maker van de vergadering of een beheerder kan de opname starten. Log in om uw machtigingen te controleren."
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"title": "Opname mislukt",
|
||||
"body": {
|
||||
"stop": "We konden de opname niet stoppen. Probeer het over enkele ogenblikken opnieuw.",
|
||||
"start": "We konden de opname niet starten. Probeer het over enkele ogenblikken opnieuw."
|
||||
},
|
||||
"button": "Opnieuw proberen"
|
||||
},
|
||||
"durationMessage": "(beperkt tot {{max_duration}})"
|
||||
},
|
||||
"errorRecordingAlertDialog": {
|
||||
"title": "Opname mislukt",
|
||||
"body": {
|
||||
"stop": "We konden de opname niet stoppen. Probeer het over enkele ogenblikken opnieuw.",
|
||||
"start": "We konden de opname niet starten. Probeer het over enkele ogenblikken opnieuw."
|
||||
},
|
||||
"button": "Opnieuw proberen"
|
||||
},
|
||||
"admin": {
|
||||
"description": "Deze organisatorinstellingen geven u controle over uw vergadering. Alleen organisatoren hebben toegang tot deze bedieningselementen.",
|
||||
"access": {
|
||||
|
||||
@@ -8,8 +8,10 @@ export enum RecordingLanguage {
|
||||
|
||||
type State = {
|
||||
language: RecordingLanguage
|
||||
isErrorDialogOpen: string
|
||||
}
|
||||
|
||||
export const recordingStore = proxy<State>({
|
||||
language: RecordingLanguage.FRENCH,
|
||||
isErrorDialogOpen: '',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user