diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index bfbb610..6a3f764 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -118,17 +118,46 @@ widthAvgIn: results.widths.avg, }) : draft(); + // The session already produced the processed PNGs: the calibration + // inventory PNG in results.inventoryPng and each sibling's in + // results.batchApply (parallel to s.batch). Attach them as + // processedBlob so the server upload carries real images (PUBLISH-40). + const calIdx = s.calibrationIndex; + const apply = results?.batchApply; const photos = s.batch.map((source, i) => ({ id: `cap-${i}-${source.blob.size}`, seq: i + 1, - isCalibration: i === s.calibrationIndex, + isCalibration: i === calIdx, url: URL.createObjectURL(source.blob), blob: source.blob, widthPx: source.widthPx, heightPx: source.heightPx, + processedBlob: + i === calIdx + ? results?.inventoryPng + : apply?.[i]?.status === 'ok' + ? apply[i].inventoryPng + : undefined, })); + // The dimension-overlay copy (REVIEW-5) is its own photo, adjacent to + // the calibration one and never flagged as it. Absent when the overlay + // encode failed (known separate defect) — the lineup just shows no overlay. + if (results?.overlayPng && calIdx != null) { + const overlay = { + id: `overlay-${calIdx}-${results.overlayPng.size}`, + seq: calIdx + 2, + isCalibration: false, + url: URL.createObjectURL(results.overlayPng), + blob: results.overlayPng, + widthPx: s.batch[calIdx]?.widthPx, + heightPx: s.batch[calIdx]?.heightPx, + processedBlob: results.overlayPng, + }; + photos.splice(calIdx + 1, 0, overlay); + for (const p of photos) p.seq = photos.indexOf(p) + 1; + } d.photos = photos; - d.calibrationPhotoId = s.calibrationIndex != null ? photos[s.calibrationIndex]?.id ?? '' : ''; + d.calibrationPhotoId = calIdx != null ? photos[calIdx]?.id ?? '' : ''; slab.set(d); await saveDraft(d); }