From 9fe908f142830da3c0afe9486411bd089e31ef09 Mon Sep 17 00:00:00 2001 From: BerthalonLucas Date: Thu, 8 Jan 2026 01:14:09 +0100 Subject: [PATCH 1/4] feat(overlay): improve recording visualization with symmetric bars - Add symmetric mirror effect for Apple-like audio visualization - Adjust FFT frequency range (150-2500Hz) to better capture voice - Fix intermittent GPU compositing issues with transparent backgrounds - Fix unused import and mut warnings --- src-tauri/src/audio_toolkit/audio/recorder.rs | 6 ++-- src-tauri/src/lib.rs | 2 +- src-tauri/src/shortcut.rs | 2 +- src/overlay/RecordingOverlay.css | 31 +++++++++++++------ src/overlay/RecordingOverlay.tsx | 11 ++++--- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src-tauri/src/audio_toolkit/audio/recorder.rs b/src-tauri/src/audio_toolkit/audio/recorder.rs index c3f23adbb..d516d6f1d 100644 --- a/src-tauri/src/audio_toolkit/audio/recorder.rs +++ b/src-tauri/src/audio_toolkit/audio/recorder.rs @@ -256,14 +256,14 @@ fn run_consumer( let mut recording = false; // ---------- spectrum visualisation setup ---------------------------- // - const BUCKETS: usize = 16; + const BUCKETS: usize = 25; const WINDOW_SIZE: usize = 512; let mut visualizer = AudioVisualiser::new( in_sample_rate, WINDOW_SIZE, BUCKETS, - 400.0, // vocal_min_hz - 4000.0, // vocal_max_hz + 150.0, // vocal_min_hz + 2500.0, // vocal_max_hz ); fn handle_frame( diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6472167d6..a7c96932d 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -320,7 +320,7 @@ pub fn run() { ) .expect("Failed to export typescript bindings"); - let mut builder = tauri::Builder::default().plugin( + let builder = tauri::Builder::default().plugin( LogBuilder::new() .level(log::LevelFilter::Trace) // Set to most verbose level globally .max_file_size(500_000) diff --git a/src-tauri/src/shortcut.rs b/src-tauri/src/shortcut.rs index f983b0b91..8458f4286 100644 --- a/src-tauri/src/shortcut.rs +++ b/src-tauri/src/shortcut.rs @@ -11,7 +11,7 @@ use crate::managers::audio::AudioRecordingManager; use crate::settings::ShortcutBinding; use crate::settings::{ self, get_settings, ClipboardHandling, LLMPrompt, OverlayPosition, PasteMethod, SoundTheme, - APPLE_INTELLIGENCE_DEFAULT_MODEL_ID, APPLE_INTELLIGENCE_PROVIDER_ID, + APPLE_INTELLIGENCE_PROVIDER_ID, }; use crate::tray; use crate::ManagedToggleState; diff --git a/src/overlay/RecordingOverlay.css b/src/overlay/RecordingOverlay.css index e11b509c3..996096971 100644 --- a/src/overlay/RecordingOverlay.css +++ b/src/overlay/RecordingOverlay.css @@ -1,15 +1,20 @@ .recording-overlay { - height: 36px; + height: 40px; width: 172px; display: grid; grid-template-columns: auto 1fr auto; align-items: center; padding: 6px; background: #000000cc; - border-radius: 18px; + border-radius: 22px; opacity: 0; transition: opacity 300ms ease-out; box-sizing: border-box; + transform: translateZ(0); + -webkit-transform: translateZ(0); + backface-visibility: hidden; + -webkit-backface-visibility: hidden; + isolation: isolate; } .overlay-left { @@ -31,21 +36,29 @@ .bars-container { display: flex; - align-items: end; + align-items: center; justify-content: center; - gap: 3px; + gap: 2px; + padding-top: 2px; padding-bottom: 0px; height: 24px; - overflow: hidden; + background: transparent; + isolation: auto; + filter: none; + contain: layout style; } .bar { - width: 6px; + width: 2px; background: #ffe5ee; - max-height: 20px; - border-radius: 2px; - transition: height 80ms linear; + max-height: 50px; + border-radius: 10px; min-height: 4px; + transition: height 80ms linear; + transform: translateZ(0); + -webkit-transform: translateZ(0); + backface-visibility: hidden; + -webkit-backface-visibility: hidden; } .recording-overlay.fade-in { diff --git a/src/overlay/RecordingOverlay.tsx b/src/overlay/RecordingOverlay.tsx index 0270491f4..bec85f03f 100644 --- a/src/overlay/RecordingOverlay.tsx +++ b/src/overlay/RecordingOverlay.tsx @@ -46,7 +46,11 @@ const RecordingOverlay: React.FC = () => { }); smoothedLevelsRef.current = smoothed; - setLevels(smoothed.slice(0, 9)); + + // Symmetric mirror effect for Apple-like visualization + const half = smoothed.slice(0, 12); + const symmetricLevels = [...half.slice().reverse(), ...half]; + setLevels(symmetricLevels); }); // Cleanup function @@ -80,9 +84,8 @@ const RecordingOverlay: React.FC = () => { key={i} className="bar" style={{ - height: `${Math.min(20, 4 + Math.pow(v, 0.7) * 16)}px`, // Cap at 20px max height - transition: "height 60ms ease-out, opacity 120ms ease-out", - opacity: Math.max(0.2, v * 1.7), // Minimum opacity for visibility + height: `${Math.min(50, 4 + Math.pow(v, 0.7) * 32)}px`, + opacity: Math.max(0.3, Math.min(1, v * 1.5)), }} /> ))} From 5b65aa351a2746208d91c97c85c155deaeed9459 Mon Sep 17 00:00:00 2001 From: BerthalonLucas Date: Thu, 8 Jan 2026 20:01:12 +0100 Subject: [PATCH 2/4] fix(overlay): restore transition in CSS instead of inline --- src/overlay/RecordingOverlay.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/overlay/RecordingOverlay.css b/src/overlay/RecordingOverlay.css index 996096971..62b89d1f7 100644 --- a/src/overlay/RecordingOverlay.css +++ b/src/overlay/RecordingOverlay.css @@ -39,7 +39,7 @@ align-items: center; justify-content: center; gap: 2px; - padding-top: 2px; + padding-top: 0px; padding-bottom: 0px; height: 24px; background: transparent; @@ -54,7 +54,7 @@ max-height: 50px; border-radius: 10px; min-height: 4px; - transition: height 80ms linear; + transition: height 60ms ease-out, opacity 120ms ease-out; transform: translateZ(0); -webkit-transform: translateZ(0); backface-visibility: hidden; From 6a23f24074173596651f1dcf11ea0268b530fee2 Mon Sep 17 00:00:00 2001 From: BerthalonLucas Date: Fri, 9 Jan 2026 00:30:45 +0100 Subject: [PATCH 3/4] fix(overlay): clean up CSS and adjust bar visualization formula - Remove GPU compositing hacks (transform, backface-visibility, isolation) that were causing transparency issues on some systems - Simplify bars-container styles - Adjust bar height/opacity formula for better responsiveness - Update array size to match 25 buckets from backend --- src/overlay/RecordingOverlay.css | 20 +++----------------- src/overlay/RecordingOverlay.tsx | 8 ++++---- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/overlay/RecordingOverlay.css b/src/overlay/RecordingOverlay.css index 62b89d1f7..c711e269c 100644 --- a/src/overlay/RecordingOverlay.css +++ b/src/overlay/RecordingOverlay.css @@ -10,11 +10,6 @@ opacity: 0; transition: opacity 300ms ease-out; box-sizing: border-box; - transform: translateZ(0); - -webkit-transform: translateZ(0); - backface-visibility: hidden; - -webkit-backface-visibility: hidden; - isolation: isolate; } .overlay-left { @@ -39,26 +34,17 @@ align-items: center; justify-content: center; gap: 2px; - padding-top: 0px; - padding-bottom: 0px; height: 24px; - background: transparent; - isolation: auto; - filter: none; - contain: layout style; + background: transparent !important; } .bar { width: 2px; background: #ffe5ee; - max-height: 50px; + max-height: 24px; border-radius: 10px; - min-height: 4px; transition: height 60ms ease-out, opacity 120ms ease-out; - transform: translateZ(0); - -webkit-transform: translateZ(0); - backface-visibility: hidden; - -webkit-backface-visibility: hidden; + min-height: 4px; } .recording-overlay.fade-in { diff --git a/src/overlay/RecordingOverlay.tsx b/src/overlay/RecordingOverlay.tsx index bec85f03f..8533422d8 100644 --- a/src/overlay/RecordingOverlay.tsx +++ b/src/overlay/RecordingOverlay.tsx @@ -16,8 +16,8 @@ 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 [levels, setLevels] = useState(Array(25).fill(0)); + const smoothedLevelsRef = useRef(Array(25).fill(0)); useEffect(() => { const setupEventListeners = async () => { @@ -84,8 +84,8 @@ const RecordingOverlay: React.FC = () => { key={i} className="bar" style={{ - height: `${Math.min(50, 4 + Math.pow(v, 0.7) * 32)}px`, - opacity: Math.max(0.3, Math.min(1, v * 1.5)), + height: `${Math.min(24, 4 + Math.pow(v * 0.8, 0.6) * 22)}px`, + opacity: Math.max(0.4, Math.min(1, v * 3)), }} /> ))} From 6878f34f897b8259926cfb095df8956c719425fe Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Sat, 10 Jan 2026 11:41:26 +0800 Subject: [PATCH 4/4] fix build on macos --- src-tauri/src/lib.rs | 2 +- src-tauri/src/shortcut.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a7c96932d..6472167d6 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -320,7 +320,7 @@ pub fn run() { ) .expect("Failed to export typescript bindings"); - let builder = tauri::Builder::default().plugin( + let mut builder = tauri::Builder::default().plugin( LogBuilder::new() .level(log::LevelFilter::Trace) // Set to most verbose level globally .max_file_size(500_000) diff --git a/src-tauri/src/shortcut.rs b/src-tauri/src/shortcut.rs index 8458f4286..f983b0b91 100644 --- a/src-tauri/src/shortcut.rs +++ b/src-tauri/src/shortcut.rs @@ -11,7 +11,7 @@ use crate::managers::audio::AudioRecordingManager; use crate::settings::ShortcutBinding; use crate::settings::{ self, get_settings, ClipboardHandling, LLMPrompt, OverlayPosition, PasteMethod, SoundTheme, - APPLE_INTELLIGENCE_PROVIDER_ID, + APPLE_INTELLIGENCE_DEFAULT_MODEL_ID, APPLE_INTELLIGENCE_PROVIDER_ID, }; use crate::tray; use crate::ManagedToggleState;