+ Pick calibration photo
+
+ Choose which photo is the top-down reference for length and thickness.
+ Mask, length axis, and Measure run on that photo only.
+
+
+
+ {#each photos as _p, i (urls[i])}
+ -
+
+
+
+ {/each}
+
+
+
+
+
+
diff --git a/frontend/src/capture/capture.types.ts b/frontend/src/capture/capture.types.ts
index e57d0db..14b3b6a 100644
--- a/frontend/src/capture/capture.types.ts
+++ b/frontend/src/capture/capture.types.ts
@@ -71,10 +71,11 @@ export interface Measures {
}
// The machine. 'resume' exists only while a draft exists and has not been chosen.
-// M2: 'batch' replaces M1 'addPhoto' — accumulate 1–N photos before calibration.
+// M2: 'batch' + 'pickCalibration' replace M1 'addPhoto' — accumulate, then user picks calibration.
export type Capture =
| { k: 'resume'; draft: Draft }
| { k: 'batch'; photos: Source[] }
+ | { k: 'pickCalibration'; photos: Source[] }
| {
k: 'mask';
source: Source;
@@ -117,10 +118,12 @@ export const DEFAULT_MASK_PARAMS: MaskParams = { sheet: 'auto', sensitivity: 50
// M2 extends with `batch` (capture-order photo blobs). Legacy M1 drafts omit it.
export interface Draft {
version: 1;
- stage: 'batch' | 'mask' | 'axis' | 'measure'; // last approved / persisted state
+ stage: 'batch' | 'pickCalibration' | 'mask' | 'axis' | 'measure'; // last approved / persisted state
/** Capture-order batch. Absent on legacy M1 drafts ⇒ treat as [source]. */
batch?: Source[];
- source: Source; // calibration / active photo; for stage==='batch' = photos[0]
+ /** Index into batch of the user-picked calibration photo. Set once picked. */
+ calibrationIndex?: number;
+ source: Source; // calibration / active photo; for stage==='batch'|'pickCalibration' = photos[0] placeholder
maskParams: MaskParams; // → re-derive mask on resume (ignored while stage==='batch')
mask: Omit