Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add reading progress sync to API and web UI - #8683

Open
KPLauritzen wants to merge 5 commits into
wallabag:masterfrom
KPLauritzen:api-sync
Open

Add reading progress sync to API and web UI#8683
KPLauritzen wants to merge 5 commits into
wallabag:masterfrom
KPLauritzen:api-sync

Conversation

@KPLauritzen

Copy link
Copy Markdown

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

  • API reading_progress syncs percentage read (0-100), but localStorage syncs how many View Heights have been scrolled. They are not the same thing. Should they be?

Changes

  • 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

Answers from template

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Documentation OpenAPI docs, no userfacing docs yet
Translation no
CHANGELOG.md no
License MIT

KPLauritzen and others added 5 commits February 14, 2026 07:57
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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add reading progress to API

1 participant