Fix 25 audit issues: memory leaks, concurrency, performance, accessibility

Address findings from comprehensive audit across 5 workstreams:

- Memory: Token-based DataController listeners (prevent closure leaks),
  static DateFormatters, ImageCache observer cleanup, MotionManager
  reference counting, FoundationModels dedup guard
- Concurrency: Replace Task.detached with Task in FeelsApp (preserve
  MainActor isolation), wrap WatchConnectivity handler in MainActor
- Performance: Cache sortedGroupedData in DayViewViewModel, cache demo
  data in MonthView/YearView, remove broken ReduceMotionModifier
- Accessibility: VoiceOver support for LockScreen, DemoHeatmapCell
  labels, MonthCard button labels, InsightsView header traits,
  Smart Invert protection on neon headers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-19 09:11:48 -06:00
parent b58dfd5093
commit c22d246865
18 changed files with 175 additions and 73 deletions

View File

@@ -153,35 +153,32 @@ extension WatchConnectivityManager: WCSessionDelegate {
}
private func handleReceivedMessage(_ message: [String: Any]) {
guard let action = message["action"] as? String else {
Self.logger.error("No action in message")
return
}
switch action {
case "logMood":
guard let moodRaw = message["mood"] as? Int,
let mood = Mood(rawValue: moodRaw),
let timestamp = message["date"] as? TimeInterval else {
Self.logger.error("Invalid mood message format")
Task { @MainActor in
guard let action = message["action"] as? String else {
Self.logger.error("No action in message")
return
}
let date = Date(timeIntervalSince1970: timestamp)
Self.logger.info("Processing mood \(moodRaw) from watch for \(date)")
switch action {
case "logMood":
guard let moodRaw = message["mood"] as? Int,
let mood = Mood(rawValue: moodRaw),
let timestamp = message["date"] as? TimeInterval else {
Self.logger.error("Invalid mood message format")
return
}
Task { @MainActor in
let date = Date(timeIntervalSince1970: timestamp)
Self.logger.info("Processing mood \(moodRaw) from watch for \(date)")
MoodLogger.shared.logMood(mood, for: date, entryType: .watch)
}
case "reloadWidgets":
Self.logger.info("Received reloadWidgets from watch")
Task { @MainActor in
case "reloadWidgets":
Self.logger.info("Received reloadWidgets from watch")
WidgetCenter.shared.reloadAllTimelines()
}
default:
Self.logger.warning("Unknown action: \(action)")
default:
Self.logger.warning("Unknown action: \(action)")
}
}
}
#endif