The lightbox's close animation needs the original thumbnail ref/dims to know
where to animate back to. The peek-commit path was passing null, so the
lightbox dropped to a fade instead of the usual return-to-thumb animation.
Rework each embed path so the tap handler and the peek-commit handler
invoke the same openLightbox call with the same ref + dims:
- Grid and scrollable Gallery: derive `openLightboxAtIndex` once per cell
and hand it to both Pressable.onPress and ContextMenu.onPreviewPress.
- Single image: add onContainerRef / onDimsChange callbacks to
AutoSizedImage, capture them in ImageEmbed, and use them for the peek
commit. Drops the now-redundant onPreviewPress prop chain.
https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT
Two UX fixes for the peek preview:
1. Black flash on first peek — the preview VC now depends on SDWebImage
directly (same version pinned by expo-image) and reads from
`SDImageCache.shared`. On open it paints the fullsize synchronously if it's
cached (common, since onPressIn prefetches), otherwise paints the thumb as a
placeholder while the fullsize loads and swaps in. Also switches the image
view to autoresizingMask so the dismiss animation interpolates cleanly
without AutoLayout relayout mid-animation.
2. Two-stage dismiss animation on aspect-mismatched thumbnails — drop the
explicit `previewForDismissingMenuWithConfiguration` override. With only
the highlight provider implemented iOS reverses it end-to-end, which
interpolates size and position together instead of snapping back to the
preview's original size before translating.
https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT
RN/Expo already owns a borderRadius property on UIView (as a style prop),
so declaring `private var borderRadius` on ExpoView was rejected by Swift
("cannot override with a stored property"). Rename the bridge prop and Swift
property to `previewCornerRadius`; the public Trigger/ImageContextMenu API
keeps `borderRadius` and Root translates it at the bridge layer.
Also tighten `var start` to `let` in the SVG parser.
https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT
Thread onPreviewPress(index) through ImageLayoutGrid / GalleryItem and the
Gallery scroll item so multi-image embeds get the same iOS peek behaviour as
single-image embeds. Each grid cell wraps its Pressable in ImageContextMenu
with the image's true aspect ratio, so the preview lifts to the full
uncropped image even when the cell is cropped to square.
https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT
Introduces expo-bluesky-context-menu, a compositional Root/Trigger/Menu/MenuItem
wrapper around UIContextMenuInteraction. The preview ViewController is sized to
the image's true aspect ratio so tall/panorama previews don't stretch mid-lift,
and menu icons are rasterized from the app's SVG icon set on the native side.
The preview prop is a discriminated union (image today; video and externalCard
reserved) so the same module can back those embeds in follow-ups.
https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT