web: count a roll as it is read, and open a frame without losing the count

Two holes left by the last change. A frame is opened with `window.location.href`
rather than a link, so the studio was still handed a fresh page and the scan with
it — every route out of the catalogue now goes through `go()`, which pushes the
address instead of reloading while a scan is in flight. And a row counted what was
filed away rather than what had been read, so it sat at zero for the whole of a
first scan: the catalogue's frames only reach IndexedDB in one batch at the end.

`ScanProgress.counts` carries the frames the scan has reached, per row, off the
scan's own bookkeeping, and the column reads it while the scan runs — the row
under the reader's eye moves as the roll is read, and the toolbar's line stays the
whole picture. A re-read counts from the start, which is what it is doing.

The regression check grows the two: a frame opened mid-scan from the catalogue
(of a roll it already holds) has to stay in the page, and the row has to count.
This commit is contained in:
2026-09-28 20:39:51 +07:00
parent 79b0d0db86
commit 1cb2618fd7
5 changed files with 113 additions and 17 deletions
+16
View File
@@ -0,0 +1,16 @@
import { scanSession } from './engine/library';
// Internal navigation, in one place. The app has no router: a route is a page
// load, and that is fine for everything except a route change made while a scan
// is reading a roll, because the reading lives in this page's memory and a reload
// throws it away. So while a scan is in flight the route changes in place —
// push the address, tell whoever draws it — and with no scan running the browser
// navigates exactly as it always has.
export function go(url: string): void {
if (!scanSession()) {
window.location.href = url;
return;
}
history.pushState(null, '', url);
window.dispatchEvent(new PopStateEvent('popstate'));
}