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:
@@ -21,25 +21,7 @@ extension EnvironmentValues {
|
||||
}
|
||||
}
|
||||
|
||||
/// View modifier that respects reduce motion preference
|
||||
struct ReduceMotionModifier: ViewModifier {
|
||||
@Environment(\.accessibilityReduceMotion) var reduceMotion
|
||||
|
||||
let animation: Animation?
|
||||
let reducedAnimation: Animation?
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.animation(reduceMotion ? reducedAnimation : animation, value: UUID())
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
/// Applies animation only when reduce motion is disabled
|
||||
func accessibleAnimation(_ animation: Animation? = .default, reduced: Animation? = nil) -> some View {
|
||||
modifier(ReduceMotionModifier(animation: animation, reducedAnimation: reduced))
|
||||
}
|
||||
|
||||
/// Wraps content in withAnimation respecting reduce motion
|
||||
func withAccessibleAnimation<V: Equatable>(_ animation: Animation? = .default, value: V, action: @escaping () -> Void) -> some View {
|
||||
self.onChange(of: value) { _, _ in
|
||||
@@ -59,11 +41,10 @@ extension View {
|
||||
extension View {
|
||||
/// Adds accessibility label with optional hint
|
||||
func accessibleMoodCell(mood: Mood, date: Date) -> some View {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
let dateString = DateFormattingCache.shared.string(for: date, format: .dateMedium)
|
||||
|
||||
return self
|
||||
.accessibilityLabel("\(mood.strValue) on \(formatter.string(from: date))")
|
||||
.accessibilityLabel("\(mood.strValue) on \(dateString)")
|
||||
.accessibilityHint("Double tap to edit mood")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user