Skip to content

feat(image): add interactive pan/zoom to image viewer#4

Merged
HelgeSverre merged 5 commits intomainfrom
image-pan-zoom-v2
Mar 1, 2026
Merged

feat(image): add interactive pan/zoom to image viewer#4
HelgeSverre merged 5 commits intomainfrom
image-pan-zoom-v2

Conversation

@HelgeSverre
Copy link
Owner

Summary

  • Replace static TabContent::Image display with full interactive ViewMode::Image viewer
  • Pan via click-and-drag, zoom-toward-cursor on scroll wheel
  • Keyboard shortcuts: Cmd+=/- (zoom), Cmd+0 (fit), Cmd+Shift+0 (actual size)
  • Status bar shows dimensions, zoom %, file size, format
  • Checkerboard background, nearest-neighbor scaling, auto-fit on resize
  • Bug fixes: zero-dimension guard, content-local coordinate math, u32 overflow protection

Test Plan

  • All 1071+ test assertions pass, 0 failures
  • Clippy clean (-D warnings)
  • 10 integration tests for ImageState, file detection, zoom, fit scale
  • Manual: open PNG/JPEG/GIF/BMP/WebP/ICO files
  • Manual: scroll to zoom (anchors at cursor)
  • Manual: click-drag to pan
  • Manual: Cmd+=/-/0/Shift+0 keyboard shortcuts
  • Manual: resize window, verify auto-fit recomputes

Replace the static image display (TabContent::Image) with a full
interactive image viewer using ViewMode::Image:

- Pan via click-and-drag with zoom-toward-cursor on scroll wheel
- Keyboard shortcuts: Cmd+=/- (zoom), Cmd+0 (fit), Cmd+Shift+0 (1:1)
- Status bar shows dimensions, zoom %, file size, format
- Checkerboard background with nearest-neighbor scaling
- Auto-fit on window resize when user hasn't manually zoomed
- Guards against zero-dimension images and u32 pixel index overflow
- Content-area-local coordinate math for accurate zoom anchoring
The render function centers small images within the viewport using a
center_x/center_y offset, but the zoom handler didn't account for this.
This caused zoom to anchor at the wrong point (shifted toward the
bottom-right corner) instead of at the cursor position.

Also fixes keyboard zoom double-subtracting the content area offset
by storing raw window coords in last_mouse_x/y.
tree-sitter-blade has a git submodule (tree-sitter-html) using an SSH
URL. Cargo's built-in libgit2 can't authenticate in CI, but the system
git CLI is configured with HTTPS credentials by the checkout action.
The previous git-fetch-with-cli fix was incomplete: the checkout action
sets persist-credentials: false, which removes the url.insteadOf config
after checkout. This means the git CLI still tries SSH URLs for
tree-sitter-blade's submodule and fails with Permission denied.

Add explicit git config to rewrite git@github.com: URLs to https:// in
all CI jobs that run cargo commands.
dist plan validates release.yml against its template and rejects our
SSH-to-HTTPS URL rewriting steps. Setting allow-dirty = ["ci"] tells
cargo-dist to accept our custom modifications.
@HelgeSverre HelgeSverre merged commit 2564650 into main Mar 1, 2026
6 checks passed
@HelgeSverre HelgeSverre deleted the image-pan-zoom-v2 branch March 11, 2026 03:35
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.

1 participant