Skip to content

Conversation

@richiemcilroy
Copy link
Member

@richiemcilroy richiemcilroy commented Jan 2, 2026

Greptile Summary

This PR implements several bug fixes and improvements across the desktop application:

  • Active Word Highlight Toggle: Added a new setting to enable/disable word-by-word caption highlighting. When disabled, captions render with full highlight color instead of progressive word timing. This addresses accuracy issues with word timing in the initial caption implementation.

  • Windows Audio Playback Improvements: Implemented a pre-rendered audio buffer system specifically for Windows to address audio-video sync issues. The entire audio is rendered upfront and stored in memory, with different sync thresholds and buffer sizes compared to other platforms.

  • Screenshot Editor Enhancements:

    • Added support for loading original.png from .cap directories with fallback to base path
    • Implemented pan/drag functionality with both left-click and middle-click support
    • Added automatic cleanup of masks smaller than 5px
    • Simplified crop logic and removed aspect ratio constraints
    • Conditionally hide styling controls when using default white background
  • Default Background Change: Changed default project background from wallpaper to solid white color

  • Logging Cleanup: Removed excessive debug and trace logging from rendering, decoding, and background layers

Issues Found:

  • Race condition in screenshot editor image loading where hasReceivedWebSocketFrame flag is never mutated
  • Event listener cleanup pattern in Preview.tsx that could cause listeners to not be re-added on subsequent drags

Confidence Score: 3/5

  • This PR contains two logic bugs that should be fixed before merging, though they may not cause critical failures in all scenarios
  • The Windows audio pre-rendering approach is a significant architectural change that could have memory implications for long recordings. The race condition in screenshot loading could cause WebSocket frames to be overwritten by fallback images, and the event listener pattern in Preview.tsx has a subtle bug with cleanup. However, most changes are straightforward (logging cleanup, UI toggles, default values).
  • Pay close attention to apps/desktop/src/routes/screenshot-editor/context.tsx and apps/desktop/src/routes/screenshot-editor/Preview.tsx for the identified logic bugs, and crates/editor/src/audio.rs and crates/editor/src/playback.rs for the Windows audio memory usage

Important Files Changed

Filename Overview
crates/editor/src/audio.rs Added Windows-specific pre-rendered audio buffer system with larger buffer sizes and platform-specific playback sample counts; adds set_playhead_smooth method and chunked rendering for Windows
crates/editor/src/playback.rs Implemented Windows-specific audio playback strategy using pre-rendered buffers with fixed latency and different sync thresholds; added fallback mechanism for better audio-video synchronization on Windows
apps/desktop/src/routes/screenshot-editor/context.tsx Added original image size tracking and fallback loading for .cap directories with original.png file support; improved image loading logic with better error handling
apps/desktop/src/routes/screenshot-editor/Preview.tsx Removed crop overlay rendering and aspect ratio logic; added pan/drag functionality with middle mouse button support and improved canvas interaction controls
crates/project/src/configuration.rs Changed default background from wallpaper to solid white color; added active_word_highlight field to CaptionSettings with default value of false

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as Desktop UI (SolidJS)
    participant Tauri as Tauri Backend (Rust)
    participant Audio as Audio System
    participant Render as Rendering Engine
    participant Caption as Caption System

    Note over User,Caption: Active Word Highlight Feature
    User->>UI: Toggle "Active Word Highlight"
    UI->>Tauri: saveCaptions with activeWordHighlight setting
    Tauri->>Tauri: Serialize setting to JSON
    Tauri->>Render: Update caption settings
    Render->>Caption: Check active_word_highlight flag
    alt active_word_highlight enabled
        Caption->>Caption: Render word-by-word with timing
    else active_word_highlight disabled
        Caption->>Caption: Render full text with highlight color
    end

    Note over User,Caption: Screenshot Editor Improvements
    User->>UI: Open screenshot in .cap directory
    UI->>UI: Check if path ends with .cap
    UI->>UI: Try loading original.png
    alt original.png exists
        UI->>UI: Load original.png
    else fallback needed
        UI->>UI: Load from base path
    end
    UI->>UI: Set originalImageSize
    User->>UI: Pan/drag canvas
    UI->>UI: Update pan state with mouse events

    Note over User,Caption: Windows Audio Playback
    User->>Tauri: Start video playback
    Tauri->>Audio: Initialize audio with duration
    alt Windows platform
        Audio->>Audio: Pre-render entire audio buffer
        Audio->>Audio: Create PrerenderedAudioBuffer
        Audio->>Audio: Render all segments upfront
        Audio->>Audio: Store samples in memory
        loop Audio callback
            Audio->>Audio: Copy from pre-rendered buffer
            Audio->>Audio: Check video playhead sync
            alt Jump > 0.5s (hard seek)
                Audio->>Audio: set_playhead (clear buffer)
            else Drift > 0.2s
                Audio->>Audio: set_playhead_smooth (keep buffer)
            end
        end
    else Other platforms
        loop Audio callback
            Audio->>Audio: Render chunks on-demand
            Audio->>Audio: Dynamic latency correction
        end
    end
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

20 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +156 to +164
createEffect(() => {
if (isDragging()) {
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseup", handleMouseUp);
}
onCleanup(() => {
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseup", handleMouseUp);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: event listeners added conditionally but removed unconditionally in cleanup, causing listeners to remain attached after dragging stops

when isDragging() becomes false, cleanup runs and removes listeners, but they were only added when dragging was true, so on subsequent drags the effect runs again but doesn't re-add listeners

Suggested change
createEffect(() => {
if (isDragging()) {
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseup", handleMouseUp);
}
onCleanup(() => {
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseup", handleMouseUp);
});
createEffect(() => {
if (isDragging()) {
window.addEventListener("mousemove", handleMouseMove);
window.addEventListener("mouseup", handleMouseUp);
onCleanup(() => {
window.removeEventListener("mousemove", handleMouseMove);
window.removeEventListener("mouseup", handleMouseUp);
});
}
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/routes/screenshot-editor/Preview.tsx
Line: 156:164

Comment:
**logic:** event listeners added conditionally but removed unconditionally in cleanup, causing listeners to remain attached after dragging stops

when `isDragging()` becomes `false`, cleanup runs and removes listeners, but they were only added when dragging was `true`, so on subsequent drags the effect runs again but doesn't re-add listeners

```suggestion
	createEffect(() => {
		if (isDragging()) {
			window.addEventListener("mousemove", handleMouseMove);
			window.addEventListener("mouseup", handleMouseUp);
			
			onCleanup(() => {
				window.removeEventListener("mousemove", handleMouseMove);
				window.removeEventListener("mouseup", handleMouseUp);
			});
		}
	});
```

How can I resolve this? If you propose a fix, please make it concise.

@richiemcilroy richiemcilroy merged commit 0103006 into main Jan 2, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants