fix(reader): route KOReader progress by format so paged books resume

KOReader reports a paged document's position as a page number and a reflowable one's as an
xpointer, but applySharedProgress treated every incoming position as an xpointer and
upsertReadingProgress hardcoded pageNumber to null on every write. A PDF synced from a device
therefore stored a correct percentage with no page, and the web reader reopened it at page 1.
The same write also destroyed a page the web reader had saved earlier, including during an
unattended bulk sweep, so this lost positions that were never synced from a device at all.

Carry the book file's format through hash resolution and pick the column from it. CBZ/CBR were
affected identically at the data level but masked in the UI, because the comic reader estimates
a page from the percentage when none is stored.

Closes #954
This commit is contained in:
neon
2026-08-09 17:29:19 +00:00
parent 4607ed8235
commit 68fae9a121
10 changed files with 553 additions and 49 deletions
+19
View File
@@ -513,6 +513,25 @@ export const E2E_SUITES = Object.freeze({
...SHARED_DB_AND_HELPER_PATHS,
],
},
"koreader-progress-position": {
id: "koreader-progress-position",
name: "KOReader Progress Position Routing",
timeout: 45,
lane: "full",
description: "KOReader progress position routing into cfi or pageNumber per book format",
vitestTarget: "test/koreader-progress-position.e2e-spec.ts",
junitOutput: `${TEST_RESULTS_DIR}/koreader-progress-position-e2e-junit.xml`,
prepareDedicatedDatabase: true,
useDedicatedDatabase: true,
changedPaths: [
"server/src/modules/koreader/**",
"server/src/modules/book/book.service.ts",
"server/src/db/schema/reader.ts",
"server/test/koreader-progress-position.e2e-spec.ts",
"server/test/e2e/reader-state-isolation/**",
...SHARED_DB_AND_HELPER_PATHS,
],
},
"koreader-file-naming": {
id: "koreader-file-naming",
name: "KOReader File Naming",