import { useState, useEffect } from "react"; import { useSettings } from "../../hooks/useSettings"; import { getSttStatus, startStt, stopStt, pullSttImage, buildSttImage } from "../../lib/tauri-commands"; import { listen } from "@tauri-apps/api/event"; import type { SttStatus } from "../../lib/types"; import Tooltip from "../ui/Tooltip"; export default function SttSettings() { const { appSettings, saveSettings } = useSettings(); const [status, setStatus] = useState(null); const [loading, setLoading] = useState(false); const [pulling, setPulling] = useState(false); const [building, setBuilding] = useState(false); const [buildLog, setBuildLog] = useState(null); const [model, setModel] = useState(appSettings?.stt?.model ?? "tiny"); const [port, setPort] = useState(String(appSettings?.stt?.port ?? 9876)); const [language, setLanguage] = useState(appSettings?.stt?.language ?? ""); useEffect(() => { setModel(appSettings?.stt?.model ?? "tiny"); setPort(String(appSettings?.stt?.port ?? 9876)); setLanguage(appSettings?.stt?.language ?? ""); }, [appSettings?.stt?.model, appSettings?.stt?.port, appSettings?.stt?.language]); useEffect(() => { refreshStatus(); }, []); const refreshStatus = () => { getSttStatus().then(setStatus).catch(console.error); }; const handleToggleEnabled = async () => { if (!appSettings) return; const newEnabled = !appSettings.stt.enabled; await saveSettings({ ...appSettings, stt: { ...appSettings.stt, enabled: newEnabled }, }); }; const handleSaveModel = async () => { if (!appSettings) return; await saveSettings({ ...appSettings, stt: { ...appSettings.stt, model }, }); }; const handleSavePort = async () => { if (!appSettings) return; const portNum = parseInt(port, 10); if (isNaN(portNum) || portNum < 1 || portNum > 65535) return; await saveSettings({ ...appSettings, stt: { ...appSettings.stt, port: portNum }, }); }; const handleSaveLanguage = async () => { if (!appSettings) return; await saveSettings({ ...appSettings, stt: { ...appSettings.stt, language: language || null }, }); }; const handleStartStop = async () => { setLoading(true); try { if (status?.running) { await stopStt(); } else { await startStt(); } refreshStatus(); } catch (e) { console.error("STT toggle failed:", e); } finally { setLoading(false); } }; const handlePull = async () => { setPulling(true); setBuildLog(null); const unlisten = await listen("stt-pull-progress", (event) => { setBuildLog(event.payload); }); try { await pullSttImage(); refreshStatus(); } catch (e) { console.error("STT image pull failed:", e); setBuildLog(`Error: ${e}`); } finally { setPulling(false); unlisten(); } }; const handleBuild = async () => { setBuilding(true); setBuildLog(null); const unlisten = await listen("stt-build-progress", (event) => { setBuildLog(event.payload); }); try { await buildSttImage(); refreshStatus(); } catch (e) { console.error("STT image build failed:", e); setBuildLog(`Error: ${e}`); } finally { setBuilding(false); unlisten(); } }; return (

Click the mic button in the terminal to dictate text via speech recognition.

{/* Enable toggle */}
{appSettings?.stt?.enabled ? "Enabled" : "Disabled"}
{appSettings?.stt?.enabled && ( <> {/* Model selector */}
{/* Port */}
setPort(e.target.value)} onBlur={handleSavePort} min={1} max={65535} className="w-full px-2 py-1 text-sm bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]" />
{/* Language */}
setLanguage(e.target.value)} onBlur={handleSaveLanguage} placeholder="Auto-detect" className="w-full px-2 py-1 text-sm bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]" />
{/* Container status + controls */}
{status?.image_exists ? status.running ? `Running (port ${status.port}, model: ${status.model})` : status.container_exists ? "Stopped" : "Image ready" : "No image"} {status?.image_exists && ( )}
{/* Image actions */}
{buildLog && (
                  {buildLog}
                
)}
)}
); }