Fix double navigation on workout log row tap

A row tap pushed twice: a value-based navigationDestination(for: String.self)
collided with the row's NavigationLink(value:), surfacing a duplicate split list
over the hidden exercise detail. Rows now use a destination-based NavigationLink,
leaving navigationDestination(item:) as the view's only destination.
This commit is contained in:
2026-06-19 15:35:06 -04:00
parent ffd301f855
commit c44cdd3f90
2 changed files with 13 additions and 7 deletions
+5
View File
@@ -20,3 +20,8 @@ All notable changes to this project are documented here.
- Fixed: workout marked complete on creation, an undismissable delete dialog, - Fixed: workout marked complete on creation, an undismissable delete dialog,
toolbar buttons hidden by nested navigation stacks, and a placeholder toolbar buttons hidden by nested navigation stacks, and a placeholder
"Settings coming soon" row. "Settings coming soon" row.
- Fixed: tapping an exercise in a workout log pushed the wrong screen (a
duplicate of the split list) with the exercise detail hidden underneath — a
single row tap was navigating twice. Caused by stacking two
`navigationDestination` modifiers on the log list; rows now use a single
destination-based link.
@@ -26,9 +26,11 @@ struct WorkoutLogListView: View {
@State private var logToDelete: WorkoutLogDocument? @State private var logToDelete: WorkoutLogDocument?
@State private var addedLog: AddedLogRoute? @State private var addedLog: AddedLogRoute?
/// Wrapper so the programmatic push after adding an exercise uses a distinct /// Drives the programmatic push into a freshly-added exercise via
/// `navigationDestination(item:)` and doesn't collide with the value-based /// `navigationDestination(item:)`. Rows navigate with plain destination-based
/// row links registered for `String`. /// `NavigationLink`s, so this is the only `navigationDestination` in the view
/// stacking a second one (e.g. a value-based `for: String.self`) made a single
/// row tap push twice.
private struct AddedLogRoute: Identifiable, Hashable { let id: String } private struct AddedLogRoute: Identifiable, Hashable { let id: String }
init(workout: Workout) { init(workout: Workout) {
@@ -65,7 +67,9 @@ struct WorkoutLogListView: View {
Form { Form {
Section(header: Text(label)) { Section(header: Text(label)) {
ForEach(sortedLogs) { log in ForEach(sortedLogs) { log in
NavigationLink(value: log.id) { NavigationLink {
ExerciseView(workout: workout, logID: log.id)
} label: {
CheckboxListItem( CheckboxListItem(
status: workoutStatus(log).checkboxStatus, status: workoutStatus(log).checkboxStatus,
title: log.exerciseName, title: log.exerciseName,
@@ -96,9 +100,6 @@ struct WorkoutLogListView: View {
} }
} }
} }
.navigationDestination(for: String.self) { logID in
ExerciseView(workout: workout, logID: logID)
}
.navigationDestination(item: $addedLog) { route in .navigationDestination(item: $addedLog) { route in
// Seed with our working doc so the brand-new log is available before // Seed with our working doc so the brand-new log is available before
// the cache catches up. // the cache catches up.