♻️(frontend) generalize recording state badge for all recording types
Extend recording state badge component to work with all types of recordings instead of just transcripts. Create flexible implementation that supports screen recordings and future recording formats while maintaining consistent visual indicators.
This commit is contained in:
committed by
aleb_the_flash
parent
f596aae1e8
commit
9734df9d5d
@@ -8,22 +8,22 @@ import { Text } from '@/primitives'
|
||||
import { RemoteParticipant, RoomEvent } from 'livekit-client'
|
||||
import { decodeNotificationDataReceived } from '@/features/notifications/utils'
|
||||
import { NotificationType } from '@/features/notifications/NotificationType'
|
||||
import { TranscriptionStatus, transcriptionStore } from '@/stores/transcription'
|
||||
import { RecordingStatus, recordingStore } from '@/stores/recording'
|
||||
|
||||
export const TranscriptStateToast = () => {
|
||||
export const RecordingStateBadge = () => {
|
||||
const { t } = useTranslation('rooms', {
|
||||
keyPrefix: 'recordingBadge.transcript',
|
||||
keyPrefix: 'recordingBadge',
|
||||
})
|
||||
const room = useRoomContext()
|
||||
|
||||
const transcriptionSnap = useSnapshot(transcriptionStore)
|
||||
const recordingSnap = useSnapshot(recordingStore)
|
||||
|
||||
useEffect(() => {
|
||||
if (room.isRecording) {
|
||||
transcriptionStore.status = TranscriptionStatus.STARTED
|
||||
if (room.isRecording && recordingSnap.status == RecordingStatus.STOPPED) {
|
||||
recordingStore.status = RecordingStatus.ANY_STARTED
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
}, [room.isRecording])
|
||||
|
||||
useEffect(() => {
|
||||
const handleDataReceived = (
|
||||
@@ -36,10 +36,16 @@ export const TranscriptStateToast = () => {
|
||||
|
||||
switch (notification.type) {
|
||||
case NotificationType.TranscriptionStarted:
|
||||
transcriptionStore.status = TranscriptionStatus.STARTING
|
||||
recordingStore.status = RecordingStatus.TRANSCRIPT_STARTING
|
||||
break
|
||||
case NotificationType.TranscriptionStopped:
|
||||
transcriptionStore.status = TranscriptionStatus.STOPPING
|
||||
recordingStore.status = RecordingStatus.TRANSCRIPT_STOPPING
|
||||
break
|
||||
case NotificationType.ScreenRecordingStarted:
|
||||
recordingStore.status = RecordingStatus.SCREEN_RECORDING_STARTING
|
||||
break
|
||||
case NotificationType.ScreenRecordingStopped:
|
||||
recordingStore.status = RecordingStatus.SCREEN_RECORDING_STOPPING
|
||||
break
|
||||
default:
|
||||
return
|
||||
@@ -47,9 +53,17 @@ export const TranscriptStateToast = () => {
|
||||
}
|
||||
|
||||
const handleRecordingStatusChanged = (status: boolean) => {
|
||||
transcriptionStore.status = status
|
||||
? TranscriptionStatus.STARTED
|
||||
: TranscriptionStatus.STOPPED
|
||||
if (!status) {
|
||||
recordingStore.status = RecordingStatus.STOPPED
|
||||
} else if (recordingSnap.status == RecordingStatus.TRANSCRIPT_STARTING) {
|
||||
recordingStore.status = RecordingStatus.TRANSCRIPT_STARTED
|
||||
} else if (
|
||||
recordingSnap.status == RecordingStatus.SCREEN_RECORDING_STARTING
|
||||
) {
|
||||
recordingStore.status = RecordingStatus.SCREEN_RECORDING_STARTED
|
||||
} else {
|
||||
recordingStore.status = RecordingStatus.ANY_STARTED
|
||||
}
|
||||
}
|
||||
|
||||
room.on(RoomEvent.DataReceived, handleDataReceived)
|
||||
@@ -59,20 +73,30 @@ export const TranscriptStateToast = () => {
|
||||
room.off(RoomEvent.DataReceived, handleDataReceived)
|
||||
room.off(RoomEvent.RecordingStatusChanged, handleRecordingStatusChanged)
|
||||
}
|
||||
}, [room])
|
||||
}, [room, recordingSnap])
|
||||
|
||||
const key = useMemo(() => {
|
||||
switch (transcriptionSnap.status) {
|
||||
case TranscriptionStatus.STOPPING:
|
||||
return 'stopping'
|
||||
case TranscriptionStatus.STARTING:
|
||||
return 'starting'
|
||||
switch (recordingSnap.status) {
|
||||
case RecordingStatus.TRANSCRIPT_STARTED:
|
||||
return 'transcript.started'
|
||||
case RecordingStatus.TRANSCRIPT_STOPPING:
|
||||
return 'transcript.stopping'
|
||||
case RecordingStatus.TRANSCRIPT_STARTING:
|
||||
return 'transcript.starting'
|
||||
case RecordingStatus.SCREEN_RECORDING_STARTED:
|
||||
return 'screenRecording.started'
|
||||
case RecordingStatus.SCREEN_RECORDING_STOPPING:
|
||||
return 'screenRecording.stopping'
|
||||
case RecordingStatus.SCREEN_RECORDING_STARTING:
|
||||
return 'screenRecording.starting'
|
||||
case RecordingStatus.ANY_STARTED:
|
||||
return 'any.started'
|
||||
default:
|
||||
return 'started'
|
||||
return
|
||||
}
|
||||
}, [transcriptionSnap])
|
||||
}, [recordingSnap])
|
||||
|
||||
if (transcriptionSnap.status == TranscriptionStatus.STOPPED) return
|
||||
if (!key) return
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -15,10 +15,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { NotificationPayload } from '@/features/notifications/NotificationPayload'
|
||||
import { NotificationType } from '@/features/notifications/NotificationType'
|
||||
import { useSnapshot } from 'valtio/index'
|
||||
import {
|
||||
TranscriptionStatus,
|
||||
transcriptionStore,
|
||||
} from '@/stores/transcription.ts'
|
||||
import { RecordingStatus, recordingStore } from '@/stores/recording'
|
||||
import { useHasTranscriptAccess } from '../hooks/useHasTranscriptAccess'
|
||||
import {
|
||||
BETA_USERS_FORM_URL,
|
||||
@@ -35,7 +32,7 @@ export const Transcript = () => {
|
||||
const { mutateAsync: startRecordingRoom } = useStartRecording()
|
||||
const { mutateAsync: stopRecordingRoom } = useStopRecording()
|
||||
|
||||
const transcriptionSnap = useSnapshot(transcriptionStore)
|
||||
const recordingSnap = useSnapshot(recordingStore)
|
||||
|
||||
const room = useRoomContext()
|
||||
|
||||
@@ -70,11 +67,11 @@ export const Transcript = () => {
|
||||
if (room.isRecording) {
|
||||
await stopRecordingRoom({ id: roomId })
|
||||
await notifyParticipant(NotificationType.TranscriptionStopped)
|
||||
transcriptionStore.status = TranscriptionStatus.STOPPING
|
||||
recordingStore.status = RecordingStatus.TRANSCRIPT_STOPPING
|
||||
} else {
|
||||
await startRecordingRoom({ id: roomId, mode: RecordingMode.Transcript })
|
||||
await notifyParticipant(NotificationType.TranscriptionStarted)
|
||||
transcriptionStore.status = TranscriptionStatus.STARTING
|
||||
recordingStore.status = RecordingStatus.TRANSCRIPT_STARTING
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to handle transcript:', error)
|
||||
@@ -85,9 +82,9 @@ export const Transcript = () => {
|
||||
const isDisabled = useMemo(
|
||||
() =>
|
||||
isLoading ||
|
||||
transcriptionSnap.status === TranscriptionStatus.STARTING ||
|
||||
transcriptionSnap.status === TranscriptionStatus.STOPPING,
|
||||
[isLoading, transcriptionSnap]
|
||||
recordingSnap.status === RecordingStatus.TRANSCRIPT_STARTING ||
|
||||
recordingSnap.status === RecordingStatus.TRANSCRIPT_STOPPING,
|
||||
[isLoading, recordingSnap]
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,7 +28,7 @@ import { FocusLayout } from '../components/FocusLayout'
|
||||
import { ParticipantTile } from '../components/ParticipantTile'
|
||||
import { SidePanel } from '../components/SidePanel'
|
||||
import { useSidePanel } from '../hooks/useSidePanel'
|
||||
import { TranscriptStateToast } from '../components/TranscriptStateToast'
|
||||
import { RecordingStateBadge } from '../components/RecordingStateBadge'
|
||||
import { ScreenShareErrorModal } from '../components/ScreenShareErrorModal'
|
||||
|
||||
const LayoutWrapper = styled(
|
||||
@@ -231,7 +231,7 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
|
||||
)}
|
||||
<RoomAudioRenderer />
|
||||
<ConnectionStateToast />
|
||||
<TranscriptStateToast />
|
||||
<RecordingStateBadge />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -297,6 +297,14 @@
|
||||
"started": "",
|
||||
"starting": "",
|
||||
"stopping": ""
|
||||
},
|
||||
"screenRecording": {
|
||||
"started": "",
|
||||
"starting": "",
|
||||
"stopping": ""
|
||||
},
|
||||
"any": {
|
||||
"started": ""
|
||||
}
|
||||
},
|
||||
"participantTileFocus": {
|
||||
|
||||
@@ -296,6 +296,14 @@
|
||||
"started": "Transcribing",
|
||||
"starting": "Transcription starting",
|
||||
"stopping": "Transcription stopping"
|
||||
},
|
||||
"screenRecording": {
|
||||
"started": "Recording in progress",
|
||||
"starting": "Starting recording",
|
||||
"stopping": "Stopping recording"
|
||||
},
|
||||
"any": {
|
||||
"started": "Recording in progress"
|
||||
}
|
||||
},
|
||||
"participantTileFocus": {
|
||||
|
||||
@@ -296,6 +296,14 @@
|
||||
"started": "Transcription en cours",
|
||||
"starting": "Démarrage de la transcription",
|
||||
"stopping": "Arrêt de la transcription"
|
||||
},
|
||||
"screenRecording": {
|
||||
"started": "Enregistrement en cours",
|
||||
"starting": "Démarrage de l'enregistrement",
|
||||
"stopping": "Arrêt de l'enregistrement"
|
||||
},
|
||||
"any": {
|
||||
"started": "Enregistrement en cours"
|
||||
}
|
||||
},
|
||||
"participantTileFocus": {
|
||||
|
||||
@@ -296,6 +296,14 @@
|
||||
"started": "Transcriptie bezig",
|
||||
"starting": "Transcriptie begint",
|
||||
"stopping": "Transcriptie stopt"
|
||||
},
|
||||
"screenRecording": {
|
||||
"started": "Opname bezig",
|
||||
"starting": "Opname starten",
|
||||
"stopping": "Opname stoppen"
|
||||
},
|
||||
"any": {
|
||||
"started": "Opname bezig"
|
||||
}
|
||||
},
|
||||
"participantTileFocus": {
|
||||
|
||||
20
src/frontend/src/stores/recording.ts
Normal file
20
src/frontend/src/stores/recording.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { proxy } from 'valtio'
|
||||
|
||||
export enum RecordingStatus {
|
||||
TRANSCRIPT_STARTING,
|
||||
TRANSCRIPT_STARTED,
|
||||
TRANSCRIPT_STOPPING,
|
||||
STOPPED,
|
||||
SCREEN_RECORDING_STARTING,
|
||||
SCREEN_RECORDING_STARTED,
|
||||
SCREEN_RECORDING_STOPPING,
|
||||
ANY_STARTED,
|
||||
}
|
||||
|
||||
type State = {
|
||||
status: RecordingStatus
|
||||
}
|
||||
|
||||
export const recordingStore = proxy<State>({
|
||||
status: RecordingStatus.STOPPED,
|
||||
})
|
||||
@@ -1,16 +0,0 @@
|
||||
import { proxy } from 'valtio'
|
||||
|
||||
export enum TranscriptionStatus {
|
||||
STARTING,
|
||||
STARTED,
|
||||
STOPPING,
|
||||
STOPPED,
|
||||
}
|
||||
|
||||
type State = {
|
||||
status: TranscriptionStatus
|
||||
}
|
||||
|
||||
export const transcriptionStore = proxy<State>({
|
||||
status: TranscriptionStatus.STOPPED,
|
||||
})
|
||||
Reference in New Issue
Block a user