Match built-in camera 1x FOV for plain ratio preview

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.
This commit is contained in:
2026-09-08 20:27:24 +07:00
parent 125c1280fa
commit 7985f25aa8
+23 -10
View File
@@ -115,14 +115,23 @@ export default function Viewfinder({
// Composition ratio band. With a ratio active the photo area is a centered
// portrait strip (w/h = ratioWH) and everything outside is letterboxed;
// exports crop to the same ratio. Only the plain full-picture frames use the
// band — polaroid keeps its own card layout (window aspect follows the ratio)
// and wall frame deliberately ignores the ratio entirely (its opening is a
// fixed 2:3). When no band is active the region is just the full screen, so
// every consumer below degrades to the old fullscreen behavior untouched.
// exports crop to the same ratio. The border/bars frames (classic-white,
// cinematic) use the band because their geometry must hug the photo edges;
// polaroid keeps its own card layout (window aspect follows the ratio) and
// the wall frame deliberately ignores the ratio entirely (fixed 2:3 window).
// A PLAIN preview (frame 'none') with a ratio does NOT band in camera mode:
// it stays the fullscreen cover view of FULL/1x so the angle of view matches
// the built-in camera app at 1x — contain-fitting the whole sensor into a
// strip reads as a crop next to the native app's zoomed fullscreen preview
// (export still crops to the ratio). When no band is active the region is
// just the full screen, so every consumer below degrades to the old
// fullscreen behavior untouched.
const ratioWH = aspectRatio === 'full' ? null : ASPECT_RATIO_W_H[aspectRatio];
const plainRatio =
mode === 'camera' && selectedFrame === 'none' && ratioWH !== null;
const regionBand =
ratioWH !== null &&
!plainRatio &&
(selectedFrame === 'none' || selectedFrame === 'classic-white' || selectedFrame === 'cinematic');
const region = useMemo(() => {
if (!regionBand || ratioWH === null) return { x: 0, y: 0, w: vw, h: vh };
@@ -582,10 +591,12 @@ export default function Viewfinder({
return wallframeLayout(vw, vh, 'contain');
}, [selectedFrame, vw, vh]);
// Live feed band rect for the CAMERA preview: the photo-area that must show
// the export-equivalent sensor crop — the ratio band region (plain frames),
// the polaroid photo window or the wall-frame window. When present the frame
// worklet redraws the feed into it (native 4:3 shows the whole sensor);
// when null ([0]=0) the feed stays the legacy fullscreen cover draw.
// the export-equivalent sensor crop — the ratio band region (classic-white /
// cinematic frames), the polaroid photo window or the wall-frame window.
// When present the frame worklet redraws the feed into it (native 4:3 shows
// the whole sensor); when null ([0]=0) the feed stays the legacy fullscreen
// cover draw — that is also the plain 'none' + ratio case now, which shows
// the built-in-camera 1x view instead of a banded whole-sensor strip.
const cameraPhotoRect =
mode === 'camera'
? polaroidGeo
@@ -845,7 +856,9 @@ export default function Viewfinder({
<Canvas style={StyleSheet.absoluteFill} pointerEvents="none">
{/* Aspect-ratio band: black out the live feed outside the composition
region. Frames with their own geometry (polaroid/wall) draw their
own bars later, so this only fires for the plain frames. */}
own bars later; the plain 'none' camera preview no longer bands
(fullscreen 1x view), so this only fires for classic-white and
cinematic, whose border/bars must sit on the photo edges. */}
{regionBand && (
<Group color="#000000">
<Rect x={0} y={0} width={vw} height={region.y} />