Skip to content

iOS audit (3/3): zoomable photos, off-main decoding, Flip that follows your finger - #32

Merged
Arluigi merged 7 commits into
mainfrom
ios-audit/photos
Sep 29, 2026
Merged

Arluigi merged 7 commits into
mainfrom
ios-audit/photos

Conversation

@Arluigi

@Arluigi Arluigi commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Last of three PRs from the 2026-09-28 Apple-design audit (plan: docs/superpowers/plans/2026-09-28-ios-design-audit.md). Client-only; no API or schema change.

  • Off-main decoding:
    • Photo decoding now happens off the main thread.
    • Core Data bytes are read on a background context by object ID.
    • The Record grid fetch leaves photoData out (SQL probe: the page query selects keys only, and metadata faults omit ZPHOTODATA).
    • Decodes cancel when their view goes away, and results are dropped after an account switch, sign-out or a missing ticket.
    • The detail view has its own cache, so it no longer evicts grid thumbnails.
    • Cache hits draw on the first frame.
  • Zoom:
    • The photo detail zooms with pinch and double-tap (UIScrollView: momentum, rubber-banding, centring).
    • Past 1.5× it swaps in a full-resolution decode, capped at 4096px and cancelled when the sheet closes.
    • VoiceOver gets "Zoom in" and "Reset zoom" actions and a dated label.
  • Photos open from their thumbnail: a .zoom navigation transition from the Record grid, list and Compare panes. Under Reduce Motion it uses .crossFade on iOS 27.
  • Flip:
    • Follows the horizontal drag 1:1, with the axis locked per drag so vertical scrolling can't flip it.
    • Settles on the photo the swipe's predicted end points to, with a spring, and can be caught mid-spring.
    • Fades under Reduce Motion. Exactly one selection tick per committed flip.
  • Capture:
    • The camera JPEG is encoded off the main thread.
    • "Saving…" actually renders, and a double tap can't save twice.
    • Retake keeps the typed note.
    • The review preview has a dated label.

Verification: 282/282 unit tests (full suite); the round-2 fix was re-run on its focused suites (36/36). Spec+quality review, re-reviews of both fix rounds, and care-access-reviewer (clean: no cross-account images, no new disk writes or logging). Not yet checked by hand: pinch/double-tap feel, the thumbnail zoom, and a Flip drag interrupted mid-spring. These need a signed-in local stack or a device.

🤖 Generated with Claude Code

Arluigi and others added 7 commits September 28, 2026 19:07
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cap the zoomed-in decode at 4096px and run it as a cancellable task keyed on
the zoom request and the shown photo. Cancel background decodes with their
caller, never keep one while signed out, seed tiles and the detail from the
cache, lock the Flip drag's axis and count it from the threshold, pause a
frame before saving, and re-centre the zoom view only when its size changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l-size decode

Keep the drag's locked axis in @State keyed by its start location, since
gesture state is already reset when onEnded runs, so a scroll that drifts
sideways can't flip on release. Let the next zoom gesture retry a failed
full-size decode, once per gesture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 29, 2026 00:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Arluigi
Arluigi merged commit 8d70b74 into main Sep 29, 2026
8 of 10 checks passed
@Arluigi
Arluigi deleted the ios-audit/photos branch September 29, 2026 00:32
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