diff --git a/docker/frontend/src/App.tsx b/docker/frontend/src/App.tsx index f09d2ba..a7411fa 100644 --- a/docker/frontend/src/App.tsx +++ b/docker/frontend/src/App.tsx @@ -1374,15 +1374,19 @@ export function Workspace() { ); const loadFile = useCallback( - async (file: File) => { + async (file: File, keepFrame = false) => { setError(null); setBusy(t('auth.busy')); // A file from the disk is nobody's saved frame: SAVE PHOTO must add one, // not overwrite whichever of the folder's own was open before. Opening one - // of those sets the id back, after this call. Same for a catalogue frame — - // the caller that hands one over names it again on the way back. + // of those sets the id back, after this call. setOpenPhotoId(null); - setLibPhotoId(null); + // A frame of the catalogue's own roll is the one exception: the strip under + // the photo reads that id, so dropping it for the length of the load is + // what tore the whole roll down and drew it again — every tile of it read + // a second time — for a click that changed one frame. The caller opening a + // frame of the roll says so, and the roll stands still until the next one. + if (!keepFrame) setLibPhotoId(null); // A RAW is PRO: the file is parked whole and developed by the engine, // which only that tier carries. A basic account is told, not silently // served a JPEG it never asked for. @@ -2537,7 +2541,7 @@ export function Workspace() { try { const row = await getPhoto(id); if (!row) throw new Error('not in the catalogue'); - await loadFile(await readPhotoFile(row)); + await loadFile(await readPhotoFile(row), true); const saved = await loadEdit(id); if (saved) restoreState(saved.state); // The catalogue's own standing for this frame, which the reader set on diff --git a/docker/frontend/src/ui/ImageStage.tsx b/docker/frontend/src/ui/ImageStage.tsx index 310b953..1256a24 100644 --- a/docker/frontend/src/ui/ImageStage.tsx +++ b/docker/frontend/src/ui/ImageStage.tsx @@ -2581,19 +2581,25 @@ export function ImageStage({ )} + {/* The frame's own name and specs, and the roll beside it, stand outside + the branch below. Opening the next frame of the roll empties the stage + while its bytes are read, and a strip inside that branch went with it: + every tile of the roll torn down and drawn again, on the way out and on + the way back, for a click that changed one frame. The roll is under the + row that names the frame it is walking. */} + {previewUrl && (shotSpecs || place || dims || photoName) ? ( +