Add CANCEL to the watermark editor, scope the mark's touch layer to that editor, and stop a library frame following the user onto the camera

The custom watermark captured EVERY image touch whenever the chip was ON
with text, in both modes: after switching from a library photo to the
camera there was no way to give the image back to tap-to-focus, and a
frame picked for the still rode along onto the live preview (and into the
capture).

- AdjustPanel: CANCEL chip next to ACCEPT. It drops the un-accepted draft
  and restores the last ACCEPTED mark (none if nothing was accepted).
- Viewfinder: draws the mark whenever the chip is ON with text, but only
  lets it CAPTURE touches while its editor is open (new wmEditing prop).
  A double-tap ON the mark still re-opens that editor from the library
  viewer.
- App: ACCEPT and CANCEL now close the editor (that closes the placement
  layer with it). Switching mode closes the deck panels, and leaves the
  frame behind: camera mode has no FRAME picker to undo one.

Verified on device (9a6a7277): camera tap locks AE/AF with the watermark
left ON; library polaroid no longer appears on the live preview after the
switch; CANCEL reverts the chip to CUSTOM WATERMARK OFF and closes the
panel; ACCEPT closes it and the next capture embeds the mark (amber text
found at 0.5/0.375 of the 3000x4000 export), while a capture before
ACCEPT carries none.
This commit is contained in:
2026-09-10 09:58:50 +07:00
parent 28e18893cd
commit d7a8e0681e
3 changed files with 85 additions and 15 deletions
+43 -8
View File
@@ -97,6 +97,26 @@ export default function App() {
setCustomWm(wm);
if (!wm.enabled) setCustomWmApplied({ ...DEFAULT_CUSTOM_WM });
};
// Leaving the watermark editor = closing its panel. The mark keeps capturing
// image touches ONLY while that panel is open (Viewfinder's wmArmed), so this
// is what hands the photo back to tap-to-focus / pinch / double-tap zoom.
const closeWatermarkEditor = () => {
setOpenTab(null);
setOpenParamKey(null);
};
// ACCEPT: the draft becomes the mark the export burns in, then the editor
// closes so the image stops being a placement surface.
const handleAcceptCustomWm = () => {
setCustomWmApplied({ ...customWm });
closeWatermarkEditor();
};
// CANCEL: drop every un-accepted edit and fall back to the last ACCEPTED mark
// (none at all when nothing was ever accepted), then close exactly like
// ACCEPT — the escape hatch a running session previously lacked.
const handleCancelCustomWm = () => {
setCustomWm({ ...customWmApplied });
closeWatermarkEditor();
};
// Composition aspect-ratio (FULL / 4:3 / 3:2 upright) + RAW DNG sidecar.
const [aspectRatio, setAspectRatio] = useState<AspectRatio>('full');
const [rawEnabled, setRawEnabled] = useState(false);
@@ -816,15 +836,20 @@ export default function App() {
// Switching back to camera: drop GPS that belongs to a library photo, so the
// live view (and any capture) never stamps a stale location.
const handleSetMode = (next: 'camera' | 'library') => {
if (next === mode) return;
if (next === 'camera' && gpsInfo && gpsInfo.source !== 'device') {
setGpsInfo(null);
}
// FRAME only exists in library mode — close the panel when switching back
// to camera so a dead frame chip row never lingers over the live preview.
if (next === 'camera' && openTab === 'frame') {
setOpenTab(null);
setOpenParamKey(null);
}
// The deck panels belong to one mode only (FRAME exists in library alone,
// and the WATERMARK panel is the watermark's edit session), so every switch
// closes them: no frame chip row over the live preview, and no watermark
// placement layer left eating the camera's tap-to-focus.
setOpenTab(null);
setOpenParamKey(null);
// A frame was picked for the still it sits on; camera mode has no FRAME
// picker to undo it, so it must never follow the user onto the live camera
// (and into the capture, which burns the frame in).
if (next === 'camera') setSelectedFrame('none');
setMode(next);
};
@@ -975,8 +1000,17 @@ export default function App() {
meteringAdjustments={meteringAdj}
imageAdjustTarget={imageAdjustTarget}
customWm={customWm}
// The mark only captures image touches while its panel is open, so a
// watermark left ON cannot block tap-to-focus or pinch/zoom.
wmEditing={openTab === 'watermark'}
onWmPositionChange={(x, y) => setCustomWm((p) => ({ ...p, x, y }))}
onWmEdit={() => setWmEditNonce((n) => n + 1)}
onWmEdit={() => {
// Double-tap on the mark re-opens its editor (and with it the
// placement layer), then focuses the input.
setOpenTab('watermark');
setOpenParamKey(null);
setWmEditNonce((n) => n + 1);
}}
/>
</View>
@@ -1019,7 +1053,8 @@ export default function App() {
onDeleteRecipe={handleDeleteRecipe}
customWm={customWm}
onUpdateCustomWm={handleUpdateCustomWm}
onAcceptCustomWm={() => setCustomWmApplied({ ...customWm })}
onAcceptCustomWm={handleAcceptCustomWm}
onCancelCustomWm={handleCancelCustomWm}
wmEditNonce={wmEditNonce}
/>
</View>