diff --git a/KisaniCal/ISSUES.md b/KisaniCal/ISSUES.md index d1d1070..708cbd1 100644 --- a/KisaniCal/ISSUES.md +++ b/KisaniCal/ISSUES.md @@ -1215,3 +1215,33 @@ Added DEBUG-only test hooks (`KISANI_AUTOADD`, `KISANI_VOICE_SIM`) to inject a transcript on the simulator; `#if DEBUG`, compiled out of Release. Files: `TodayView.swift` (`NLTaskField.updateUIView`), `ContentView.swift`. + +--- + +## KC-39 — Workout state lost on reinstall/update (incomplete iCloud restore) + +**Status:** Fixed (build-verified) +**Reported by:** User +**Area:** Workout / iCloud sync + +### Description +Workout state was lost after app updates / fresh installs. + +### Root cause +`save()` pushes 7 workout keys to iCloud KVS (programs, schedule, activePid, +completedDates, history, missedDates, compensations), but `WorkoutViewModel.init` +only `restoreIfMissing(...)` for the first four. So **history, missed dates, and +rest-day compensations** were uploaded to iCloud but never restored on a fresh +launch — silently lost on reinstall/update. + +### Fix +Added the three missing `restoreIfMissing` calls (`history`, `missedDates`, +`compensations`) so restore is symmetric with save. (Per-day `lastActiveDay` is +transient set-reset state and intentionally not synced.) + +Files: `ExerciseModels.swift`. + +### Note +Cross-device *live* refresh while the app is open isn't wired (`WorkoutViewModel` +doesn't observe `kisaniCloudDataRefreshed`) — out of scope; the restore-on-launch +path is what preserves state across updates. diff --git a/KisaniCal/Models/ExerciseModels.swift b/KisaniCal/Models/ExerciseModels.swift index 151c9be..7240523 100644 --- a/KisaniCal/Models/ExerciseModels.swift +++ b/KisaniCal/Models/ExerciseModels.swift @@ -290,11 +290,15 @@ class WorkoutViewModel: ObservableObject { self.kMissedDates = "kisani.workout.missedDates.\(uid)" self.kCompensations = "kisani.workout.compensations.\(uid)" - // Restore all workout keys from iCloud if missing locally (fresh install / new build) + // Restore all workout keys from iCloud if missing locally (fresh install / new build). + // Must cover EVERY key save() pushes, or that state is lost on reinstall/update. CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.programs.\(uid)") CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.schedule.\(uid)") CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.activePid.\(uid)") CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.completedDates.\(uid)") + CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.history.\(uid)") + CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.missedDates.\(uid)") + CloudSyncManager.shared.restoreIfMissing(key: "kisani.workout.compensations.\(uid)") // ── Attempt to restore persisted state ── if let data = UserDefaults.kisani.data(forKey: kPrograms),