Files
readest/apps/readest-app/src/components/settings/integrations/cloudSync.ts
T
Huang Xin 942c062d35 fix(sync): decouple Readest Cloud storage quota from third-party cloud sync (#4959) (#4971)
When a third-party provider (WebDAV or Google Drive) is the selected
cloud sync backend, Readest Cloud storage is no longer written to:

- New src/services/sync/cloudSyncProvider.ts policy module: the selected
  provider is derived from the existing per-device enabled flags
  (webdav wins deterministically if both are ever set); the premium
  guard resolves to a PAUSED state instead of silently falling back to
  Readest Cloud, with the user plan cached for non-React modules.
- transferManager gates book uploads on the selected provider: queueUpload
  returns null when gated; pending book uploads from before a provider
  switch are visibly cancelled (cancelReason policy) and pruned on the
  next restore; downloads and replica transfers are never gated.
- Book uploads are deferred until settings hydrate (settings.version
  barrier) so a persisted queue cannot be mis-processed at startup;
  replica transfers are not stalled.
- Quota-exceeded uploads fail fast with zero retries, and a batch import
  produces one summary toast instead of one toast per book.
- Policy cancellations are a distinct bucket via a shared predicate:
  excluded from failed stats, Retry All, and the per-item Retry button.
- Auto-upload call sites (ingest, OPDS, subscriptions) check the provider
  gate; the explicit Upload Book action explains the gate with a toast
  instead of silently doing nothing.
- Activating a provider auto-enables its syncBooks so books keep backing
  up somewhere; a one-time migration (20260706) applies the same flip for
  users who already had a provider enabled.
- webdav.deviceId and webdav.lastSyncedAt are excluded from backups,
  matching the existing googleDrive entries.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 17:31:15 +02:00

34 lines
1.4 KiB
TypeScript

import type { SystemSettings } from '@/types/settings';
import type { FileSyncBackendKind } from '@/services/sync/file/providerRegistry';
/**
* Return settings with exactly one third-party cloud-sync provider active (or
* none). WebDAV and Google Drive are mutually exclusive — only one syncs the
* library at a time — so enabling one always disables the other. Provider config
* (WebDAV creds, the Drive keychain token) is left untouched, so switching back
* to a previously-configured provider needs no re-entry; only an explicit
* Disconnect tears a provider's config down.
*
* Activating a provider (disabled -> enabled) also turns its `syncBooks` on:
* the selected provider owns the book-file channel — native Readest Cloud
* uploads gate off — so leaving syncBooks at its `false` default would back
* books up nowhere. An explicit opt-out while the provider stays active is
* respected (re-activation of an already-active provider changes nothing).
*/
export const withActiveCloudProvider = (
settings: SystemSettings,
active: FileSyncBackendKind | null,
): SystemSettings => ({
...settings,
webdav: {
...settings.webdav,
enabled: active === 'webdav',
...(active === 'webdav' && !settings.webdav?.enabled ? { syncBooks: true } : {}),
},
googleDrive: {
...settings.googleDrive,
enabled: active === 'gdrive',
...(active === 'gdrive' && !settings.googleDrive?.enabled ? { syncBooks: true } : {}),
},
});