Files
gui-video-clipper/chat-summaries/2026-09-23_07-18-blur-icons-zoom-fixes-summary.md
cottongin c1de18715e feat: v0.2.1 — Player controls polish, screenshot capture, quit shortcut
v0.2.0 introduced Player mode with floating controls, auto-hide UI,
PiP, fullscreen, JKL shuttle, speed selector, captions, and cut-clip.

v0.2.1 builds on that with extensive UI polish and new features:

Player Controls Polish:
- Enlarged center playback icons (Play 48, Rewind/FF 36) with filled SVGs
- Moved Cut Clip scissors into center group with hidden cut-before button
- Narrowed floating panel from 70% to 60% width
- Custom-styled volume slider matching seek bar (linear-gradient fill)
- Pure opacity fade animation (0.35s) replacing slide-in
- Tinted panel background (rgba(53,54,80,0.75)) visible on black canvas
- Drop shadow on center transport controls
- Scissors buttons dimmed via color (not opacity) with single-property transitions
- ScissorsLineDashed icon for cut-before variant
- Timestamps in single seek row (time | bar | duration) with sans-serif font
- Milliseconds shown at smaller size, revealed on hover

Screenshot Capture (S / Shift+S):
- Canvas compositing at native video resolution with optional caption burn-in
- Caption rendering matches CSS preview (font, background, outline, word highlight)
- New Rust save_screenshot command using existing filename pattern
- Output: {title} - {ms}ms-screenshot.png
- crossorigin=anonymous on video element for untainted canvas

Other:
- Q keyboard shortcut to quit via Tauri process plugin
- formatTimeParts() utility for split timestamp rendering
- Updated About dialog shortcuts list
- Version bump to 0.2.1

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-23 05:30:45 -04:00

2.5 KiB

v0.2.1 Fixes: Blur, Icon Sizing, Timeline Zoom

Task Description

Three fixes for the v0.2.1 release: (1) fix the backdrop blur pop-in animation in Player mode floating controls, raise controls another 20px; (2) enlarge center playback icons by 50%; (3) zoom timeline to clip region when using cut-clip from Player mode.

Changes Made

Commits

  1. f6ad41f — fix: blur via visibility (no opacity), raise to 84px, enlarge center icons 50%

    • src/lib/components/PlayerControls.svelte:
      • Blur fix: Restructured CSS so the overlay no longer transitions opacity at all. The ::before blur pseudo-element uses visibility: hidden/visible (instant toggle, always opacity: 1 when visible) so WebKit never has to composite backdrop-filter during an opacity transition. A new .panel-content wrapper handles the fade+slide animation (opacity 0->1, translateY(6px)->0) independently.
      • Position: bottom: 64px -> bottom: 84px
      • Icon sizes: Play/Pause size={18} -> size={27}, Rewind/FastForward size={16} -> size={24}, play button min-width: 40px -> 48px
  2. 619fe59 — feat: timeline zooms to clip region on cut-clip from Player mode

    • src/lib/components/Timeline.svelte: Added zoomRegion and onZoomApplied optional props. Added a second $effect (after the duration-reset effect) that zooms to the given region with 20% padding (min 2s) on each side.
    • src/App.svelte: Added pendingTimelineZoom state. cutClip() sets it to the created clip's range before switching to Clipper mode. Passed zoomRegion={pendingTimelineZoom} and onZoomApplied callback to <Timeline>.

Test Results

  • 69/69 tests passing, svelte-check 0 errors/0 warnings

Lessons Learned

  • WebKit backdrop-filter + opacity compositing: The ::before pseudo-element approach from the previous attempt still failed because ANY opacity transition (even on the pseudo-element itself, not just ancestors) prevents WebKit from compositing backdrop-filter during the animation. The only reliable fix is to NEVER transition opacity on the element that has backdrop-filter. Use visibility: hidden/visible for instant show/hide of the blur layer, and animate content separately.
  • Svelte 5 $effect ordering: When two effects run on mount, the one declared later wins for overlapping state mutations. This is leveraged for the timeline zoom — the duration-reset effect runs first (sets full view), then the zoom effect runs second and overrides if zoomRegion is set.