import { useCallback, useEffect, useRef, useState } from "react"; import type { SttState } from "../../hooks/useSTT"; import * as commands from "../../lib/tauri-commands"; interface Props { state: SttState; error: string | null; onToggle: () => Promise; onCancel: () => Promise; } export default function SttButton({ state, error, onToggle, onCancel }: Props) { const [elapsed, setElapsed] = useState(0); const [hovered, setHovered] = useState(false); const timerRef = useRef | null>(null); // Track recording duration useEffect(() => { if (state === "recording") { setElapsed(0); timerRef.current = setInterval(() => setElapsed((e) => e + 1), 1000); } else { if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; } } return () => { if (timerRef.current) clearInterval(timerRef.current); }; }, [state]); const handleClick = useCallback(async () => { // Auto-start STT container if not running if (state === "idle") { try { const status = await commands.getSttStatus(); if (!status.running) { await commands.startStt(); } } catch { // Container start failed, toggle will still attempt transcription } } await onToggle(); }, [state, onToggle]); const handleContextMenu = useCallback( (e: React.MouseEvent) => { e.preventDefault(); if (state === "recording") { onCancel(); } }, [state, onCancel], ); const formatTime = (seconds: number) => { const m = Math.floor(seconds / 60); const s = seconds % 60; return `${m}:${s.toString().padStart(2, "0")}`; }; return (
{hovered && state !== "recording" && (
{state === "transcribing" ? "Transcribing..." : ( <>Speech to text Ctrl+Shift+M )}
)}
{state === "recording" && ( {formatTime(elapsed)} )} {state === "error" && error && ( {error} )}
); }