Skip to content

Fix dropdowns, photo metadata, queue sections and edge-case bugs - #7

Merged
HapticHash merged 2 commits into
masterfrom
claude/capabilities-discussion-hrjot1
Oct 2, 2026
Merged

HapticHash merged 2 commits into
masterfrom
claude/capabilities-discussion-hrjot1

Conversation

@HapticHash

Copy link
Copy Markdown
Owner

Summary

Fixes the three issues reported from manual testing, plus ten edge-case bugs found by testing the production build.

Reported issues

  1. Dropdown arrows too close to the edge. All dropdowns now use a shared Select component that hides the native arrow and draws a chevron with padding.
  2. Photo metadata removed even with "Keep photo metadata" on. The toggle only worked for JPEG → JPEG. The new src/lib/metadata.ts reads EXIF from JPEG, PNG, WebP and HEIC and writes it into JPEG, PNG or WebP output, resetting the orientation tag to upright. AVIF can't store EXIF, and the file's row says so. When the original is returned because it was already optimized, EXIF and XMP are now stripped losslessly unless metadata should be kept; previously GPS data leaked through in that case.
  3. Adding files while others are processing. The queue now splits into Processing and Newly added, with Compress new files (N) and Re-compress all buttons. All batches share one concurrency limit. Files waiting for a slot show "Waiting" and can be cancelled; their Cancel button used to do nothing.

Edge-case bugs

# Bug Fix
1 A Custom target larger than the file still re-encoded it heavily (707 KB photo with a 10 MB target → 210 KB) The original is kept ("Already under your target") unless a format, size or trim change was requested; the custom ratio is capped at 1 instead of 0.9
2 Small image targets missed silently (5 KB target → 9 KB) Retries at smaller dimensions until the image fits (now 3.9 KB); rows say when a target couldn't be met
3 PDF targets overshot badly (708 KB PDF with a 100 KB target → 11 KB) Samples page 1 at each render step and picks the best one that fits, with up to three corrective passes (now 68 KB)
4 Nonsense targets accepted (0.0000001 KB) Targets must be between 1 KB and 100 GB
5 Failures just said "Compression failed" src/lib/errors.ts gives specific messages: empty file (rejected when added), unreadable image or PDF, password-protected PDF, unsupported media
6 A trim starting past the end produced an empty 262-byte "success" Validated against the clip's duration, and empty output is rejected
7 Trim end before start was silently ignored Flagged inline in the file's options and rejected
8 Offline video failed without explanation Says the 31 MB video engine needs an internet connection the first time
9 Audio-only WebM (reported as video) was saved as an audio-only .mp4 Detected as audio and handled that way
10 The savings estimate was misleading mid-run and for targets Covers only the new files when that's what the main button compresses, shows as approximate, and says when nothing needs compressing

Testing

  • npm run lint and npm test (25 unit tests, including new tests for the metadata module and target parsing): pass
  • npm run test:e2e (15 Playwright tests, 5 of them new): pass. They cover keeping and removing metadata through JPEG and WebP, the queue sections and buttons, error messages for broken files, Custom targets (under target, a tiny invalid target, and a PDF target being met without collapsing), and trim validation.
  • Manual checks on the production build with a GPS-tagged JPEG and an iPhone HEIC: metadata is kept or removed as chosen for every format. WebP output is valid; Chrome decodes it, and the EXIF chunk and flag are present.

🤖 Generated with Claude Code

https://claude.ai/code/session_011UUBS4XF57trCnZcGwBu35


Generated by Claude Code

- Dropdowns: hide the native arrow and draw a chevron with padding, via a
  shared Select component used by every dropdown.
- Photo metadata: "Keep photo metadata" only worked for JPEG to JPEG.
  EXIF is now read from JPEG, PNG, WebP and HEIC and written back into
  JPEG, PNG or WebP output (orientation reset to upright). AVIF says it
  can't store it. When the original file is returned (already optimized),
  EXIF/XMP is stripped losslessly unless metadata should be kept. The
  "removed" note only shows when the photo actually had metadata.
- Queue: files added while others are processing are listed under
  "Newly added", with "Compress new files" and "Re-compress all" buttons.
  All batches share one concurrency limit; files waiting for a slot show
  "Waiting" and can be cancelled (previously their Cancel did nothing).

Claude-Session: https://claude.ai/code/session_011UUBS4XF57trCnZcGwBu35
- Custom target at or above the file size: the original is kept ("Already
  under your target") instead of being re-encoded at low quality; the
  estimate no longer claims savings. Targets under 1 KB are rejected.
- Small image targets: when quality alone can't reach the target, the image
  is shrunk step by step until it fits (5 KB target: 9 KB -> 3.9 KB).
- PDF "Smallest size" with a target: samples the first page at each quality
  step and uses the best one that fits, instead of a fixed formula (708 KB
  at a 100 KB target: 11 KB -> 68 KB). Rows say when a target couldn't be
  reached, with a hint.
- Failures explain why: empty files are rejected on add; unreadable images
  and PDFs, password-protected PDFs, unsupported media and a missing
  internet connection for the first video each get their own message.
- Trims: end before start is flagged inline and rejected; a start past the
  end of the clip is rejected instead of producing an empty file.
- Audio-only WebM recordings (reported as video) are handled as audio.
- Savings estimate covers only the new files when that's what the main
  button compresses, and reads as approximate.

Claude-Session: https://claude.ai/code/session_011UUBS4XF57trCnZcGwBu35
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
compressly e1554f0 Oct 02 2026, 03:31 AM

@HapticHash
HapticHash merged commit 65ffa98 into master Oct 2, 2026
4 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.

1 participant