Remove the buried Start This Split button from the exercise editor
ExerciseListView is reached only via Settings > Splits > split > Edit >
Exercises, so its toolbar start button was effectively undiscoverable and
duplicated the home-screen split picker (the sole remaining start path).
Strip the button and its now-dead start flow: the active-workout prompt,
end-and-restart handling, started-workout navigation, and the AppServices
dependency. Also drop the changelog entry for the watch-launch wiring of
that button (f01e149) since the button no longer exists and never shipped.
Claude-Session: https://claude.ai/code/session_01PVNBVKp5bcq52X722uMjwT
This commit is contained in:
@@ -2,8 +2,6 @@
|
||||
|
||||
A new Cardio exercise and matching starter split let you log aerobic sessions, tracked on your Apple Watch as a cardio workout.
|
||||
|
||||
Starting a workout with a split's Start This Split button now brings it up on your Apple Watch too, matching how starting one from the main list already worked.
|
||||
|
||||
A new Auto-Advance option lets a split flow hands-free from one exercise to the next, resting automatically between them.
|
||||
|
||||
Each split can now set its own rest time, overriding the app-wide default in Settings.
|
||||
|
||||
@@ -13,7 +13,6 @@ import SwiftData
|
||||
|
||||
struct ExerciseListView: View {
|
||||
@Environment(SyncEngine.self) private var sync
|
||||
@Environment(AppServices.self) private var services
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
// Resolve the split by id, not a captured entity: editing a seed's exercise from
|
||||
@@ -25,15 +24,6 @@ struct ExerciseListView: View {
|
||||
@State private var showingAddSheet: Bool = false
|
||||
@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 (see
|
||||
/// `navigatesToStartedWorkout`).
|
||||
@State private var pendingWorkoutID: String? = nil
|
||||
|
||||
@Query(sort: \Workout.start, order: .reverse)
|
||||
private var workouts: [Workout]
|
||||
|
||||
@State private var showingActivePrompt = false
|
||||
@AppStorage("weightUnit") private var weightUnit: WeightUnit = .lb
|
||||
|
||||
init(split: Split) {
|
||||
@@ -45,10 +35,6 @@ struct ExerciseListView: View {
|
||||
return splits.first { $0.id == id }
|
||||
}
|
||||
|
||||
private var activeWorkouts: [Workout] {
|
||||
workouts.filter { $0.status == .inProgress || $0.status == .notStarted }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let split {
|
||||
@@ -58,8 +44,6 @@ struct ExerciseListView: View {
|
||||
.task { dismiss() }
|
||||
}
|
||||
}
|
||||
// Navigate into the workout's log screen once the entity appears in the cache.
|
||||
.navigatesToStartedWorkout(pendingWorkoutID: $pendingWorkoutID)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
@@ -103,14 +87,6 @@ struct ExerciseListView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle(split.name)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button("Start This Split") {
|
||||
confirmAndStart()
|
||||
}
|
||||
.disabled(split.exercisesArray.isEmpty)
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingAddSheet) {
|
||||
ExercisePickerView(onExerciseSelected: { exerciseNames in
|
||||
addExercises(names: exerciseNames)
|
||||
@@ -138,53 +114,10 @@ struct ExerciseListView: View {
|
||||
} message: { item in
|
||||
Text("Remove \"\(item.name)\" from this split?")
|
||||
}
|
||||
.confirmationDialog(
|
||||
activePromptTitle,
|
||||
isPresented: $showingActivePrompt,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("End Current & Start New") { endActiveThenStart() }
|
||||
Button("Start in Parallel") { start() }
|
||||
Button("Cancel", role: .cancel) { showingActivePrompt = false }
|
||||
} message: {
|
||||
Text(activePromptMessage)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private var activePromptTitle: String {
|
||||
activeWorkouts.count == 1 ? "Workout in Progress" : "\(activeWorkouts.count) Workouts in Progress"
|
||||
}
|
||||
|
||||
private var activePromptMessage: String {
|
||||
let n = activeWorkouts.count
|
||||
let those = n == 1 ? "it" : "them"
|
||||
return "You already have \(n == 1 ? "a workout" : "\(n) workouts") going. End \(those) first, or run this one alongside."
|
||||
}
|
||||
|
||||
/// Prompt before starting if other workouts are still going; otherwise start straight away.
|
||||
private func confirmAndStart() {
|
||||
if activeWorkouts.isEmpty {
|
||||
start()
|
||||
} else {
|
||||
showingActivePrompt = true
|
||||
}
|
||||
}
|
||||
|
||||
/// End every in-flight workout (keeping its progress), then start this split.
|
||||
private func endActiveThenStart() {
|
||||
let toEnd = activeWorkouts.map { WorkoutDocument(from: $0) }
|
||||
showingActivePrompt = false
|
||||
Task {
|
||||
for var doc in toEnd {
|
||||
doc.endKeepingProgress()
|
||||
await sync.save(workout: doc)
|
||||
}
|
||||
}
|
||||
start()
|
||||
}
|
||||
|
||||
private func moveExercises(from source: IndexSet, to destination: Int) {
|
||||
guard let split else { return }
|
||||
var exercises = split.exercisesArray
|
||||
@@ -199,34 +132,6 @@ struct ExerciseListView: View {
|
||||
Task { await sync.save(split: doc) }
|
||||
}
|
||||
|
||||
private func start() {
|
||||
guard let split else { return }
|
||||
let startDate = Date()
|
||||
let logs = split.exercisesArray.enumerated().map { i, ex in
|
||||
WorkoutLogDocument(planFrom: ExerciseDocument(from: ex), order: i, date: startDate)
|
||||
}
|
||||
let doc = WorkoutDocument(
|
||||
schemaVersion: WorkoutDocument.currentSchemaVersion,
|
||||
id: ULID.make(),
|
||||
splitID: split.id,
|
||||
splitName: split.name,
|
||||
start: startDate,
|
||||
end: nil,
|
||||
status: WorkoutStatus.notStarted.rawValue,
|
||||
createdAt: startDate,
|
||||
updatedAt: startDate,
|
||||
logs: logs,
|
||||
restSeconds: split.restSeconds, autoAdvance: split.autoAdvance
|
||||
)
|
||||
Task {
|
||||
await sync.save(workout: doc)
|
||||
pendingWorkoutID = doc.id
|
||||
}
|
||||
// Bring the Apple Watch up into the session so the user can run it from the wrist,
|
||||
// tagged with the split's activity type — mirroring the split-picker start path.
|
||||
services.workoutLauncher.launchWatchWorkout(activityType: split.activityTypeEnum.hkActivityType)
|
||||
}
|
||||
|
||||
private func addExercises(names: [String]) {
|
||||
guard let split else { return }
|
||||
var doc = SplitDocument(from: split)
|
||||
|
||||
Reference in New Issue
Block a user