diff --git a/js/desktop/src/features/compose/recording-overlay.tsx b/js/desktop/src/features/compose/recording-overlay.tsx index 4527241..bdb1644 100644 --- a/js/desktop/src/features/compose/recording-overlay.tsx +++ b/js/desktop/src/features/compose/recording-overlay.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState } from 'react'; +import { toast } from 'sonner'; import { Paperclip } from 'lucide-react'; import type { RecordingMode } from '@/stores/media-settings-store'; import { CenteredWaveform } from '@/components/audio/centered-waveform'; @@ -7,10 +8,7 @@ import { useObjectUrl } from '@/hooks/use-object-url'; import { AttachmentStrip } from '@/features/compose/attachment-strip'; import type { PendingAttachment } from '@/features/compose/attachment-strip'; import { cn } from '@/lib/utils'; -import { - RECORDING_MAX_DURATION_SECONDS, - RECORDING_WARNING_SECONDS, -} from '@/lib/constants'; +import { RECORDING_MAX_DURATION_SECONDS } from '@/lib/constants'; import { Button } from '@/components/ui/button'; import { KeyHint } from '@/components/key-hint'; import { useComposeIntentStore } from '@/stores/compose-intent-store'; @@ -38,41 +36,32 @@ interface RecordingOverlayProps { objectFit?: 'cover' | 'contain'; } -const WARNING_AT_SECONDS = - RECORDING_MAX_DURATION_SECONDS - RECORDING_WARNING_SECONDS; - -/** - * Tracks elapsed recording time and drives the time-limit UI. Keeps the - * recorder itself unaware of limits: when the cap is reached it dispatches the - * standard `stop` intent (the same path as releasing the ` key), which finishes - * the recording into the review step. - */ function useRecordingCountdown(active: boolean) { const [elapsed, setElapsed] = useState(0); - const requestIntent = useComposeIntentStore((s) => s.request); useEffect(() => { if (!active) return; + let toastSent = false; const start = Date.now(); - let stopped = false; - // Tick faster than 1s so the auto-stop lands within ~250ms of the cap, but - // only re-render when the whole-second value actually changes. const interval = setInterval(() => { const seconds = Math.floor((Date.now() - start) / 1000); - setElapsed((prev) => (prev === seconds ? prev : seconds)); - if (seconds >= RECORDING_MAX_DURATION_SECONDS && !stopped) { - stopped = true; - requestIntent('stop'); + setElapsed(seconds); + + if (seconds >= RECORDING_MAX_DURATION_SECONDS && !toastSent) { + toast.warning( + 'That is a long recording, cancel and re-record with your distilled thoughts', + ); + toastSent = true; } - }, 250); + }, 1000); return () => { clearInterval(interval); setElapsed(0); }; - }, [active, requestIntent]); + }, [active]); - return { elapsed, isWarning: elapsed >= WARNING_AT_SECONDS }; + return { elapsed, isWarning: elapsed >= RECORDING_MAX_DURATION_SECONDS }; } function RecordingTimer({ diff --git a/js/desktop/src/lib/constants.ts b/js/desktop/src/lib/constants.ts index e888941..8df2a15 100644 --- a/js/desktop/src/lib/constants.ts +++ b/js/desktop/src/lib/constants.ts @@ -4,12 +4,9 @@ export const MAX_ATTACHMENT_SIZE_BYTES = 25 * 1024 * 1024; /** Maximum number of file attachments per particle. */ export const MAX_ATTACHMENTS = 10; -/** Maximum duration for a media (audio/video) recording, in seconds. */ +/** Maximum recommended duration for a media (audio/video) recording, in seconds. */ export const RECORDING_MAX_DURATION_SECONDS = 60; -/** When this many seconds or fewer remain, show the red warning state. */ -export const RECORDING_WARNING_SECONDS = 10; - export const SUPPORT_EMAIL = 'team@flowylabs.ai'; export const PRIVACY_URL = 'https://flowylabs.ai/llink/privacy';