Skip to content

[Sync] 7 - Show backup status #285

Description

@KacperKozak

Parent

What to build

The Rider-facing half: one setting, one choice, one status line.

The setting. An App Setting, "Back up over Wi-Fi only", defaulting to off. When it is on, nothing syncs until the phone is on an unmetered connection — mid-ride included. There are no row classes, no backlog thresholds and no partial exceptions. A switch that partly ignores the Rider is worse than one that does not exist. The setting lives in a synced table, so it restores with everything else.

The choice. The Rider is offered it once, in the flow where backup is turned on, with the pending volume shown, so the only expensive moment in the feature's life — the first upload on a phone with months of history — is a decision they made rather than one that happened to them. Afterwards it is an ordinary settings row.

The status line. The account widget on the social sheet already renders sign-in state and is the most-seen surface in the app. It gains a line:

signed out    -> the existing sign-in affordance, with a hint that names backup
up to date    -> with a relative time
syncing       -> with a pending count
waiting for Wi-Fi
offline
paused        -> sign in again / update required / backup error

Native owns the state and actionable pause reason and emits both; JS renders them. Every paused reason also raises a notification: it does not resolve through ordinary retry, and a backup that has silently stopped for weeks is the failure this feature can least afford.

Failures become Diagnostic Events, so the existing event log is the debugging surface and no new error UI is invented. Permanent failures are coalesced by error class/table/cursor and contain metadata only, so one poison row cannot create one new pending Diagnostic Event per retry.

Per AGENTS.md, any reusable component or new visual state added here needs its preview in the component showcase under src/app/settings/components/.

Likely files

  • src/modules/profile/components/AccountWidget.tsx - the widget that gains the status line, in both its signed-in and signed-out branches
  • src/screens/main/overlays/TopBar.tsx - where the widget is mounted into the social sheet
  • modules/vescape-core/src/index.ts - the state native emits and the event JS subscribes to
  • src/modules/settings/store/ - the app setting and its default
  • src/app/settings/other.tsx - where a backup settings row plausibly belongs
  • modules/vescape-core/android/src/main/java/expo/modules/vescapecore/diagnostics/DiagnosticReporter.kt - how failures become Diagnostic Events
  • modules/vescape-core/android/src/main/java/expo/modules/vescapecore/notification/ - the existing notification surface for the paused state
  • src/app/settings/components/ - the component showcase entry

Implementation hints

AccountWidget has three branches — loading, signed out, signed in — and the signed-in branch already has an identity block with a secondary text line. The status belongs there rather than as a fourth branch.

The signed-out hint currently reads as generic online-features wording. Backup is now the concrete reason to sign in; say so.

Diagnostic Events are uploaded, so a failure payload must not carry the Device Token, a server URL with credentials in it, or row contents.

docs/agents/react.md covers the icon and UI conventions; docs/design.md covers the visual language. Follow the existing widget surface rather than introducing a new card style.

The pending volume shown at the one-time choice comes from the same per-table pending counts the uploader already computes — do not add a second counting path.

Acceptance criteria

  • "Back up over Wi-Fi only" exists as an app setting, defaults to off, and syncs like any other setting
  • With it on, nothing uploads on a metered connection, including during a ride
  • With it off, uploads happen on any connection
  • The Rider is offered the choice once when backup is turned on, with the pending volume shown
  • The account widget shows every backup state and distinguishes paused sign-in, update-required and backup-error reasons
  • The signed-out hint names backup as a reason to sign in
  • Every paused reason raises a matching actionable notification as well as showing in the widget
  • Permanent sync failures appear once per failure fingerprint in the existing Diagnostic Event log, not once per retry
  • No Diagnostic Event payload contains the Device Token, row contents, coordinates, opaque server body or SQL
  • New or changed components have showcase previews

Blocked by

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreApp shell, storage, lifecycle, infraarea:designDesign system, theme, and color tokensarea:syncBackup sync — native uploader, Sync Cursors, Sync Actions, Device Tokencomplexity:mediumNeeds care, moderate integration surface. Use sonnet.ready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions