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

@@ -1616,10 +1616,12 @@ struct LockScreenView: View {
ZStack {
// Themed background
backgroundView
.accessibilityHidden(true)
// Floating particles (Aurora only)
if lockScreenStyle == .aurora {
FloatingParticlesView()
.accessibilityHidden(true)
}
// Main content
@@ -1630,6 +1632,7 @@ struct LockScreenView: View {
centralElement
.opacity(showContent ? 1 : 0)
.scaleEffect(showContent ? 1 : 0.8)
.accessibilityHidden(true)
Spacer()
.frame(height: 50)
@@ -1649,6 +1652,7 @@ struct LockScreenView: View {
.multilineTextAlignment(.center)
.opacity(showContent ? 1 : 0)
.offset(y: showContent ? 0 : 20)
.accessibilityElement(children: .combine)
Spacer()
.frame(height: 16)
@@ -1666,6 +1670,8 @@ struct LockScreenView: View {
.opacity(showContent ? 1 : 0)
.offset(y: showContent ? 0 : 30)
.padding(.horizontal, 32)
.accessibilityLabel("Unlock")
.accessibilityHint("Double tap to authenticate with \(authManager.biometricName)")
// Passcode button
if authManager.canUseDevicePasscode {
@@ -1684,6 +1690,8 @@ struct LockScreenView: View {
.disabled(authManager.isAuthenticating)
.padding(.top, 16)
.opacity(showContent ? 1 : 0)
.accessibilityLabel("Use device passcode")
.accessibilityHint("Double tap to authenticate with your device passcode")
}
Spacer()