From d3a8090ae9d0ccda677cf8152f1d76ac0ee5da89 Mon Sep 17 00:00:00 2001 From: erik-keifer <69150393+erik-keifer@users.noreply.github.com> Date: Sat, 4 Apr 2026 22:27:49 -0700 Subject: [PATCH 1/4] Update SleepFocusApp.swift Fix: refresh smart alarm guidance when app returns to foreground --- SleepFocus/SleepFocusApp.swift | 41 ++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/SleepFocus/SleepFocusApp.swift b/SleepFocus/SleepFocusApp.swift index f7d1e7e..28e80f8 100644 --- a/SleepFocus/SleepFocusApp.swift +++ b/SleepFocus/SleepFocusApp.swift @@ -7,9 +7,11 @@ struct SleepFocusApp: App { @StateObject private var sleepPreferences = SleepPreferencesStore() @StateObject private var notificationSettings = NotificationSettingsStore() @StateObject private var appearanceStore = AppearanceStore() - @StateObject private var insightsStore = InsightsStore() private let healthAutoSyncService = HealthAutoSyncService.shared - + + // ✅ Fix: observe scene phase so we can detect app foregrounding + @Environment(\.scenePhase) private var scenePhase + var body: some Scene { WindowGroup { Group { @@ -20,7 +22,6 @@ struct SleepFocusApp: App { .environmentObject(sleepPreferences) .environmentObject(notificationSettings) .environmentObject(appearanceStore) - .environmentObject(insightsStore) } else if authManager.requiresProfileConfirmation { ConfirmProfileView(authManager: authManager) } else { @@ -31,19 +32,24 @@ struct SleepFocusApp: App { .task { await notificationSettings.requestAlarmPermissionsAtLaunchIfNeeded() } - .task(id: authManager.isAuthenticated) { - guard authManager.isAuthenticated else { return } - insightsStore.updateSleepGoalHours(sleepPreferences.sleepGoalHours) - await insightsStore.loadIfNeeded() - } - .task(id: sleepPreferences.sleepGoalHours) { - guard authManager.isAuthenticated else { return } - insightsStore.updateSleepGoalHours(sleepPreferences.sleepGoalHours) - } .task(id: authManager.isAuthenticated) { guard authManager.isAuthenticated else { return } await healthAutoSyncService.startIfNeeded(authManager: authManager) } + // ✅ Fix: when app comes back to foreground, force-refresh smart alarm + // guidance so the backend model result is used instead of the fallback + .onChange(of: scenePhase) { _, newPhase in + guard newPhase == .active, authManager.isAuthenticated else { return } + Task { + await sleepPreferences.refreshSmartAlarmCycleGuidance( + using: authManager, + force: true + ) + await sleepPreferences.syncSmartAlarmRuntime( + notificationSettings: notificationSettings + ) + } + } .onOpenURL { url in navigationManager.handleDeepLink(url) } @@ -59,6 +65,17 @@ struct SleepFocusApp: App { + + + + + + + + + + + From 43d626aadebe9299f4d226fc428a74f7416eb1e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Apr 2026 05:52:21 +0000 Subject: [PATCH 2/4] Remove emoji/prefix from comments and trailing blank lines in SleepFocusApp.swift Agent-Logs-Url: https://github.com/SleepFocus/SleepFocus_Frontend/sessions/a3bb8221-b5e4-45b0-b37c-98e64793f618 Co-authored-by: austinkimchi <40729751+austinkimchi@users.noreply.github.com> --- SleepFocus/SleepFocusApp.swift | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/SleepFocus/SleepFocusApp.swift b/SleepFocus/SleepFocusApp.swift index 28e80f8..f103547 100644 --- a/SleepFocus/SleepFocusApp.swift +++ b/SleepFocus/SleepFocusApp.swift @@ -9,7 +9,7 @@ struct SleepFocusApp: App { @StateObject private var appearanceStore = AppearanceStore() private let healthAutoSyncService = HealthAutoSyncService.shared - // ✅ Fix: observe scene phase so we can detect app foregrounding + // Observe scene phase to detect app foregrounding. @Environment(\.scenePhase) private var scenePhase var body: some Scene { @@ -36,8 +36,8 @@ struct SleepFocusApp: App { guard authManager.isAuthenticated else { return } await healthAutoSyncService.startIfNeeded(authManager: authManager) } - // ✅ Fix: when app comes back to foreground, force-refresh smart alarm - // guidance so the backend model result is used instead of the fallback + // When the app returns to foreground, force-refresh smart alarm guidance + // so the backend model result is used instead of the fallback. .onChange(of: scenePhase) { _, newPhase in guard newPhase == .active, authManager.isAuthenticated else { return } Task { @@ -56,28 +56,3 @@ struct SleepFocusApp: App { } } } - - - - - - - - - - - - - - - - - - - - - - - - - From 5690a4779c9d70d0db059542222db6725be4b4c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 5 Apr 2026 05:56:44 +0000 Subject: [PATCH 3/4] Reintroduce InsightsStore @StateObject and environmentObject injection Agent-Logs-Url: https://github.com/SleepFocus/SleepFocus_Frontend/sessions/6d87427a-7488-4920-8ffc-ca2ddb97e755 Co-authored-by: austinkimchi <40729751+austinkimchi@users.noreply.github.com> --- SleepFocus/SleepFocusApp.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/SleepFocus/SleepFocusApp.swift b/SleepFocus/SleepFocusApp.swift index f103547..197f738 100644 --- a/SleepFocus/SleepFocusApp.swift +++ b/SleepFocus/SleepFocusApp.swift @@ -7,6 +7,7 @@ struct SleepFocusApp: App { @StateObject private var sleepPreferences = SleepPreferencesStore() @StateObject private var notificationSettings = NotificationSettingsStore() @StateObject private var appearanceStore = AppearanceStore() + @StateObject private var insightsStore = InsightsStore() private let healthAutoSyncService = HealthAutoSyncService.shared // Observe scene phase to detect app foregrounding. @@ -22,6 +23,7 @@ struct SleepFocusApp: App { .environmentObject(sleepPreferences) .environmentObject(notificationSettings) .environmentObject(appearanceStore) + .environmentObject(insightsStore) } else if authManager.requiresProfileConfirmation { ConfirmProfileView(authManager: authManager) } else { @@ -32,6 +34,15 @@ struct SleepFocusApp: App { .task { await notificationSettings.requestAlarmPermissionsAtLaunchIfNeeded() } + .task(id: authManager.isAuthenticated) { + guard authManager.isAuthenticated else { return } + insightsStore.updateSleepGoalHours(sleepPreferences.sleepGoalHours) + await insightsStore.loadIfNeeded() + } + .task(id: sleepPreferences.sleepGoalHours) { + guard authManager.isAuthenticated else { return } + insightsStore.updateSleepGoalHours(sleepPreferences.sleepGoalHours) + } .task(id: authManager.isAuthenticated) { guard authManager.isAuthenticated else { return } await healthAutoSyncService.startIfNeeded(authManager: authManager) From d892c4eeff9dedebf5a49093a6e3c368cab540f0 Mon Sep 17 00:00:00 2001 From: Austin Kim <40729751+austinkimchi@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:53:46 -0700 Subject: [PATCH 4/4] refresh when no other refresh is in progress Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- SleepFocus/SleepFocusApp.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SleepFocus/SleepFocusApp.swift b/SleepFocus/SleepFocusApp.swift index 197f738..fc98731 100644 --- a/SleepFocus/SleepFocusApp.swift +++ b/SleepFocus/SleepFocusApp.swift @@ -52,10 +52,14 @@ struct SleepFocusApp: App { .onChange(of: scenePhase) { _, newPhase in guard newPhase == .active, authManager.isAuthenticated else { return } Task { + guard !sleepPreferences.isRefreshingSmartAlarmGuidance else { return } + await sleepPreferences.refreshSmartAlarmCycleGuidance( using: authManager, force: true ) + + guard !sleepPreferences.isRefreshingSmartAlarmGuidance else { return } await sleepPreferences.syncSmartAlarmRuntime( notificationSettings: notificationSettings )