Add reading progress sync to API and web UI - #8683
Open
KPLauritzen wants to merge 5 commits into
Open
Conversation
Persist reading progress (0-100%) per article in the database so it
syncs across devices. Previously, scroll position was only stored in
browser localStorage and lost when switching devices.
- Add reading_progress and reading_progress_updated_at columns to the
Entry entity with last-write-wins conflict resolution
- Add database migration for the new columns
- Update API POST/PATCH endpoints to accept reading_progress and
reading_progress_updated_at parameters with OpenAPI annotations
- Add web controller POST /reading-progress/{id} with CSRF protection
for session-authenticated browser sync
- Rewrite scroll_storage_controller.js to sync progress to server
(debounced 2s) and restore from server or localStorage on page load
- Validate timestamp format in API, rejecting invalid values with 400
- Add API tests covering PATCH, GET, bounds clamping, and conflict
resolution
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Wrap the JS fetch in a retry helper (3 retries, exponential backoff at 5s/10s/20s, no retry on 4xx). Add a 5-second per-entry rate limit in both the web and API controllers, returning 429 when exceeded. Update tests to account for the new rate limit. Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Refactor applyReadingProgress() to use guard clauses and extract parseTimestamp(), matching the controller's existing style - Add docblocks to reading_progress tests explaining clamping and conflict resolution - Remove misleading default=0 from OpenAPI spec for reading_progress on POST and PATCH endpoints (missing value means "leave unchanged", not "reset to 0") Co-Authored-By: Claude Opus 4.6 <[email protected]>
The server-side 5-second rate limit and client-side retry with exponential backoff are not used by any other feature in the codebase and add unnecessary complexity. The 2-second debounce already prevents excessive requests, and the timestamp-based conflict resolution in Entry::updateReadingProgress() already ignores stale updates. - Remove 5-second rate-limit check from EntryController and EntryRestController - Replace syncWithRetry() with a simple syncProgress() fetch call - Remove rate-limit workaround scaffolding from tests Co-Authored-By: Claude Opus 4.6 <[email protected]>
Multi-request tests need to call createAuthorizedClient() before each request, matching the pattern used throughout the test file. Co-Authored-By: Claude Opus 4.6 <[email protected]>
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.
Persist reading progress (0-100%) per article in the database so it syncs across devices. Previously, scroll position was only stored in browser localStorage and lost when switching devices.
NOTE: This PR was created with most of the actual code changes done by Claude Code. If you dont want to review AI code or are just generally against it, feel free to close this PR. I don't want to put extra burden on the maintainers.
Fixes #2643
Questions
Changes
Answers from template