diff --git a/MVMCoreUI/Accessibility/AccessibilityHandler.swift b/MVMCoreUI/Accessibility/AccessibilityHandler.swift index 96664c06..fde20909 100644 --- a/MVMCoreUI/Accessibility/AccessibilityHandler.swift +++ b/MVMCoreUI/Accessibility/AccessibilityHandler.swift @@ -65,9 +65,9 @@ open class AccessibilityHandler { queue.maxConcurrentOperationCount = 1 return queue }() - private var accessibilityId: String? + private(set) var accessibilityId: String? private var announcementText: String? - private var hasTopNotitificationInPage: Bool = false + private(set) var hasTopNotitificationInPage: Bool = false public init() { registerWithResponseLoaded() @@ -121,7 +121,7 @@ open class AccessibilityHandler { switch event { case .willNavigate: willNavigate(operation) - @unknown default: + default: break } }.store(in: &anyCancellable) @@ -138,22 +138,6 @@ open class AccessibilityHandler { delegate = operation.toNavigationControllerViewControllers?.last as? MVMCoreViewControllerProtocol } } - - /*private func didNavigate(_ operation: NavigationOperation) { - guard UIAccessibility.isVoiceOverRunning, - let viewController = operation.toNavigationControllerViewControllers?.last, - canPostAccessbilityNotification(for: viewController) else { return } - delegate = viewController as? MVMCoreViewControllerProtocol - guard let view = operation.toNavigationControllerViewControllers?.last?.view else { return } - view.accessibilityElements = getAccessibilityElementsOnScreen() - if hasTopNotitificationInPage { - previousAccessiblityElement = getFirstFocusedElementOnScreen() - } else { - let accessbilityElement = getUIElementBasedOn(id: accessibilityId) - post(notification: .screenChanged, argument: accessbilityElement ?? getFirstFocusedElementOnScreen()) - accessibilityId = nil - } - }*/ // MARK: - Accessibility Handler operation events open func capturePreviousFocusElement() { @@ -210,30 +194,49 @@ struct AccessibilityHandlerBehaviorModel: PageBehaviorModelProtocol { class AccessibilityHandlerBehavior: PageVisibilityBehavior { + private var delegateObj: MVMCoreUIDelegateObject? + private var anyCancellable: Set = [] + required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { } public func willShowPage(_ delegateObject: MVMCoreUIDelegateObject?) { - let viewController = updateAccessibilityViews(delegateObject) - AccessibilityHandler.shared()?.post(notification: .layoutChanged, argument: AccessibilityHandler.shared()?.getPreDefinedFocusedElementIfAny() ?? AccessibilityHandler.shared()?.getFirstFocusedElementOnScreen()) + guard let controller = delegateObject?.moleculeDelegate as? UIViewController, + (AccessibilityHandler.shared()?.canPostAccessbilityNotification(for: controller) ?? true), + AccessibilityHandler.shared()?.accessibilityId == nil else { return } + if AccessibilityHandler.shared()?.hasTopNotitificationInPage ?? false { + AccessibilityHandler.shared()?.previousAccessiblityElement = AccessibilityHandler.shared()?.getFirstFocusedElementOnScreen() + } else { + AccessibilityHandler.shared()?.post(notification: .layoutChanged, argument: AccessibilityHandler.shared()?.getFirstFocusedElementOnScreen()) + } + delegateObj = delegateObject } - private func updateAccessibilityViews(_ delegateObject: MVMCoreUIDelegateObject?) -> UIViewController? { - var accessibilityElements: [Any?] = [MVMCoreUISplitViewController.main()?.topAlertView, MVMCoreUISplitViewController.main()?.navigationController] - var viewController: UIViewController? + ///We need to shift focus to any element mentioned in server response i.e to retain focus of the element in new page, from where action is triggered. + ///https://oneconfluence.verizon.com/display/MFD/Accessibility+-+Focus+Retain + func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { + updateAccessibilityViews(delegateObject) //To track FAB & HAB elements on UI + guard let accessibilityElement = AccessibilityHandler.shared()?.getPreDefinedFocusedElementIfAny() else { return } + if AccessibilityHandler.shared()?.hasTopNotitificationInPage ?? false { + AccessibilityHandler.shared()?.previousAccessiblityElement = accessibilityElement + } else { + AccessibilityHandler.shared()?.post(notification: .layoutChanged, argument: accessibilityElement) + } + } + + private func updateAccessibilityViews(_ delegateObject: MVMCoreUIDelegateObject?) { + var accessibilityElements: [Any?] = [MVMCoreUISplitViewController.main()?.topAlertView] if let managerController = (delegateObject?.moleculeDelegate as? MVMCoreViewManagerViewControllerProtocol)?.manager as? SubNavManagerController { - var managerControllerViews = [Any?]() - managerControllerViews.append(managerController.navigationController) - managerControllerViews.append(managerController.tabs) - managerControllerViews.append(contentsOf: managerController.view.subviews) - managerController.view.accessibilityElements = managerControllerViews.compactMap { $0 } + accessibilityElements.append(managerController.navigationController) + accessibilityElements.append(managerController.tabs) + accessibilityElements.append(contentsOf: managerController.view.subviews) + accessibilityElements.append(MVMCoreUISplitViewController.main()?.tabBar) + managerController.view.accessibilityElements = accessibilityElements.compactMap { $0 } } else if let controller = delegateObject?.moleculeDelegate as? UIViewController { accessibilityElements.append(controller.navigationController) accessibilityElements.append(contentsOf: controller.view.subviews.reversed()) accessibilityElements.append(MVMCoreUISplitViewController.main()?.tabBar) - controller.view.accessibilityElements = accessibilityElements - viewController = controller + controller.view.accessibilityElements = accessibilityElements.compactMap { $0 } } - return viewController } }