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
+2
View File
@@ -56,6 +56,7 @@ SwiftData cache entity (`Shared/Model/Entities.swift`) kept in sync by
| `loadType` | Int | | Raw `LoadType` |
| `durationSeconds` | Int | | Total seconds; 0 when not a timed exercise |
| `machineSettings` | [MachineSetting] | ✓ | Ordered machine comfort settings; nil → not a machine exercise, empty → machine exercise with nothing recorded. Doubles as the machine-based flag |
| `libraryName` | String | ✓ | The library exercise `name` was customized from (e.g. one Treadmill segment renamed "Brisk Walk 10 min"); nil → `name` IS the library name. Figure/info/cue lookups resolve `libraryName ?? name`, never `name` directly. *Not schema-bumped* |
## WorkoutDocument — `currentSchemaVersion: 5`
@@ -98,6 +99,7 @@ SwiftData cache entity (`Shared/Model/Entities.swift`) kept in sync by
| `completedAt` | Date | ✓ | Last move to `.completed`. *Not schema-bumped* |
| `setEntries` | [SetEntry] | ✓ | Per-set actuals in set order; nil → legacy file / nothing recorded. Appended as sets complete (pre-filled from the plan); `transition(to:)` fills the missing tail on `.completed` and clears on `.notStarted`; `.skipped` keeps partials. Added in schema v4 |
| `updatedAt` | Date | ✓ | Per-log modification time driving the per-log merge (`WorkoutMergePlanner`); stamped by `transition(to:)` on status flips and `touch()` at content-only edit sites. Nil in files written before v5. Added (unused) in schema v4, written since v5 |
| `libraryName` | String | ✓ | Plan-time snapshot of the exercise's `libraryName` (like sets/reps/weight); nil → `exerciseName` IS the library name. *Not schema-bumped* |
## MachineSetting (embedded in ExerciseDocument and WorkoutLogDocument)