Fix boundary bugs, route side effects through MoodLogger, add data listeners

- Fix ExtensionDataProvider <= boundary to < in date queries (prevented cross-day leaks)
- Replace force-unwraps with guards and add error logging in DataControllerGET and ExtensionDataProvider
- Route DayViewViewModel update/delete through MoodLogger.shared (was duplicating side effects)
- Add data listeners to InsightsViewModel and YearViewModel for cross-tab refresh
- Add HealthKitManager.deleteMood(for:) for single-date cleanup
- Add SharedModelContainer.isUsingInMemoryFallback flag with critical logging
- Add analytics events: entryDeleted, allDataCleared, duplicatesRemoved, storageFallbackActivated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-14 23:34:09 -06:00
parent 0e8738794b
commit 7c142568be
8 changed files with 157 additions and 39 deletions

View File

@@ -7,7 +7,6 @@
import SwiftUI
import SwiftData
import WidgetKit
@MainActor
class DayViewViewModel: ObservableObject {
@@ -61,25 +60,8 @@ class DayViewViewModel: ObservableObject {
}
public func update(entry: MoodEntryModel, toMood mood: Mood) {
if !DataController.shared.update(entryDate: entry.forDate, withMood: mood) {
if !MoodLogger.shared.updateMood(entryDate: entry.forDate, withMood: mood) {
print("Failed to update mood entry")
return
}
// Sync to HealthKit for past day updates (only if user has full access)
guard mood != .missing && mood != .placeholder else { return }
let healthKitEnabled = GroupUserDefaults.groupDefaults.bool(forKey: UserDefaultsStore.Keys.healthKitEnabled.rawValue)
let hasAccess = !IAPManager.shared.shouldShowPaywall
if healthKitEnabled && hasAccess {
Task {
try? await HealthKitManager.shared.saveMood(mood, for: entry.forDate)
}
}
// Reload widgets asynchronously to avoid UI delay
Task { @MainActor in
WidgetCenter.shared.reloadAllTimelines()
}
}
@@ -95,13 +77,9 @@ class DayViewViewModel: ObservableObject {
entriesToDelete.append(obj)
}
entriesToDelete.forEach({ entry in
let entryDate = entry.forDate
DataController.shared.modelContext.delete(entry)
self.add(mood: .missing, forDate: entryDate, entryType: .listView)
MoodLogger.shared.deleteMood(forDate: entry.forDate)
})
}
DataController.shared.save()
}
static func updateTitleHeader(forEntry entry: MoodEntryModel?) -> String {