Files
readest/apps/readest-app/TODOS.md
T
Huang Xin e08622b416 feat(sync): route library sync exclusively to the selected cloud provider (#4380) (#4975)
While WebDAV or Google Drive is the selected cloud sync backend, the
native Readest Cloud book/progress/note channels are gated off and the
file-sync engine owns library data end to end:

- isSyncCategoryEnabled returns false for book/progress/note (and their
  legacy aliases) when a third-party provider is selected. A runtime
  override, deliberately not written into syncCategories: the user's own
  toggles persist and take effect again on switch-back. Account channels
  (settings, stats, dictionaries, fonts, textures, OPDS catalogs) always
  stay native.
- persistActiveCloudProvider is the single write path for provider
  switching, used by the chooser, both connect/disconnect flows, and the
  Drive OAuth callback (which previously bypassed the cross-window
  broadcast). The broadcast carries ONLY the enabled flags plus
  providerSelectedAt, never credentials or sync cursors, and only on
  switch events, so a stale window's routine save cannot revert a switch.
- buildWebDAVConnectSettings no longer pre-sets enabled: activation
  belongs to withActiveCloudProvider, so the fresh-connect path now gets
  the syncBooks auto-flip and the providerSelectedAt stamp.
- Sync health: fileSyncStore records lastError per backend; the durable
  lastSyncedAt stays in provider settings. The SettingsMenu sync row
  reads Synced via provider / Sync failed and its tap (with pull to
  refresh and BackupWindow, all routed through pullLibrary) runs the
  file engine via the shared runActiveFileLibrarySync helper instead of
  a gated native pull that would toast undefined book(s) synced.
- Mixed-fleet detection: while gated, the auto-sync interval runs a
  read-only probe of /api/sync since providerSelectedAt; any newer book
  row means another device still syncs natively, and a once-per-session
  notice explains the fork instead of leaving it silent.
- Readest-Cloud-only affordances hide while a third-party provider is
  selected: the quota row becomes a caption naming the active provider,
  Auto Upload disappears from the menu and command palette, the
  BookItem upload badge and the Transfer Queue Upload All button hide.
- providerSelectedAt added to both provider settings types and the
  backup blacklist.

Stacked on the quota-decoupling change for #4959; requires the
metadata-parity change so gated channels lose nothing users can see.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 18:05:54 +02:00

3.3 KiB

TODOS

Cloud Sync provider selection follow-ups (deferred by /autoplan, 2026-07-06)

Deferred from the Cloud Sync provider-selection plan (#4959/#4380). See the Decision Audit Trail in the plan for reasoning.

  • Pre-switch "download all Readest Cloud books" affordance so a fresh device gets full library completeness when a third-party provider is selected. (S)
  • Library-page sync-status indicator for the active third-party provider (fileSyncStore already exposes aggregate progress). (S)
  • Account page active-provider chip. (XS)
  • File-engine parity: reading stats + per-book viewSettings sync via the file layout (readingStatus/tags parity shipped as its own PR). (M)
  • Server-side quota error code (code: 'quota_exceeded', mirroring the share import route) so the client stops string-matching 'Insufficient storage quota'; message drift silently restores retry behavior. (S)
  • Pre-existing: Manage Sync "Books" category gates metadata rows but NOT binary uploads to Readest Cloud (queueUpload never consults isSyncCategoryEnabled('book') despite the category docs claiming it) — align behavior or docs. (S)
  • Sentry cloudSyncProvider tag: Sentry tagging is Rust-mediated (set_webview_info pattern in sentry_config.rs); add a set_cloud_sync_provider command + before_send tag so sync-related reports carry the active provider. Console log lines ship in the meantime. (S, needs src-tauri)

Deferred items from the Edge TTS Web Audio plan review (/autoplan, 2026-07-04). Each was explicitly deferred, not forgotten — see the Decision Audit Trail in .agents/plans/2026-07-03-edge-tts-webaudio.md.

TTS listening engine follow-ups

  • Cross-section gapless playback: preload and schedule the next section's first sentence so chapter boundaries are as seamless as sentence boundaries. (M)
  • Buffer-ahead indicator in the TTS scrubber (show the prefetched region, YouTube-style). (S)
  • Lock-screen ±10s seek offsets in addition to prev/next sentence. (S)
  • Persist measured sentence durations per book so a reopened chapter starts with an exact timeline instead of estimates. (S)
  • Worker offload for decode + WSOLA if device profiling shows main-thread jank on low-end Android. (S)
  • Sticky TTSBar scrubber (panel + lock screen only in the first release; recorded as deliberate in decision #24). (S)
  • Provider-agnostic voice source hedge: local neural TTS (e.g. Piper/Kokoro WASM) plugging into WebAudioPlayer/SectionTimeline — the engine is designed for this; see "Strategic framing" in the plan. (L)
  • Background chapter prefetch (convert timeline estimates to exact durations ahead of playback). (M)
  • Background TTS: decouple session ownership from the reader view via an app-level TTSSessionManager so closing the book keeps TTS playing (headless text supply via section.createDocument(), CFI re-anchoring for highlights on reattach, library now-playing pill). Decided matrix: close book = keep playing; reopen same book = seamless reattach (adopt session, redispatchPosition, lazy doc swap at next section); open a DIFFERENT book = TTS stops; explicit stop / sleep timer = stops. (M)