import { listen } from "@tauri-apps/api/event"; import React, { useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { MicrophoneIcon, TranscriptionIcon, CancelIcon, } from "../components/icons"; import "./RecordingOverlay.css"; import { commands } from "@/bindings"; import i18n, { syncLanguageFromSettings } from "@/i18n"; import { getLanguageDirection } from "@/lib/utils/rtl"; type OverlayState = "recording" | "transcribing" | "processing"; const RecordingOverlay: React.FC = () => { const { t } = useTranslation(); const [isVisible, setIsVisible] = useState(false); const [state, setState] = useState("recording"); const [levels, setLevels] = useState(Array(16).fill(0)); const smoothedLevelsRef = useRef(Array(16).fill(0)); const direction = getLanguageDirection(i18n.language); useEffect(() => { const setupEventListeners = async () => { // Listen for show-overlay event from Rust const unlistenShow = await listen("show-overlay", async (event) => { // Sync language from settings each time overlay is shown await syncLanguageFromSettings(); const overlayState = event.payload as OverlayState; setState(overlayState); setIsVisible(true); }); // Listen for hide-overlay event from Rust const unlistenHide = await listen("hide-overlay", () => { setIsVisible(false); }); // Listen for mic-level updates const unlistenLevel = await listen("mic-level", (event) => { const newLevels = event.payload as number[]; // Apply smoothing to reduce jitter const smoothed = smoothedLevelsRef.current.map((prev, i) => { const target = newLevels[i] || 0; return prev * 0.7 + target * 0.3; // Smooth transition }); smoothedLevelsRef.current = smoothed; setLevels(smoothed.slice(0, 9)); }); // Cleanup function return () => { unlistenShow(); unlistenHide(); unlistenLevel(); }; }; setupEventListeners(); }, []); const getIcon = () => { if (state === "recording") { return ; } else { return ; } }; return (
{getIcon()}
{state === "recording" && (
{levels.map((v, i) => (
))}
)} {state === "transcribing" && (
{t("overlay.transcribing")}
)} {state === "processing" && (
{t("overlay.processing")}
)}
{state === "recording" && (
{ commands.cancelOperation(); }} >
)}
); }; export default RecordingOverlay;