Files
workouts/Workouts/Screenshots/ScreenshotRootView.swift
T
rzen 6e440317c4 Restructure into a three-tab app with Progress, goals, and Meditation
The UX redesign's first landing (spec in UX-REDESIGN.md): ContentView
becomes a Today / Progress / Settings TabView, "Routine" replaces
"Split" in every user-facing string and view name (code-level types
keep their names), and workout starting moves to shared
WorkoutStarter / StartedWorkoutNavigator plumbing.

- New Progress tab: weekly goal streaks, workout trends, per-exercise
  weight progression, achievements, and the full history list
  (WorkoutLogsView -> WorkoutHistoryView).
- Goals: stable categories workouts roll up to, managed from Settings.
- New Meditation exercise + starter routine; timed sits record to
  Apple Health as Mind & Body sessions.

Claude-Session: https://claude.ai/code/session_012qw2itfzKyEJ1HpsFt8Ex4
2026-07-11 07:53:01 -04:00

79 lines
3.0 KiB
Swift

#if DEBUG
import SwiftUI
import SwiftData
/// DEBUG-only root used for App Store screenshot capture. Bypasses the iCloud gate and
/// renders one fully-formed screen (chosen by `--screen`) against the seeded cache, so
/// captures are deterministic with no UI automation. Never compiled into release.
struct ScreenshotRootView: View {
let services: AppServices
private var activeWorkout: Workout? {
let context = services.container.mainContext
var descriptor = FetchDescriptor<Workout>(sortBy: [SortDescriptor(\.start, order: .reverse)])
descriptor.fetchLimit = 25
let workouts = (try? context.fetch(descriptor)) ?? []
return workouts.first { $0.status == .inProgress } ?? workouts.first
}
var body: some View {
content
.environment(services)
.environment(services.syncEngine)
.environment(services.liveRunState)
.modelContainer(services.container)
}
@ViewBuilder
private var content: some View {
// The full tab shell and the Progress tab need no particular workout,
// so they're handled before the active-workout unwrap.
if ScreenshotSeed.screen(default: "workouts") == "today" {
ContentView()
} else if ScreenshotSeed.screen(default: "workouts") == "progress" {
ProgressTabView()
} else if ScreenshotSeed.screen(default: "workouts") == "progress-bottom" {
ProgressTabView(initialAnchor: .bottom)
} else if ScreenshotSeed.screen(default: "workouts") == "exercise-trends" {
NavigationStack { ExerciseTrendsListView() }
} else if let workout = activeWorkout {
switch ScreenshotSeed.screen(default: "workouts") {
case "exercise":
let logID = WorkoutDocument(from: workout).logs.first { $0.exerciseName == "Seated Row" }?.id
NavigationStack { ExerciseView(workout: workout, logID: logID ?? "") }
case "run":
ScreenshotRunView(workout: workout)
case "settings":
SettingsView()
default:
NavigationStack { WorkoutLogListView(workout: workout) }
}
} else {
Color(.systemBackground)
}
}
}
/// The paged run flow for the in-progress exercise, showing the animated form guide
/// (with machine props) — the screenshot works off its own local document copy, so
/// nothing persists.
private struct ScreenshotRunView: View {
@State private var doc: WorkoutDocument
private let logID: String
init(workout: Workout) {
let document = WorkoutDocument(from: workout)
_doc = State(initialValue: document)
logID = document.logs.first { $0.exerciseName == "Seated Row" }?.id
?? document.logs.first?.id ?? ""
}
var body: some View {
NavigationStack {
ExerciseProgressView(doc: $doc, logID: logID, onChange: {},
onLive: { _ in }, onLiveEnded: {}, incomingFrame: nil)
}
}
}
#endif