Let routines rename exercises and repeat them for interval segments

An exercise's name is now a per-routine display name: a new optional
libraryName on ExerciseDocument (snapshotted onto WorkoutLogDocument at
plan time) keeps the link to the bundled library exercise, and every
figure/info/cue lookup resolves libraryName ?? name. Deliberately not
schema-bumped — an older app dropping the key only strands the
figure link, same rationale as activityType. Cache schema bumped to 9
for the new columns.

The picker no longer filters out exercises already in the routine
(an "×N" badge marks them instead), exercise rows gain a leading
Duplicate swipe that clones an entry in place, and the edit sheet gets
a Name field with the library exercise shown read-only above it.

Claude-Session: https://claude.ai/code/session_01H8VxUX4ckjU3vRF5M4L5FV
This commit is contained in:
2026-07-12 18:38:14 -04:00
parent d04526826c
commit df5c77eee1
15 changed files with 203 additions and 38 deletions
+7 -4
View File
@@ -17,7 +17,7 @@ extension ExerciseDocument {
init(from e: Exercise) {
self.init(id: e.id, name: e.name, order: e.order, sets: e.sets, reps: e.reps,
weight: e.weight, loadType: e.loadType, durationSeconds: e.durationTotalSeconds,
machineSettings: e.machineSettings)
machineSettings: e.machineSettings, libraryName: e.libraryName)
}
}
@@ -41,7 +41,8 @@ extension WorkoutLogDocument {
status: log.statusRaw, notes: log.notes, date: log.date,
machineSettings: log.machineSettings,
startedAt: log.startedAt, completedAt: log.completedAt,
setEntries: log.setEntries, updatedAt: log.logUpdatedAt)
setEntries: log.setEntries, updatedAt: log.logUpdatedAt,
libraryName: log.libraryName)
}
}
@@ -164,7 +165,7 @@ enum CacheMapper {
private static func makeExercise(_ d: ExerciseDocument) -> Exercise {
Exercise(id: d.id, name: d.name, order: d.order, sets: d.sets, reps: d.reps, weight: d.weight,
loadType: d.loadType, durationTotalSeconds: d.durationSeconds,
machineSettings: d.machineSettings)
machineSettings: d.machineSettings, libraryName: d.libraryName)
}
private static func apply(_ d: ExerciseDocument, to e: Exercise) {
@@ -176,6 +177,7 @@ enum CacheMapper {
e.loadType = d.loadType
e.durationTotalSeconds = d.durationSeconds
e.machineSettings = d.machineSettings
e.libraryName = d.libraryName
}
// MARK: Workout
@@ -228,7 +230,7 @@ enum CacheMapper {
currentStateIndex: d.currentStateIndex, statusRaw: d.status,
notes: d.notes, date: d.date, machineSettings: d.machineSettings,
startedAt: d.startedAt, completedAt: d.completedAt,
setEntries: d.setEntries, logUpdatedAt: d.updatedAt)
setEntries: d.setEntries, logUpdatedAt: d.updatedAt, libraryName: d.libraryName)
}
private static func apply(_ d: WorkoutLogDocument, to l: WorkoutLog) {
@@ -248,6 +250,7 @@ enum CacheMapper {
l.completedAt = d.completedAt
l.setEntries = d.setEntries
l.logUpdatedAt = d.updatedAt
l.libraryName = d.libraryName
}
// MARK: Schedule