fix(reader): serve PDF and comic files correctly to every client

Fix the server and web gaps found while porting the PDF and comic
readers and offline downloads to Android, checked against the iOS app:

- KOReader: answer a pull for a PDF or comic with the page number when a
  BookOrbit client wrote last, instead of a percentage with no page
- comics: key the zip offset, RAR and CB7 caches by file id and
  modification time, so pages are not served from stale offsets after a
  metadata write-back rewrites the archive
- comics: answer an unreadable archive with 422 rather than a page count
  of 0, and extract CB7 with its folders so same-named pages in
  different folders no longer overwrite each other
- book files: send an ETag and Last-Modified on serve and download and
  honour If-None-Match and If-Range, clamp a range that runs past the
  end, answer suffix ranges with 206, and honour Range on download,
  which advertised it but sent the whole file
- book files: leave raw file routes uncompressed, so FB2 and unknown
  formats keep their Content-Length
- progress: reject a fractional or negative page number with 400 rather
  than failing with 500 at the database
- types: declare the comic page-count response shared by the web and
  the apps
- web: open a percentage-only PDF position at its estimated page, and
  flush pending PDF and comic progress before the reading session ends
This commit is contained in:
neon
2026-10-13 16:33:11 +00:00
parent a9f8cea616
commit 198d36ae56
32 changed files with 1764 additions and 211 deletions
+4
View File
@@ -0,0 +1,4 @@
/** `GET /cbz/files/:fileId/pages`: how many readable pages a CBZ, CBR or CB7 file has. */
export interface ComicPageCountResponse {
pageCount: number;
}
+1
View File
@@ -49,6 +49,7 @@ export * from "./indexer-manager";
export * from "./request-credential";
export * from "./file-write";
export * from "./epub";
export * from "./comic";
export * from "./author";
export * from "./metadata-score";
export * from "./metadata-reminders";