|
|
|
|
@ -32,7 +32,13 @@ public class AccessbilityOperation: MVMCoreOperation {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
UIAccessibility.post(notification: self.notificationType, argument: self.argument)
|
|
|
|
|
self.markAsFinished()
|
|
|
|
|
if self.notificationType == .announcement {
|
|
|
|
|
NotificationCenter.default.addObserver(forName: UIAccessibility.announcementDidFinishNotification, object: nil, queue: .main) { _ in
|
|
|
|
|
self.markAsFinished()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
self.markAsFinished()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -44,125 +50,6 @@ public class AccessbilityOperation: MVMCoreOperation {
|
|
|
|
|
|
|
|
|
|
open class AccessibilityHandler {
|
|
|
|
|
|
|
|
|
|
public static func shared() -> Self? {
|
|
|
|
|
guard let shared = CoreUIObject.sharedInstance()?.accessibilityHandler else { return nil }
|
|
|
|
|
return MVMCoreActionUtility.fatalClassCheck(object: shared)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public var previousAccessiblityElement: Any?
|
|
|
|
|
public var anyCancellable: Set<AnyCancellable> = []
|
|
|
|
|
public weak var delegate: MVMCoreViewControllerProtocol?
|
|
|
|
|
|
|
|
|
|
private var accessibilityOperationQueue: OperationQueue = {
|
|
|
|
|
let queue = OperationQueue()
|
|
|
|
|
queue.maxConcurrentOperationCount = 1
|
|
|
|
|
return queue
|
|
|
|
|
}()
|
|
|
|
|
public var accessibilityId: String?
|
|
|
|
|
public var hasTopNotificationInPage: Bool = false
|
|
|
|
|
|
|
|
|
|
public init() {
|
|
|
|
|
registerForPageChanges()
|
|
|
|
|
registerForFocusChanges()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Register with Accessibility Handler listeners
|
|
|
|
|
private func registerForFocusChanges() {
|
|
|
|
|
//Since foucs shifted to other elements cancelling existing focus shift notifications if any
|
|
|
|
|
NotificationCenter.default.publisher(for: UIAccessibility.elementFocusedNotification)
|
|
|
|
|
.sink { [weak self] _ in
|
|
|
|
|
self?.cancelAllOperations()
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func registerForTopNotificationsChanges() {
|
|
|
|
|
NotificationHandler.shared()?.onNotificationWillShow
|
|
|
|
|
.sink { [weak self] (_, model) in
|
|
|
|
|
if self?.previousAccessiblityElement == nil {
|
|
|
|
|
self?.capturePreviousFocusElement()
|
|
|
|
|
}
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
NotificationHandler.shared()?.onNotificationShown
|
|
|
|
|
.sink { [weak self] (view, model) in
|
|
|
|
|
self?.post(notification: .layoutChanged, argument: view)
|
|
|
|
|
self?.hasTopNotificationInPage = false
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
NotificationHandler.shared()?.onNotificationWillDismiss
|
|
|
|
|
.sink { [weak self] (view, model) in
|
|
|
|
|
self?.post(notification: .announcement, argument: MVMCoreUIUtility.hardcodedString(withKey: "AccTopAlertClosed"))
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
NotificationHandler.shared()?.onNotificationDismissed
|
|
|
|
|
.sink { [weak self] (view, model) in
|
|
|
|
|
self?.postAccessbilityToPrevElement()
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Registers to know when pages change.
|
|
|
|
|
open func registerForPageChanges() {
|
|
|
|
|
NavigationHandler.shared()
|
|
|
|
|
.onNavigation
|
|
|
|
|
.sink { [self] (event, operation) in
|
|
|
|
|
switch event {
|
|
|
|
|
case .willNavigate:
|
|
|
|
|
willNavigate(operation)
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func willNavigate(_ operation: NavigationOperation) {
|
|
|
|
|
previousAccessiblityElement = nil
|
|
|
|
|
if let subNavManagerController = (operation.toNavigationControllerViewControllers?.last as? MVMCoreViewManagerViewControllerProtocol)?.manager as? SubNavManagerController {
|
|
|
|
|
delegate = subNavManagerController.getCurrentViewController() as? MVMCoreViewControllerProtocol
|
|
|
|
|
} else {
|
|
|
|
|
delegate = operation.toNavigationControllerViewControllers?.last as? MVMCoreViewControllerProtocol
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Accessibility Handler operation events
|
|
|
|
|
open func capturePreviousFocusElement() {
|
|
|
|
|
previousAccessiblityElement = UIAccessibility.focusedElement(using: .notificationVoiceOver)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
open func postAccessbilityToPrevElement() {
|
|
|
|
|
post(notification: .layoutChanged, argument: previousAccessiblityElement)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func add(operation: Operation) {
|
|
|
|
|
accessibilityOperationQueue.addOperation(operation)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func cancelAllOperations() {
|
|
|
|
|
accessibilityOperationQueue.cancelAllOperations()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func post(notification type: UIAccessibility.Notification, argument: Any? = nil) {
|
|
|
|
|
guard UIAccessibility.isVoiceOverRunning else { return }
|
|
|
|
|
let accessbilityOperation = AccessbilityOperation(notificationType: type, argument: argument)
|
|
|
|
|
add(operation: accessbilityOperation)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//To get first focus element on the screen
|
|
|
|
|
open func getFirstFocusedElementOnScreen() -> Any? {
|
|
|
|
|
(delegate as? UIViewController)?.navigationController?.navigationBar
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Subclass can decide to trigger Accessibility notification on screen change.
|
|
|
|
|
open func canPostAccessbilityNotification(for viewController: UIViewController) -> Bool { true }
|
|
|
|
|
|
|
|
|
|
func getPreDefinedFocusedElementIfAny() -> UIView? {
|
|
|
|
|
guard let accessibilityId, let view = (delegate as? UIViewController)?.view else { return nil }
|
|
|
|
|
return MVMCoreUIUtility.findViews(by: MoleculeViewProtocol.self, views: [view]).first {
|
|
|
|
|
($0 as? MoleculeViewModelProtocol)?.moleculeModel?.id == accessibilityId
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Accessibility Handler Behaviour
|
|
|
|
|
///Accessibility Handler Behaviour to detect page shown and post notification to first interactive element on screen or the pre-defined focused element.
|
|
|
|
|
open class AccessibilityHandlerBehavior: PageVisibilityBehavior, PageMoleculeTransformationBehavior {
|
|
|
|
|
|
|
|
|
|
enum RotorType: String, CaseIterable {
|
|
|
|
|
|
|
|
|
|
case button = "Buttons"
|
|
|
|
|
@ -189,72 +76,121 @@ open class AccessibilityHandlerBehavior: PageVisibilityBehavior, PageMoleculeTra
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public var anyCancellable: Set<AnyCancellable> = []
|
|
|
|
|
private var delegateObj: MVMCoreUIDelegateObject?
|
|
|
|
|
private var rotorIndexes: [RotorType: Int] = [:]
|
|
|
|
|
public static func shared() -> Self? {
|
|
|
|
|
guard let shared = CoreUIObject.sharedInstance()?.accessibilityHandler else { return nil }
|
|
|
|
|
return MVMCoreActionUtility.fatalClassCheck(object: shared)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { }
|
|
|
|
|
public var accessibilityId: String?
|
|
|
|
|
public var previousAccessiblityElement: Any?
|
|
|
|
|
public var anyCancellable: Set<AnyCancellable> = []
|
|
|
|
|
public weak var delegate: MVMCoreViewControllerProtocol?
|
|
|
|
|
private var rotorIndexes: [RotorType: Int] = [:]
|
|
|
|
|
private var hasTopNotificationInPage: Bool { NotificationHandler.shared()?.isNotificationShowing() ?? false }
|
|
|
|
|
private let accessibilityOperationQueue: OperationQueue = {
|
|
|
|
|
let queue = OperationQueue()
|
|
|
|
|
queue.maxConcurrentOperationCount = 1
|
|
|
|
|
return queue
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
public init() {
|
|
|
|
|
registerForFocusChanges()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Accessibility Handler operation events
|
|
|
|
|
open func capturePreviousFocusElement() {
|
|
|
|
|
previousAccessiblityElement = UIAccessibility.focusedElement(using: .notificationVoiceOver)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
open func postAccessbilityToPrevElement() {
|
|
|
|
|
post(notification: .layoutChanged, argument: previousAccessiblityElement)
|
|
|
|
|
previousAccessiblityElement = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func post(notification type: UIAccessibility.Notification, argument: Any? = nil) {
|
|
|
|
|
guard UIAccessibility.isVoiceOverRunning else { return }
|
|
|
|
|
let accessbilityOperation = AccessbilityOperation(notificationType: type, argument: argument)
|
|
|
|
|
accessibilityOperationQueue.addOperation(accessbilityOperation)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//To get first focus element on the screen
|
|
|
|
|
open func getFirstFocusedElementOnScreen() -> Any? {
|
|
|
|
|
(delegate as? UIViewController)?.navigationController?.navigationBar
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Subclass can decide to trigger Accessibility notification on screen change.
|
|
|
|
|
open func canPostAccessbilityNotification(for viewController: UIViewController) -> Bool { true }
|
|
|
|
|
|
|
|
|
|
func getPreDefinedFocusedElementIfAny() -> UIView? {
|
|
|
|
|
guard let accessibilityId, let view = (delegate as? UIViewController)?.view else { return nil }
|
|
|
|
|
return MVMCoreUIUtility.findViews(by: MoleculeViewProtocol.self, views: [view]).first {
|
|
|
|
|
$0.model?.id == accessibilityId
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extension AccessibilityHandler {
|
|
|
|
|
|
|
|
|
|
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
rotorIndexes = [:]
|
|
|
|
|
previousAccessiblityElement = nil
|
|
|
|
|
guard let loadObject = (delegateObject?.loadDelegate as? MVMCoreViewControllerProtocol)?.loadObject else { return }
|
|
|
|
|
AccessibilityHandler.shared()?.accessibilityId = loadObject?.pageJSON?.optionalStringForKey("accessibilityId")
|
|
|
|
|
//TODO: - Need to revisit this logic
|
|
|
|
|
AccessibilityHandler.shared()?.hasTopNotificationInPage = loadObject?.responseJSON?.optionalDictionaryForKey("TopNotification") != nil || loadObject?.responseInfoMap?.optionalStringForKey("userMessage") != nil
|
|
|
|
|
accessibilityId = loadObject?.pageJSON?.optionalStringForKey("accessibilityId")
|
|
|
|
|
if let announcementText = loadObject?.pageJSON?.optionalStringForKey("announcementText") {
|
|
|
|
|
AccessibilityHandler.shared()?.post(notification: .announcement, argument: announcementText)
|
|
|
|
|
post(notification: .announcement, argument: announcementText)
|
|
|
|
|
}
|
|
|
|
|
delegate = delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//MARK: - PageVisibiltyBehaviour
|
|
|
|
|
open func willShowPage(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
public func willShowPage(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
updateAccessibilityViews(delegateObject)
|
|
|
|
|
guard let controller = delegateObject?.moleculeDelegate as? UIViewController,
|
|
|
|
|
(AccessibilityHandler.shared()?.canPostAccessbilityNotification(for: controller) ?? true),
|
|
|
|
|
AccessibilityHandler.shared()?.accessibilityId == nil else { return }
|
|
|
|
|
if AccessibilityHandler.shared()?.hasTopNotificationInPage ?? false {
|
|
|
|
|
AccessibilityHandler.shared()?.previousAccessiblityElement = AccessibilityHandler.shared()?.getFirstFocusedElementOnScreen()
|
|
|
|
|
canPostAccessbilityNotification(for: controller),
|
|
|
|
|
accessibilityId == nil else { return }
|
|
|
|
|
if hasTopNotificationInPage {
|
|
|
|
|
previousAccessiblityElement = getFirstFocusedElementOnScreen()
|
|
|
|
|
} else {
|
|
|
|
|
AccessibilityHandler.shared()?.post(notification: .layoutChanged, argument: AccessibilityHandler.shared()?.getFirstFocusedElementOnScreen())
|
|
|
|
|
post(notification: .layoutChanged, argument: getFirstFocusedElementOnScreen())
|
|
|
|
|
}
|
|
|
|
|
delegateObj = delegateObject
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///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
|
|
|
|
|
open func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
updateAccessibilityViews(delegateObject) //To track FAB & HAB elements on UI
|
|
|
|
|
identifyAndPrepareRotors()
|
|
|
|
|
guard let accessibilityElement = AccessibilityHandler.shared()?.getPreDefinedFocusedElementIfAny() else { return }
|
|
|
|
|
AccessibilityHandler.shared()?.accessibilityId = nil
|
|
|
|
|
if AccessibilityHandler.shared()?.hasTopNotificationInPage ?? false {
|
|
|
|
|
AccessibilityHandler.shared()?.previousAccessiblityElement = accessibilityElement
|
|
|
|
|
public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
identifyAndPrepareRotors(delegateObject)
|
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
|
|
|
(delegateObject?.moleculeDelegate as? UIViewController)?.view.accessibilityElements = nil
|
|
|
|
|
}
|
|
|
|
|
guard let accessibilityElement = getPreDefinedFocusedElementIfAny() else { return }
|
|
|
|
|
accessibilityId = nil
|
|
|
|
|
if hasTopNotificationInPage {
|
|
|
|
|
previousAccessiblityElement = accessibilityElement
|
|
|
|
|
} else {
|
|
|
|
|
AccessibilityHandler.shared()?.post(notification: .layoutChanged, argument: accessibilityElement)
|
|
|
|
|
post(notification: .layoutChanged, argument: accessibilityElement)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//MARK: - Accessibility Methods
|
|
|
|
|
private func updateAccessibilityViews(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
//TODO: - Need to revisit this logic
|
|
|
|
|
var accessibilityElements: [Any?] = [MVMCoreUISplitViewController.main()?.topAlertView]
|
|
|
|
|
if let managerController = (delegateObject?.moleculeDelegate as? MVMCoreViewManagerViewControllerProtocol)?.manager as? SubNavManagerController {
|
|
|
|
|
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.compactMap { $0 }
|
|
|
|
|
var currentController = delegateObject?.moleculeDelegate as? UIViewController
|
|
|
|
|
var accessibilityElements: [Any?] = [MVMCoreUISplitViewController.main()?.topAlertView, MVMCoreUISplitViewController.main()?.navigationController]
|
|
|
|
|
if let manager = ((delegateObject?.moleculeDelegate as? MVMCoreViewManagerViewControllerProtocol)?.manager as? MVMCoreViewManagerProtocol & UIViewController),
|
|
|
|
|
let managerAccessibilityElements = manager.getAccessibilityElements() {
|
|
|
|
|
accessibilityElements.append(contentsOf: managerAccessibilityElements)
|
|
|
|
|
accessibilityElements.append(contentsOf: manager.view.subviews)
|
|
|
|
|
currentController = manager
|
|
|
|
|
} else {
|
|
|
|
|
accessibilityElements.append(contentsOf: currentController?.view.subviews ?? [])
|
|
|
|
|
}
|
|
|
|
|
accessibilityElements.append(MVMCoreUISplitViewController.main()?.tabBar)
|
|
|
|
|
currentController?.view.accessibilityElements = accessibilityElements.compactMap { $0 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//MARK: - Rotor Methods
|
|
|
|
|
private func identifyAndPrepareRotors() {
|
|
|
|
|
private func identifyAndPrepareRotors(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
var rotorElements: [UIAccessibilityCustomRotor] = []
|
|
|
|
|
let currentViewController = ((delegateObj?.moleculeDelegate as? MVMCoreViewManagerViewControllerProtocol)?.manager as? SubNavManagerController) ?? (delegateObj?.moleculeDelegate as? ViewController)
|
|
|
|
|
let currentViewController = ((delegateObject?.moleculeDelegate as? MVMCoreViewManagerViewControllerProtocol)?.manager as? SubNavManagerController) ?? (delegateObject?.moleculeDelegate as? ViewController)
|
|
|
|
|
for type in RotorType.allCases {
|
|
|
|
|
if let elements = getTraitMappedElements(currentViewController, type: type),
|
|
|
|
|
let rotor = createRotor(elements, for: type) {
|
|
|
|
|
@ -337,14 +273,76 @@ open class AccessibilityHandlerBehavior: PageVisibilityBehavior, PageMoleculeTra
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var rotorElement = elements[rotorIndex - 1]
|
|
|
|
|
if let tableView = (self.delegateObj?.moleculeListDelegate as? MoleculeListTemplate)?.tableView,
|
|
|
|
|
if let tableView = (self.delegate as? MoleculeListTemplate)?.tableView,
|
|
|
|
|
let element = rotorElement as? (model: MoleculeModelProtocol, indexPath: IndexPath) { //for List templates
|
|
|
|
|
tableView.scrollToRow(at: element.indexPath, at: .middle, animated: false)
|
|
|
|
|
rotorElement = MVMCoreUIUtility.findViews(by: MoleculeViewProtocol.self, views: [tableView.cellForRow(at: element.indexPath)].compactMap { $0 }).filter { $0.accessibilityTraits.contains(type.trait) && ($0 as? MoleculeViewModelProtocol)?.moleculeModel?.id == element.model.id }.first as Any
|
|
|
|
|
rotorElement = MVMCoreUIUtility.findViews(by: MoleculeViewProtocol.self, views: [tableView.cellForRow(at: element.indexPath)].compactMap { $0 }).filter { $0.accessibilityTraits.contains(type.trait) && $0.model?.id == element.model.id }.first as Any
|
|
|
|
|
}
|
|
|
|
|
self.rotorIndexes[type] = rotorIndex
|
|
|
|
|
AccessibilityHandler.shared()?.post(notification: .layoutChanged, argument: rotorElement)
|
|
|
|
|
post(notification: .layoutChanged, argument: rotorElement)
|
|
|
|
|
return UIAccessibilityCustomRotorItemResult(targetElement: rotorElement as! NSObjectProtocol, targetRange: nil)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@objc extension AccessibilityHandler {
|
|
|
|
|
|
|
|
|
|
// MARK: - Register with Accessibility Handler listeners
|
|
|
|
|
private func registerForFocusChanges() {
|
|
|
|
|
//Since focus shifted to other elements cancelling existing focus shift notifications if any
|
|
|
|
|
NotificationCenter.default.publisher(for: UIAccessibility.elementFocusedNotification)
|
|
|
|
|
.sink { [weak self] _ in
|
|
|
|
|
self?.accessibilityOperationQueue.cancelAllOperations()
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func registerForTopNotificationsChanges() {
|
|
|
|
|
NotificationHandler.shared()?.onNotificationWillShow
|
|
|
|
|
.sink { [weak self] (_, model) in
|
|
|
|
|
if self?.previousAccessiblityElement == nil {
|
|
|
|
|
self?.capturePreviousFocusElement()
|
|
|
|
|
}
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
NotificationHandler.shared()?.onNotificationShown
|
|
|
|
|
.sink { [weak self] (view, model) in
|
|
|
|
|
self?.post(notification: .layoutChanged, argument: view)
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
NotificationHandler.shared()?.onNotificationWillDismiss
|
|
|
|
|
.sink { [weak self] (view, model) in
|
|
|
|
|
self?.post(notification: .announcement, argument: MVMCoreUIUtility.hardcodedString(withKey: "AccTopAlertClosed"), priority: .veryHigh)
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
NotificationHandler.shared()?.onNotificationDismissed
|
|
|
|
|
.sink { [weak self] (view, model) in
|
|
|
|
|
self?.postAccessbilityToPrevElement()
|
|
|
|
|
}.store(in: &anyCancellable)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Accessibility Handler Behaviour
|
|
|
|
|
///Accessibility Handler Behaviour to detect page shown and post notification to first interactive element on screen or the pre-defined focused element.
|
|
|
|
|
open class AccessibilityHandlerBehavior: PageVisibilityBehavior, PageMoleculeTransformationBehavior {
|
|
|
|
|
|
|
|
|
|
public let accessibilityHandler: AccessibilityHandler?
|
|
|
|
|
|
|
|
|
|
public init(accessibilityHandler: AccessibilityHandler?) {
|
|
|
|
|
self.accessibilityHandler = accessibilityHandler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
accessibilityHandler = AccessibilityHandler.shared() //Protocol Mandatory init method.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//MARK: - PageMoleculeTransformationBehavior
|
|
|
|
|
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
accessibilityHandler?.onPageNew(rootMolecules: rootMolecules, delegateObject)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//MARK: - PageVisibiltyBehaviour
|
|
|
|
|
open func willShowPage(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
accessibilityHandler?.willShowPage(delegateObject)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
open func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) {
|
|
|
|
|
accessibilityHandler?.onPageShown(delegateObject)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|