Edge-to-edge (edgeToEdgeEnabled) makes Android ignore the manifest's
adjustResize, so the IME never shrank the window and the text input sat
under the keyboard. Track keyboardDidShow/Hide height and pad the deck.
Restore shutter sound/metering/RAW from a dedicated key under both 'default'
and 'last session' startup (the session file only stores the look and is
written on background events, so it can be stale after a force-kill). Guard
the persist effect until hydration finishes so the mount-time defaults cannot
overwrite the stored values; drop the stale session override of these three.
Flip only reconfigured the CameraSession in place, leaving the Skia
offscreen-surface cache from the old lens wedged on this Xiaomi: after a
flip the preview banded then went black while the frame pipeline kept
delivering (heartbeat kept rising) and only a full app restart revived it.
- key <SkiaCamera> by facing + mount nonce so a flip fully unmounts and
remounts the camera (lib clears its surface cache on unmount), i.e. a
clean restart on every lens switch instead of an in-place reconfigure.
- watchdog now recovers by the same full remount instead of an isActive
toggle (which never revives a wedged preview), budgeted to 3 restarts.
- bump a re-render on every onStarted: after a remount cameraActive never
drops (no onStopped on unmount) so the reopen did not re-render and the
new controller was never re-read, leaving the 1x-10x zoom chips hidden
until the next touch.
Verified on device: 15+ flips with no wedge, chips visible immediately
after each flip, preview stays live (was ~5 min to black before).
- Settings STARTUP MODE chips (AsyncStorage startup_mode): default = clean camera
+ PROVIA neutral 4:3, last = restore full session look.
- initSession: resolve sim-* recipe ids via FILM_SIMS (fix clobber of session
ratio/adjustments to 4:3 canonical); restore via setSelectedRecipe not
applyRecipe so user tweaks (frame/geotag/ratio) survive restore.
- applyDefaultStartup turns GPS watermark OFF (user-requested default).
- Shutter: OFF must not play click on must-play-policy devices. VisionCamera
v5.2.3 HybridPhotoOutput.kt plays MediaActionSound itself gated by
(enableShutterSound ?: true) || mustPlayShutterSound — on Xiaomi mustPlay=true
so OFF still clicked. Both capture paths now gate on enableShutterSound != false.
node_modules patch not trackable -> artifacts/patches/vision-camera-shutter-silent.patch.
Verified on Xiaomi 12S Ultra: log SND user=false -> play=false; cold-start
DEFAULT shows GPS WATERMARK OFF.
Local Kotlin module modules/recipescam-export (autolinked via expo ./modules)
exposes decodeEncodeAsync — BitmapFactory decode -> JPEG q95 encode -> file,
all on Dispatchers.IO off the JS/main threads. EXPO_PUBLIC_BENCH=1 builds run
src/dev/nativeBenchProbe.ts: 3 timed decode+encode passes on the bundled
wallframe artwork plus a JS-timer gap check proving the JS thread never
blocks during native rendering. Legacy Skia engine untouched (reference).
Plain frame 'none' with ratio 4:3 shows the whole sensor at screen width (85 deg FOV, like the built-in app at 23mm equiv); 3:2 crops the two vertical sides, same height and zoom, matching the export crop. The fullscreen-cover plain preview from 7985f25 was a wrong interpretation of the built-in view and made every ratio look identical fullscreen.
Plain frame 'none' with an aspect ratio no longer bands the feed into a letterboxed strip; it keeps the fullscreen cover view like FULL/1x, so 4:3 preview shows the same angle of view as the built-in camera app at 1x (export crop unchanged). Border/bars frames (classic-white, cinematic) keep the banded contain view.
The band region was the ratio photo re-scaled to the screen width, so 3:2
(0.667) rendered taller than the 4:3 (== native 3:4) band and zoomed the
scene. Anchor the band on the contain-fitted native sensor box instead and
cut the ratio strip out of it at the same scale: 3:2 is now the identical
vertical view with a narrower horizontal crop, never a taller image.
SkiaCamera cover-fits the upright frame snapshot onto the fullscreen view,
so a 4:3 ratio band (aspect == native 3:4 sensor) only revealed a center
slice of the sensor instead of the whole frame. Redraw the feed inside the
frame worklet: when a photo-area rect is active (ratio band / polaroid
window / wall window) black the surface, clip to the rect's raw-frame
inverse under the renderToTexture rotation/mirror CTM, and cover-map the
sensor there. Equal-aspect bands now show the full sensor; narrower ratios
(3:2) crop center like the export. Inactive feed keeps the legacy draw.