Open new workouts directly and improve accessibility
Starting a workout — from the split picker or a split's exercise list — now drops straight into its log screen once the cache catches up, via a shared StartedWorkoutNavigator. Adds VoiceOver labels/values to the log checkboxes and the settings button, a color-independent numbered legend and spoken summary to the heart-rate-zone bar, and Dynamic Type scaling to the run-flow badges and timer. Claude-Session: https://claude.ai/code/session_01HJDQQDA9QdP8zByg43H5v3
This commit is contained in:
@@ -13,7 +13,6 @@ import SwiftData
|
||||
|
||||
struct ExerciseListView: View {
|
||||
@Environment(SyncEngine.self) private var sync
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
// Resolve the split by id, not a captured entity: editing a seed's exercise from
|
||||
@@ -26,9 +25,9 @@ struct ExerciseListView: View {
|
||||
@State private var itemToEdit: Exercise? = nil
|
||||
@State private var itemToDelete: Exercise? = nil
|
||||
/// ID of the just-created workout; drives programmatic navigation once the
|
||||
/// cache observer delivers the entity a beat after the file write.
|
||||
/// cache observer delivers the entity a beat after the file write (see
|
||||
/// `navigatesToStartedWorkout`).
|
||||
@State private var pendingWorkoutID: String? = nil
|
||||
@State private var resolvedWorkout: Workout? = nil
|
||||
|
||||
@Query(sort: \Workout.start, order: .reverse)
|
||||
private var workouts: [Workout]
|
||||
@@ -58,15 +57,8 @@ struct ExerciseListView: View {
|
||||
.task { dismiss() }
|
||||
}
|
||||
}
|
||||
// Navigate to the workout log once the entity appears in the cache.
|
||||
.navigationDestination(item: $resolvedWorkout) { workout in
|
||||
WorkoutLogListView(workout: workout)
|
||||
}
|
||||
// Poll for the entity after we write the document.
|
||||
.onChange(of: pendingWorkoutID) { _, id in
|
||||
guard let id else { return }
|
||||
pollForWorkout(id: id)
|
||||
}
|
||||
// Navigate into the workout's log screen once the entity appears in the cache.
|
||||
.navigatesToStartedWorkout(pendingWorkoutID: $pendingWorkoutID)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
@@ -192,22 +184,6 @@ struct ExerciseListView: View {
|
||||
start()
|
||||
}
|
||||
|
||||
private func pollForWorkout(id: String) {
|
||||
Task {
|
||||
// Give the file→observer→cache loop a moment to complete (typically < 1 s).
|
||||
for _ in 0..<20 {
|
||||
try? await Task.sleep(for: .milliseconds(150))
|
||||
if let workout = CacheMapper.fetchWorkout(id: id, in: modelContext) {
|
||||
resolvedWorkout = workout
|
||||
pendingWorkoutID = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
// If still not available after ~3 s, clear the pending ID silently.
|
||||
pendingWorkoutID = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func moveExercises(from source: IndexSet, to destination: Int) {
|
||||
guard let split else { return }
|
||||
var exercises = split.exercisesArray
|
||||
|
||||
Reference in New Issue
Block a user