feat(photos): multi-photo batch + device draft (#59)

Replace single Add photo with Batch: accumulate 1–N photos, Continue
when ≥1 (M1 bridge: mask on first), persist batch blobs in the device
draft, Resume Continue restores. Keeps Mask/Axis/Measure intact.
This commit is contained in:
2026-09-15 21:08:44 +00:00
parent e919fe9a35
commit ff4bb0f31e
5 changed files with 273 additions and 70 deletions
+9 -6
View File
@@ -4,7 +4,7 @@
import { createCaptureSession, type CaptureSession } from './capture/session';
import type { Capture } from './capture/capture.types';
import Resume from './capture/Resume.svelte';
import AddPhoto from './capture/AddPhoto.svelte';
import BatchPhotos from './capture/BatchPhotos.svelte';
import MaskPanel from './capture/MaskPanel.svelte';
import AxisPanel from './capture/AxisPanel.svelte';
import MeasurePanel from './capture/MeasurePanel.svelte';
@@ -12,7 +12,7 @@
const gate = typeof window !== 'undefined' ? supported() : 'window unavailable';
const session: CaptureSession = createCaptureSession();
let cap: Capture = { k: 'addPhoto' };
let cap: Capture = { k: 'batch', photos: [] };
let busy = false;
let pngUrl: string | null = null;
@@ -24,8 +24,6 @@
busy = b;
});
const pick = (f: File) => void session.addPhoto(f);
onMount(() => {
void session.resumeProbe();
});
@@ -49,8 +47,13 @@
<main class="app">
{#if cap.k === 'resume'}
<Resume onContinue={() => session.continueDraft()} onFresh={() => void session.startFresh()} />
{:else if cap.k === 'addPhoto'}
<AddPhoto onPicked={pick} />
{:else if cap.k === 'batch'}
<BatchPhotos
photos={cap.photos}
onAdd={(f) => void session.addToBatch(f)}
onRemove={session.removeFromBatch}
onContinue={session.continueBatch}
/>
{:else if cap.k === 'mask'}
<MaskPanel
state={cap}