Queue document writes durably and surface sync trouble in the UI
iCloud Drive writes now flow through a persistent WriteBacklog sidecar (drained with backoff, flushed on backgrounding, wiped with the cache on account change), so a save can never be lost to a transient coordinator error. A status banner on the workout list surfaces stuck syncing. Also: the split picker gains a Recent section with day labels, split rows fold SplitItem into SplitListView, and list rows dim the multiply sign in sets-by-reps. Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// SyncStatusBanner.swift
|
||||
// Workouts
|
||||
//
|
||||
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Surfaces the write queue's banner tiers at the bottom of the main screen.
|
||||
/// Tier 0 (fresh writes, silent retries) shows nothing; tier 1 is a calm
|
||||
/// "changes pending" capsule that clears itself on success; tier 2 is a
|
||||
/// prominent fault that opens Diagnostics.
|
||||
struct SyncStatusBanner: View {
|
||||
@Environment(SyncEngine.self) private var sync
|
||||
@State private var showingDiagnostics = false
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
switch sync.writeQueueState {
|
||||
case .idle, .pending:
|
||||
EmptyView()
|
||||
case .retrying:
|
||||
HStack(spacing: 8) {
|
||||
ProgressView()
|
||||
.controlSize(.small)
|
||||
Text("Changes pending — retrying…")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 8)
|
||||
.background(.regularMaterial, in: Capsule())
|
||||
.padding(.bottom, 6)
|
||||
case .fault(let message):
|
||||
Button {
|
||||
showingDiagnostics = true
|
||||
} label: {
|
||||
HStack(alignment: .firstTextBaseline, spacing: 10) {
|
||||
Image(systemName: "exclamationmark.icloud.fill")
|
||||
.foregroundStyle(.white)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(message)
|
||||
.font(.footnote.weight(.semibold))
|
||||
.foregroundStyle(.white)
|
||||
.multilineTextAlignment(.leading)
|
||||
Text("Your changes are safe on this iPhone. Tap for diagnostics.")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.white.opacity(0.85))
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 14)
|
||||
.padding(.vertical, 10)
|
||||
.background(.red.gradient, in: RoundedRectangle(cornerRadius: 14))
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, 6)
|
||||
.sheet(isPresented: $showingDiagnostics) {
|
||||
NavigationStack { DiagnosticsView() }
|
||||
}
|
||||
}
|
||||
}
|
||||
.animation(.default, value: sync.writeQueueState)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user