Fix: Remaining Kobo "Sync to last page read?" popup on sync#3607
Open
leahjessie wants to merge 2 commits into
Open
Fix: Remaining Kobo "Sync to last page read?" popup on sync#3607leahjessie wants to merge 2 commits into
leahjessie wants to merge 2 commits into
Conversation
|
Same flow landed in the community CWA-derived build Calibre-Web-NextGen — |
leahjessie
added a commit
to leahjessie/calibre-web
that referenced
this pull request
May 22, 2026
…otes/ - pr-kobo-popup-fix.md and pr-kobo-popup-fix-short.md: deleted. Submitted upstream as janeczku#3607. - READER_SYNC_PLAN.md: moved into notes/ with a status header noting that most of the plan has shipped via feat/epub-reader-foliate (per-source reader_position, dual-write, Stage 1/2 arbitration, web Kobo offer popup, observability endpoints, config gate). - notes/kobo-popup-attempts.md: cross-reference the upstream PR. meta/ root is now scripts + AGENTS.md/CLAUDE.md/TODO.md + profiles/. Investigation history and design plans live under notes/.
leahjessie
added a commit
to leahjessie/calibre-web
that referenced
this pull request
May 22, 2026
…empts The previous commit missed these because the modifications were unstaged when git mv ran. Adds the 2026-05-21 status header to the plan and the upstream PR (janeczku#3607) link in kobo-popup-attempts.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When reading with a synced Kobo, users sometimes see a "Sync to last page read?" popup even though they've only been reading on that one device. The answer is always "no" and even when selecting "yes" it takes you to the same position. Previous fixes addressed related popup triggers but some still persisted. Fixes #3596 .
Background
The device uses
GET /v1/library/<uuid>/stateto fetch reading state when opening a book, andPUTto push progress updates while reading. GETs and PUTs are interspersed during a session; which one the session ends on appears to vary.The popup decision happens on GET.
Two relevant timestamp fields on
KoboReadingState:LastModified(LM) - generated by the device, sent in every PUT body, stored on each sub-record (bookmark, statistics, read status) and propagated to the parent row.PriorityTimestamp(PT) - conflict-detection field on the parent row only. Based on observed behavior, the device stores the PT from each GET response. If the next GET returns a newer PT, the device assumes another client made changes and could show the popup (e.g. the intended use case is syncing position across a Kobo device and the Kobo app, not something calibre-web supports.)Observed via proxy: official Kobo cloud appears to always return PT = LM = the device's own
LastModified, so the device always gets back a timestamp it recognizes.Root cause
Our server was stamping PT with
datetime.now()on every PUT. When the device next did a GET it saw a server-generated PT newer than its last confirmed one, which triggered the popup despite no real conflict or change on another client. If a session ended with a GET the device would confirm the new PT and the next open was fine; if it ended with a PUT, the next GET would show the mismatch and trigger the popup. That is why it was intermittent.Fix
Commit 2 (core fix): Read
LastModifiedfrom the PUT request body and use it as both LM and PT for all state saved in that request. The subsequent GET returns the device's own timestamp back, eliminating the mismatch. When state is changed outside a Kobo PUT, the flush hook falls back todatetime.now(), so PT still advances as before. Also fixes a minor issue wherebook_read.last_modifiedwas being written on every PUT even when read status hadn't changed.Commit 1 (prerequisite): Two things that would otherwise undermine commit 2:
priority_timestamphad its ownonupdate=datetime.now()independent of LM, so PT and LM could drift apart, which is itself a popup trigger. Removedonupdatefrom PT; the flush hook now sets both fields together.2d4ca23dadded LM and PT to the PUT responseUpdateResultsto let the device confirm the new PT without a GET. Based on observed behavior, that does not appear to work. The device seems not to persist reading-state timestamps from PUT responses. This change removes that response data again and instead keeps PT/LM aligned through the normal GET path, matching observed official Kobo cloud behavior.##Testing
I've been running this for a few weeks locally and have not seen the popup once.