Files
workouts/Workouts/WorkoutsApp.swift
T
rzen c05e83cff7 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
2026-07-08 12:48:12 -04:00

58 lines
2.0 KiB
Swift

//
// WorkoutsApp.swift
// Workouts
//
// Copyright 2025 Rouslan Zenetl. All Rights Reserved.
//
import SwiftUI
import SwiftData
import UIKit
@main
struct WorkoutsApp: App {
@State private var services = AppServices()
@Environment(\.scenePhase) private var scenePhase
var body: some Scene {
WindowGroup {
#if DEBUG
if ScreenshotSeed.isActive {
ScreenshotRootView(services: services)
} else {
root
}
#else
root
#endif
}
// Keep the screen lit for the whole app, not just while logging — the phone is
// often propped up across the room during a workout. iOS clears this flag when
// the app is backgrounded, so re-assert it each time the scene becomes active.
.onChange(of: scenePhase, initial: true) { _, phase in
UIApplication.shared.isIdleTimerDisabled = (phase == .active)
// Last chance before suspension: push any queued document writes out
// now rather than waiting out a retry backoff we may not live to see.
if phase == .background {
Task { await services.syncEngine.flushPendingWrites() }
}
}
}
private var root: some View {
RootGateView()
.environment(services)
.environment(services.syncEngine)
.environment(services.liveRunState)
.modelContainer(services.container)
.task { await services.bootstrap() }
// Tap a shared ".workoutsbackup" file (Files, AirDrop, share sheet) to
// restore it. The controller stops the sync observer for the restore and
// rebuilds the cache afterward (see AppBackupConfiguration).
.onOpenURL { url in
guard url.pathExtension == "workoutsbackup" else { return }
Task { try? await services.backupController.restoreBackup(from: url) }
}
}
}