♻️(frontend) encapsulate recording maximum duration handling

Centralize the logic to compute, internationalize, and present the maximum
recording duration in a human-readable way, reducing duplication across the
codebase.
This commit is contained in:
lebaudantoine
2025-12-31 19:15:07 +01:00
committed by aleb_the_flash
parent 5e1705d259
commit f7d463f380
5 changed files with 33 additions and 20 deletions

View File

@@ -1,8 +1,7 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Button, Dialog, P } from '@/primitives' import { Button, Dialog, P } from '@/primitives'
import { HStack } from '@/styled-system/jsx' import { HStack } from '@/styled-system/jsx'
import { useConfig } from '@/api/useConfig' import { useHumanizeRecordingMaxDuration } from '@/features/recording'
import humanizeDuration from 'humanize-duration'
export const LimitReachedAlertDialog = ({ export const LimitReachedAlertDialog = ({
isOpen, isOpen,
@@ -11,19 +10,19 @@ export const LimitReachedAlertDialog = ({
isOpen: boolean isOpen: boolean
onClose: () => void onClose: () => void
}) => { }) => {
const { t, i18n } = useTranslation('rooms', { const { t } = useTranslation('rooms', {
keyPrefix: 'recordingStateToast.limitReachedAlert', keyPrefix: 'recordingStateToast.limitReachedAlert',
}) })
const { data } = useConfig()
const maxDuration = useHumanizeRecordingMaxDuration()
return ( return (
<Dialog isOpen={isOpen} role="alertdialog" title={t('title')}> <Dialog isOpen={isOpen} role="alertdialog" title={t('title')}>
<P> <P>
{t('description', { {t('description', {
duration_message: data?.recording?.max_duration duration_message: maxDuration
? t('durationMessage', { ? t('durationMessage', {
duration: humanizeDuration(data?.recording?.max_duration, { duration: maxDuration,
language: i18n.language,
}),
}) })
: '', : '',
})} })}

View File

@@ -8,6 +8,7 @@ import {
useHasFeatureWithoutAdminRights, useHasFeatureWithoutAdminRights,
useStartRecording, useStartRecording,
useStopRecording, useStopRecording,
useHumanizeRecordingMaxDuration,
} from '@/features/recording' } from '@/features/recording'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { ConnectionState, RoomEvent } from 'livekit-client' import { ConnectionState, RoomEvent } from 'livekit-client'
@@ -27,8 +28,6 @@ import posthog from 'posthog-js'
import { useSnapshot } from 'valtio/index' import { useSnapshot } from 'valtio/index'
import { Spinner } from '@/primitives/Spinner' import { Spinner } from '@/primitives/Spinner'
import { useConfig } from '@/api/useConfig' import { useConfig } from '@/api/useConfig'
import humanizeDuration from 'humanize-duration'
import i18n from 'i18next'
import { FeatureFlags } from '@/features/analytics/enums' import { FeatureFlags } from '@/features/analytics/enums'
import { NoAccessView } from './NoAccessView' import { NoAccessView } from './NoAccessView'
import { HStack, VStack } from '@/styled-system/jsx' import { HStack, VStack } from '@/styled-system/jsx'
@@ -36,6 +35,8 @@ import { Checkbox } from '@/primitives/Checkbox'
export const ScreenRecordingSidePanel = () => { export const ScreenRecordingSidePanel = () => {
const { data } = useConfig() const { data } = useConfig()
const recordingMaxDuration = useHumanizeRecordingMaxDuration()
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const recordingSnap = useSnapshot(recordingStore) const recordingSnap = useSnapshot(recordingStore)
const { t } = useTranslation('rooms', { keyPrefix: 'screenRecording' }) const { t } = useTranslation('rooms', { keyPrefix: 'screenRecording' })
@@ -175,11 +176,9 @@ export const ScreenRecordingSidePanel = () => {
{t('heading')} {t('heading')}
</H> </H>
<Text variant="body" fullWidth> <Text variant="body" fullWidth>
{data?.recording?.max_duration {recordingMaxDuration
? t('body', { ? t('body', {
max_duration: humanizeDuration(data?.recording?.max_duration, { max_duration: recordingMaxDuration,
language: i18n.language,
}),
}) })
: t('bodyWithoutMaxDuration')}{' '} : t('bodyWithoutMaxDuration')}{' '}
{data?.support?.help_article_recording && ( {data?.support?.help_article_recording && (

View File

@@ -9,6 +9,7 @@ import {
useStartRecording, useStartRecording,
useStopRecording, useStopRecording,
useHasFeatureWithoutAdminRights, useHasFeatureWithoutAdminRights,
useHumanizeRecordingMaxDuration,
} from '../index' } from '../index'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { ConnectionState, RoomEvent } from 'livekit-client' import { ConnectionState, RoomEvent } from 'livekit-client'
@@ -28,8 +29,6 @@ import posthog from 'posthog-js'
import { useSnapshot } from 'valtio/index' import { useSnapshot } from 'valtio/index'
import { Spinner } from '@/primitives/Spinner' import { Spinner } from '@/primitives/Spinner'
import { useConfig } from '@/api/useConfig' import { useConfig } from '@/api/useConfig'
import humanizeDuration from 'humanize-duration'
import i18n from 'i18next'
import { HStack, VStack } from '@/styled-system/jsx' import { HStack, VStack } from '@/styled-system/jsx'
import { Checkbox } from '@/primitives/Checkbox.tsx' import { Checkbox } from '@/primitives/Checkbox.tsx'
@@ -42,6 +41,7 @@ import { NoAccessView } from './NoAccessView'
export const TranscriptSidePanel = () => { export const TranscriptSidePanel = () => {
const { data } = useConfig() const { data } = useConfig()
const recordingMaxDuration = useHumanizeRecordingMaxDuration()
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const { t } = useTranslation('rooms', { keyPrefix: 'transcript' }) const { t } = useTranslation('rooms', { keyPrefix: 'transcript' })
@@ -203,11 +203,9 @@ export const TranscriptSidePanel = () => {
{t('heading')} {t('heading')}
</H> </H>
<Text variant="body" fullWidth> <Text variant="body" fullWidth>
{data?.recording?.max_duration {recordingMaxDuration
? t('body', { ? t('body', {
max_duration: humanizeDuration(data?.recording?.max_duration, { max_duration: recordingMaxDuration,
language: i18n.language,
}),
}) })
: t('bodyWithoutMaxDuration')}{' '} : t('bodyWithoutMaxDuration')}{' '}
{data?.support?.help_article_transcript && ( {data?.support?.help_article_transcript && (

View File

@@ -0,0 +1,16 @@
import { useMemo } from 'react'
import humanizeDuration from 'humanize-duration'
import i18n from 'i18next'
import { useConfig } from '@/api/useConfig'
export const useHumanizeRecordingMaxDuration = () => {
const { data } = useConfig()
return useMemo(() => {
if (!data?.recording?.max_duration) return
return humanizeDuration(data?.recording?.max_duration, {
language: i18n.language,
})
}, [data])
}

View File

@@ -3,6 +3,7 @@ export { useIsRecordingModeEnabled } from './hooks/useIsRecordingModeEnabled'
export { useHasRecordingAccess } from './hooks/useHasRecordingAccess' export { useHasRecordingAccess } from './hooks/useHasRecordingAccess'
export { useIsRecordingActive } from './hooks/useIsRecordingActive' export { useIsRecordingActive } from './hooks/useIsRecordingActive'
export { useHasFeatureWithoutAdminRights } from './hooks/useHasFeatureWithoutAdminRights' export { useHasFeatureWithoutAdminRights } from './hooks/useHasFeatureWithoutAdminRights'
export { useHumanizeRecordingMaxDuration } from './hooks/useHumanizeRecordingMaxDuration'
// api // api
export { useStartRecording } from './api/startRecording' export { useStartRecording } from './api/startRecording'