Kobo: progress tracking and kepubify #8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "state-debug"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Test plan
🤖 Generated with Claude Code
Root cause of the "reading position resets on every book reopen" bug: the library stores plain EPUBs. Kobo's Nickel encodes resume positions as `Location.Type=KoboSpan, Value=kobo.{paragraph}.{span}`, where the span identifier points at a `<span class="koboSpan" id="kobo.X.Y">` element inside the chapter's HTML. Those elements only exist in kepubified files; plain EPUBs have nothing to encode against, and Nickel falls back to `kobo.1.1` (first span of the current chapter file) for every restore position. Every reopen lands at the chapter start. Confirmed by inspecting library files on the live server: zero koboSpan markers anywhere under /opt/books/library, and every reading_state row in the device's sync state has Location.Value stuck at kobo.1.1 — even as ContentSourceProgressPercent advances, confirming Nickel does track within-chapter progress but has no span markers to encode it against. Fix: run the epub through `github.com/pgaskin/kepubify/v4/kepub` on the download handler, streaming the converted bytes to the client. The library stays as plain EPUBs on disk (so other download paths still work); only the Kobo download endpoint gets the kepubified version. A few milliseconds of CPU per request, no disk cost, no cache to invalidate. Existing on-device position state for already-downloaded books will still be broken because they were fetched as plain EPUBs — recovery is per-book: unshelve → sync → reshelve → sync → fresh kepubified download → position tracking starts working.