syncStatusExplanation function

String syncStatusExplanation(
  1. WalletLocalizations l10n,
  2. SyncStatus status, {
  3. required bool driving,
  4. bool startFailed = false,
  5. bool syncDisabled = false,
})

The plain-language sheet explanation of the CURRENT state (what it means, whether the balance is trustworthy, what — if anything — to do). Sheet-only copy; the badge headline stays the compact form above.

Implementation

String syncStatusExplanation(
  WalletLocalizations l10n,
  SyncStatus status, {
  required bool driving,
  bool startFailed = false,
  bool syncDisabled = false,
}) {
  // #383 R1: sync-off owns the slot on every arm (same shape as startFailed
  // below) — the honest answer to "what's going on" is that the HOST turned
  // syncing off, figures show the last synced state, and the way back is the
  // host's own settings (the copy points there, not at a package affordance).
  if (syncDisabled) return l10n.walletSyncExplainDisabled;
  // A failed START owns the explanation slot on EVERY arm (#356-F8): the
  // truthful answer to "what's going on" is that the loop isn't running —
  // an Idle "starts automatically, no action needed" AND a retained
  // UpToDate "your balance is current" both contradict the retry sitting
  // right below this text. The headline/figures still show the last-known
  // state; only the explanation flips.
  if (startFailed) return l10n.walletSyncExplainStartFailed;
  return switch (status) {
    SyncStatus_Idle() =>
      driving ? l10n.walletSyncExplainStarting : l10n.walletSyncExplainIdle,
    SyncStatus_Connecting() => l10n.walletSyncExplainConnecting,
    SyncStatus_Scanning() => l10n.walletSyncExplainScanning,
    SyncStatus_UpToDate() => l10n.walletSyncExplainUpToDate,
    SyncStatus_UpToDateLimited() => l10n.walletSyncExplainUpToDateLimited,
    SyncStatus_UpToDateDegraded() => l10n.walletSyncExplainUpToDateDegraded,
    SyncStatus_EndpointBehind() => l10n.walletSyncExplainEndpointBehind,
    // P3-12 (maintainer, Q2 option 2): under a REPORTED rewinding streak the
    // grace claim still wins the ranking (P2-6 — the countdown is never
    // hidden), but the explanation drops "your balance is current" and names
    // what the claim outranked: a server the loop judged misbehaving. Same next
    // step, "switch servers".
    SyncStatus_UpToDateUnverified(streakReported: true) =>
      l10n.walletSyncExplainUnverifiedStreak,
    SyncStatus_UpToDateUnverified() => l10n.walletSyncExplainUnverified,
    // #399: the connectivity stall tells the calm normal-offline story (funds
    // safe, last synced state, queued sends drain on a future online sync) —
    // the generic "hit a problem" explanation matches only the hard stalls.
    SyncStatus_Stalled(reason: StallReason.endpointUnreachable) =>
      l10n.walletSyncExplainStalledOffline,
    SyncStatus_Stalled() => l10n.walletSyncExplainStalled,
    SyncStatus_Offline() => l10n.walletSyncExplainOffline,
    SyncStatus_Unknown() => l10n.walletSyncExplainUnknown,
  };
}