From 525d275d21a69d1a83ef014a30c9c31fcfd88fe2 Mon Sep 17 00:00:00 2001 From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> Date: Sun, 9 Feb 2025 14:24:01 -0500 Subject: [PATCH] accessibility: add helpers for focus management This commit adds helper methods and view modifiers for dynamic accessibility focus control for iOS 15 and later. Change-Id: I6e7d7ab9f033ec020ad9ef66a40ecef97c13e33d --- Ring/Ring/Extensions/View+Helpers.swift | 61 +++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/Ring/Ring/Extensions/View+Helpers.swift b/Ring/Ring/Extensions/View+Helpers.swift index 35f2f9ed4..7a176efe5 100644 --- a/Ring/Ring/Extensions/View+Helpers.swift +++ b/Ring/Ring/Extensions/View+Helpers.swift @@ -263,3 +263,64 @@ struct CloseButton: View { }) } } + +// MARK: - Accessibility +extension View { + // Conditionally applies an accessibility focus modifier on iOS 15+, + func accessibilityFocusCompat(_ isFocused: Binding<Bool>) -> some View { + if #available(iOS 15, *) { + return AnyView(self.modifier(AccessibilityFocusModifier(isFocused: isFocused))) + } else { + return AnyView(self) + } + } + + // Automatically apply accessibility focus to view when it appears on iOS 15+. + func accessibilityAutoFocusOnAppear(_ shouldFocus: Bool = true) -> some View { + if #available(iOS 15, *) { + return AnyView(self.modifier(AccessibilityAutoFocusModifier(shouldFocus: shouldFocus))) + } else { + return AnyView(self) + } + } +} + +@available(iOS 15, *) +struct AccessibilityAutoFocusModifier: ViewModifier { + let shouldFocus: Bool + @AccessibilityFocusState private var isFocused: Bool + + func body(content: Content) -> some View { + content + .accessibilityFocused($isFocused) + .onAppear { + if shouldFocus { + isFocused = true + } + } + } +} + +@available(iOS 15, *) +private struct AccessibilityFocusModifier: ViewModifier { + @Binding var isFocused: Bool + @AccessibilityFocusState private var internalFocus: Bool + + func body(content: Content) -> some View { + content + .accessibilityFocused($internalFocus) + .onAppear { + internalFocus = isFocused + } + .onChange(of: internalFocus) { newValue in + if isFocused != newValue { + isFocused = newValue + } + } + .onChange(of: isFocused) { newValue in + if internalFocus != newValue { + internalFocus = newValue + } + } + } +} -- GitLab