Molecular top alerts
This commit is contained in:
parent
ea50b838d2
commit
f771469bc5
@ -484,9 +484,10 @@
|
|||||||
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; };
|
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; };
|
||||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; };
|
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; };
|
||||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
||||||
D2FA83D62515021F00564112 /* NotificationStatusBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* NotificationStatusBar.swift */; };
|
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */; };
|
||||||
D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; };
|
D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */; };
|
||||||
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; };
|
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */; };
|
||||||
|
D2FD4A4925199BD9000C28A9 /* AccessibilityProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FD4A4825199BD9000C28A9 /* AccessibilityProtocol.swift */; };
|
||||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
|
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
|
||||||
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
|
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
|
||||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
|
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
|
||||||
@ -977,9 +978,10 @@
|
|||||||
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; };
|
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
D2FA83D12513EA6900564112 /* NotificationXButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButton.swift; sourceTree = "<group>"; };
|
D2FA83D12513EA6900564112 /* NotificationXButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButton.swift; sourceTree = "<group>"; };
|
||||||
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotification.swift; sourceTree = "<group>"; };
|
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotification.swift; sourceTree = "<group>"; };
|
||||||
D2FA83D52515021F00564112 /* NotificationStatusBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationStatusBar.swift; sourceTree = "<group>"; };
|
D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationTopView.swift; sourceTree = "<group>"; };
|
||||||
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = "<group>"; };
|
D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainer.swift; sourceTree = "<group>"; };
|
||||||
D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = "<group>"; };
|
D2FB151C23A40F1500C20E10 /* MoleculeStackItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeStackItem.swift; sourceTree = "<group>"; };
|
||||||
|
D2FD4A4825199BD9000C28A9 /* AccessibilityProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityProtocol.swift; sourceTree = "<group>"; };
|
||||||
DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = "<group>"; };
|
DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftRightLabelView.swift; sourceTree = "<group>"; };
|
||||||
DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
|
||||||
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
|
DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = "<group>"; };
|
||||||
@ -1067,6 +1069,7 @@
|
|||||||
children = (
|
children = (
|
||||||
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */,
|
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */,
|
||||||
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */,
|
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */,
|
||||||
|
D2FD4A4825199BD9000C28A9 /* AccessibilityProtocol.swift */,
|
||||||
);
|
);
|
||||||
path = Protocols;
|
path = Protocols;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2091,7 +2094,7 @@
|
|||||||
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */,
|
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */,
|
||||||
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */,
|
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */,
|
||||||
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */,
|
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */,
|
||||||
D2FA83D52515021F00564112 /* NotificationStatusBar.swift */,
|
D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */,
|
||||||
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */,
|
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */,
|
||||||
);
|
);
|
||||||
path = TopNotification;
|
path = TopNotification;
|
||||||
@ -2400,6 +2403,7 @@
|
|||||||
AA633B3124989EC000731E80 /* HeadersH2PricingTwoRowsModel.swift in Sources */,
|
AA633B3124989EC000731E80 /* HeadersH2PricingTwoRowsModel.swift in Sources */,
|
||||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */,
|
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */,
|
||||||
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */,
|
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */,
|
||||||
|
D2FD4A4925199BD9000C28A9 /* AccessibilityProtocol.swift in Sources */,
|
||||||
D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */,
|
D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */,
|
||||||
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
||||||
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
|
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
|
||||||
@ -2574,7 +2578,7 @@
|
|||||||
AAB8549824DC01BD00477C40 /* ListThreeColumnBillHistoryDividerModel.swift in Sources */,
|
AAB8549824DC01BD00477C40 /* ListThreeColumnBillHistoryDividerModel.swift in Sources */,
|
||||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
||||||
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
|
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
|
||||||
D2FA83D62515021F00564112 /* NotificationStatusBar.swift in Sources */,
|
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */,
|
||||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
||||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import Foundation
|
|||||||
// MARK: - Outlets
|
// MARK: - Outlets
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public let topView = NotificationStatusBar()
|
public let topView = CollapsableNotificationTopView()
|
||||||
public let bottomView = NotificationView()
|
public let bottomView = NotificationView()
|
||||||
public var verticalStack: UIStackView!
|
public var verticalStack: UIStackView!
|
||||||
|
|
||||||
@ -53,108 +53,112 @@ import Foundation
|
|||||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
super.set(with: model, delegateObject, additionalData)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
guard let model = model as? CollapsableNotificationModel else { return }
|
guard let model = model as? CollapsableNotificationModel else { return }
|
||||||
|
|
||||||
topView.label.set(with: model.topLabel, delegateObject, additionalData)
|
topView.label.set(with: model.topLabel, delegateObject, additionalData)
|
||||||
topView.button.set(with: model.topAction, delegateObject: delegateObject, additionalData: additionalData)
|
topView.button.set(with: model.topAction, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
bottomView.set(with: model, delegateObject, additionalData)
|
topView.updateAccessibility()
|
||||||
updateAccessibilityLabel()
|
|
||||||
|
|
||||||
|
bottomView.set(with: model, delegateObject, additionalData)
|
||||||
|
|
||||||
|
// Set initial collapse/expand state.
|
||||||
topView.isHidden = !model.alwaysShowTopLabel && !model.initiallyCollapsed
|
topView.isHidden = !model.alwaysShowTopLabel && !model.initiallyCollapsed
|
||||||
topView.button.isUserInteractionEnabled = model.initiallyCollapsed
|
topView.button.isUserInteractionEnabled = model.initiallyCollapsed
|
||||||
bottomView.isHidden = model.initiallyCollapsed
|
bottomView.isHidden = model.initiallyCollapsed
|
||||||
verticalStack.layoutIfNeeded()
|
verticalStack.layoutIfNeeded()
|
||||||
|
|
||||||
if !model.initiallyCollapsed {
|
if !model.initiallyCollapsed {
|
||||||
collapse(with: .now() + DispatchTimeInterval.seconds(model.collapseTime))
|
autoCollapse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open func collapse(with delay: DispatchTime) {
|
open func performBlockOperation(with block: @escaping (MVMCoreBlockOperation) -> Void) {
|
||||||
DispatchQueue.main.asyncAfter(deadline: delay) { [weak self] in
|
let operation = MVMCoreBlockOperation(block: block)!
|
||||||
self?.collapse()
|
MVMCoreNavigationHandler.shared()?.addNavigationOperation(operation)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collapses after a delay
|
||||||
|
open func autoCollapse() {
|
||||||
|
let delay: DispatchTimeInterval = DispatchTimeInterval.seconds((model as? CollapsableNotificationModel)?.collapseTime ?? 5)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
|
||||||
|
// If accessibility focused, delay collapse.
|
||||||
|
guard let localSelf = self else { return }
|
||||||
|
if MVMCoreUIUtility.viewContainsAccessiblityFocus(localSelf) {
|
||||||
|
NotificationCenter.default.addObserver(localSelf, selector: #selector(localSelf.accessibilityFocusChanged(notification:)), name: UIAccessibility.elementFocusedNotification, object: nil)
|
||||||
|
} else {
|
||||||
|
localSelf.collapse()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Collapses to show just the top view.
|
||||||
open func collapse(animated: Bool = true) {
|
open func collapse(animated: Bool = true) {
|
||||||
let animation = { [weak self] in
|
guard !bottomView.isHidden else { return }
|
||||||
self?.topView.isHidden = false
|
performBlockOperation { [weak self] (operation) in
|
||||||
self?.bottomView.isHidden = true
|
let strongSelf = self
|
||||||
self?.verticalStack.layoutIfNeeded()
|
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||||
}
|
MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded()
|
||||||
if animated {
|
let animation = {
|
||||||
UIView.animate(withDuration: 0.5, animations: animation) { [weak self] (finished) in
|
strongSelf?.topView.isHidden = false
|
||||||
self?.topView.button.isUserInteractionEnabled = true
|
strongSelf?.bottomView.isHidden = true
|
||||||
}
|
strongSelf?.verticalStack.layoutIfNeeded()
|
||||||
} else {
|
}
|
||||||
animation()
|
let completion: (Bool) -> Void = { (finished) in
|
||||||
|
strongSelf?.topView.button.isUserInteractionEnabled = true
|
||||||
|
MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded()
|
||||||
|
UIAccessibility.post(notification: .layoutChanged, argument: strongSelf?.getAccessibilityLayoutChangedArgument())
|
||||||
|
operation.markAsFinished()
|
||||||
|
}
|
||||||
|
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.5, animations: animation, completion: completion)
|
||||||
|
} else {
|
||||||
|
animation()
|
||||||
|
completion(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expands to show the bottom view.
|
||||||
open func expand(topViewShowing: Bool = false, animated: Bool = true) {
|
open func expand(topViewShowing: Bool = false, animated: Bool = true) {
|
||||||
topView.button.isUserInteractionEnabled = false
|
guard bottomView.isHidden else { return }
|
||||||
let animation = { [weak self] in
|
performBlockOperation { [weak self] (operation) in
|
||||||
self?.topView.isHidden = !topViewShowing
|
let strongSelf = self
|
||||||
self?.bottomView.isHidden = false
|
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||||
self?.verticalStack.layoutIfNeeded()
|
MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded()
|
||||||
}
|
strongSelf?.topView.button.isUserInteractionEnabled = false
|
||||||
if animated {
|
let animation = {
|
||||||
UIView.animate(withDuration: 0.5, animations: animation) { [weak self] (finished) in
|
strongSelf?.topView.isHidden = !topViewShowing
|
||||||
|
strongSelf?.bottomView.isHidden = false
|
||||||
|
strongSelf?.verticalStack.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
let completion: (Bool) -> Void = { (finished) in
|
||||||
|
MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded()
|
||||||
|
UIAccessibility.post(notification: .layoutChanged, argument: strongSelf?.getAccessibilityLayoutChangedArgument())
|
||||||
|
strongSelf?.autoCollapse()
|
||||||
|
operation.markAsFinished()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
if animated {
|
||||||
} else {
|
UIView.animate(withDuration: 0.5, animations: animation, completion: completion)
|
||||||
animation()
|
} else {
|
||||||
|
animation()
|
||||||
|
completion(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 96
|
return 96
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
func getAccessibilityMessage() -> String? {
|
|
||||||
|
|
||||||
guard let leftImageLabel = leftImage.imageView.accessibilityLabel else {
|
/// Collapse if focus is no longer on this top alert.
|
||||||
return eyebrowHeadlineBodyLink.getAccessibilityMessage()
|
@objc func accessibilityFocusChanged(notification: Notification) {
|
||||||
|
if !MVMCoreUIUtility.viewContainsAccessiblityFocus(self) {
|
||||||
|
NotificationCenter.default.removeObserver(self, name: UIAccessibility.elementFocusedNotification, object: nil)
|
||||||
|
collapse()
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let label = eyebrowHeadlineBodyLink.getAccessibilityMessage() else {
|
|
||||||
return leftImageLabel
|
|
||||||
}
|
|
||||||
|
|
||||||
return leftImageLabel + ", " + label
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func updateAccessibilityLabel() {
|
|
||||||
/*headline.accessibilityLabel = headline.text
|
|
||||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: headline)
|
|
||||||
|
|
||||||
body.accessibilityLabel = body.text
|
|
||||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: body)
|
|
||||||
|
|
||||||
|
|
||||||
let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0
|
|
||||||
isAccessibilityElement = !linkShowing
|
|
||||||
accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none
|
|
||||||
|
|
||||||
if !linkShowing {
|
|
||||||
// Make whole cell focusable if no link.
|
|
||||||
accessibilityLabel = getAccessibilityMessage()
|
|
||||||
} else if let accessoryView = accessoryView {
|
|
||||||
// Both caret and link. Read all content on caret.
|
|
||||||
accessoryView.accessibilityLabel = getAccessibilityMessage()
|
|
||||||
accessibilityElements = [accessoryView, eyebrowHeadlineBodyLink.link]
|
|
||||||
} else {
|
|
||||||
// Only link. Manually add accessibility elements to ensure they are read in the right order.
|
|
||||||
var elements: [Any] = []
|
|
||||||
|
|
||||||
if let leftImageLabel = leftImage.imageView.accessibilityLabel, !leftImageLabel.isEmpty {
|
|
||||||
elements.append(leftImage.imageView)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let otherElements = eyebrowHeadlineBodyLink.getAccessibilityElements() {
|
|
||||||
elements.append(otherElements)
|
|
||||||
}
|
|
||||||
|
|
||||||
accessibilityElements = elements
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,3 +170,13 @@ extension CollapsableNotification: StatusBarUI {
|
|||||||
return (color, greyScale > 0.5 ? .lightContent : .default)
|
return (color, greyScale > 0.5 ? .lightContent : .default)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension CollapsableNotification: AccessibilityProtocol {
|
||||||
|
public func getAccessibilityLayoutChangedArgument() -> Any? {
|
||||||
|
if !topView.isHidden {
|
||||||
|
return topView
|
||||||
|
} else {
|
||||||
|
return bottomView.headline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// NotificationStatusBar.swift
|
// CollapsableNotificationTopView.swift
|
||||||
// MVMCoreUI
|
// MVMCoreUI
|
||||||
//
|
//
|
||||||
// Created by Scott Pfeil on 9/18/20.
|
// Created by Scott Pfeil on 9/18/20.
|
||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@objcMembers open class NotificationStatusBar: View {
|
@objcMembers open class CollapsableNotificationTopView: View {
|
||||||
public let label: Label = {
|
public let label: Label = {
|
||||||
let label = Label(fontStyle: .BoldBodySmall)
|
let label = Label(fontStyle: .BoldBodySmall)
|
||||||
label.numberOfLines = 1
|
label.numberOfLines = 1
|
||||||
@ -50,6 +50,13 @@ import Foundation
|
|||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func updateAccessibility() {
|
||||||
|
isAccessibilityElement = true
|
||||||
|
accessibilityLabel = label.text
|
||||||
|
accessibilityTraits = (button.isUserInteractionEnabled && button.actionModel != nil) ? .button : .none
|
||||||
|
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: self)
|
||||||
|
}
|
||||||
|
|
||||||
@objc func pressed(_ sender: Notification) {
|
@objc func pressed(_ sender: Notification) {
|
||||||
button.callActionBlock(button)
|
button.callActionBlock(button)
|
||||||
}
|
}
|
||||||
@ -59,59 +59,22 @@ import Foundation
|
|||||||
guard let model = model as? NotificationModel else { return }
|
guard let model = model as? NotificationModel else { return }
|
||||||
labelStack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, nil)
|
labelStack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, nil)
|
||||||
horizontalStack.updateContainedMolecules(with: [labelStack.stackModel, model.button, model.closeButton], delegateObject, nil)
|
horizontalStack.updateContainedMolecules(with: [labelStack.stackModel, model.button, model.closeButton], delegateObject, nil)
|
||||||
|
updateAccessibility()
|
||||||
updateAccessibilityLabel()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 96
|
return 96
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
func getAccessibilityMessage() -> String? {
|
|
||||||
|
|
||||||
guard let leftImageLabel = leftImage.imageView.accessibilityLabel else {
|
open func updateAccessibility() {
|
||||||
return eyebrowHeadlineBodyLink.getAccessibilityMessage()
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let label = eyebrowHeadlineBodyLink.getAccessibilityMessage() else {
|
|
||||||
return leftImageLabel
|
|
||||||
}
|
|
||||||
|
|
||||||
return leftImageLabel + ", " + label
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func updateAccessibilityLabel() {
|
|
||||||
/*headline.accessibilityLabel = headline.text
|
|
||||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: headline)
|
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: headline)
|
||||||
|
|
||||||
body.accessibilityLabel = body.text
|
|
||||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: body)
|
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: body)
|
||||||
|
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: button)
|
||||||
|
}
|
||||||
let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0
|
}
|
||||||
isAccessibilityElement = !linkShowing
|
|
||||||
accessibilityTraits = (isAccessibilityElement && accessoryView != nil) ? .button : .none
|
extension NotificationView: AccessibilityProtocol {
|
||||||
|
public func getAccessibilityLayoutChangedArgument() -> Any? {
|
||||||
if !linkShowing {
|
return headline
|
||||||
// Make whole cell focusable if no link.
|
|
||||||
accessibilityLabel = getAccessibilityMessage()
|
|
||||||
} else if let accessoryView = accessoryView {
|
|
||||||
// Both caret and link. Read all content on caret.
|
|
||||||
accessoryView.accessibilityLabel = getAccessibilityMessage()
|
|
||||||
accessibilityElements = [accessoryView, eyebrowHeadlineBodyLink.link]
|
|
||||||
} else {
|
|
||||||
// Only link. Manually add accessibility elements to ensure they are read in the right order.
|
|
||||||
var elements: [Any] = []
|
|
||||||
|
|
||||||
if let leftImageLabel = leftImage.imageView.accessibilityLabel, !leftImageLabel.isEmpty {
|
|
||||||
elements.append(leftImage.imageView)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let otherElements = eyebrowHeadlineBodyLink.getAccessibilityElements() {
|
|
||||||
elements.append(otherElements)
|
|
||||||
}
|
|
||||||
|
|
||||||
accessibilityElements = elements
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
MVMCoreUI/BaseClasses/Protocols/AccessibilityProtocol.swift
Normal file
14
MVMCoreUI/BaseClasses/Protocols/AccessibilityProtocol.swift
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// AccessibilityProtocol.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 9/21/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objc public protocol AccessibilityProtocol {
|
||||||
|
/// Should return the argument to use for posting a layout change.
|
||||||
|
func getAccessibilityLayoutChangedArgument() -> Any?
|
||||||
|
}
|
||||||
@ -1073,10 +1073,13 @@ CGFloat const PanelAnimationDuration = 0.2;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (UIViewController *)getCurrentDetailViewController {
|
- (UIViewController *)getCurrentDetailViewController {
|
||||||
UIViewController *viewController = self.navigationController.topViewController;
|
__block UIViewController *viewController = nil;
|
||||||
if ([viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) {
|
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
|
||||||
viewController = [viewController performSelector:@selector(getCurrentViewController)];
|
viewController = self.navigationController.topViewController;
|
||||||
}
|
if ([viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) {
|
||||||
|
viewController = [viewController performSelector:@selector(getCurrentViewController)];
|
||||||
|
}
|
||||||
|
}];
|
||||||
return viewController;
|
return viewController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -187,6 +187,19 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
[[MVMCoreUISession sharedGlobal].splitViewController.parentViewController setNeedsStatusBarAppearanceUpdate];
|
[[MVMCoreUISession sharedGlobal].splitViewController.parentViewController setNeedsStatusBarAppearanceUpdate];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)updateAccessibilityForTopAlert:(nullable UIView *)view {
|
||||||
|
// Update accessibility with top alert
|
||||||
|
if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) {
|
||||||
|
[((MVMCoreUITopAlertBaseView *)view) handleAccessibility];
|
||||||
|
} else {
|
||||||
|
id accessibilityArgument = view;
|
||||||
|
if ([view conformsToProtocol:@protocol(AccessibilityProtocol)]) {
|
||||||
|
accessibilityArgument = [((id <AccessibilityProtocol>)view) getAccessibilityLayoutChangedArgument];
|
||||||
|
}
|
||||||
|
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, accessibilityArgument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)showAlertView:(nullable UIView *)view topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
- (void)showAlertView:(nullable UIView *)view topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||||
|
|
||||||
__weak typeof(self) weakSelf = self;
|
__weak typeof(self) weakSelf = self;
|
||||||
@ -207,9 +220,8 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
} completion:^(BOOL finished) {
|
} completion:^(BOOL finished) {
|
||||||
[weakSelf.superview layoutIfNeeded];
|
[weakSelf.superview layoutIfNeeded];
|
||||||
[weakSelf.animationDelegate topAlertViewFinishAnimation];
|
[weakSelf.animationDelegate topAlertViewFinishAnimation];
|
||||||
if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) {
|
|
||||||
[((MVMCoreUITopAlertBaseView *)view) handleAccessibility];
|
[weakSelf updateAccessibilityForTopAlert:view];
|
||||||
}
|
|
||||||
|
|
||||||
[MVMCoreDispatchUtility performBlockInBackground:^{
|
[MVMCoreDispatchUtility performBlockInBackground:^{
|
||||||
if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewShown:topAlertObject:)]) {
|
if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewShown:topAlertObject:)]) {
|
||||||
|
|||||||
@ -89,7 +89,11 @@
|
|||||||
if (![focusedElement isKindOfClass:[UIView class]]) {
|
if (![focusedElement isKindOfClass:[UIView class]]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
return [(UIView *)focusedElement isDescendantOfView:view];
|
__block BOOL containsFocus;
|
||||||
|
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
|
||||||
|
containsFocus = [(UIView *)focusedElement isDescendantOfView:view];
|
||||||
|
}];
|
||||||
|
return containsFocus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Setters
|
#pragma mark - Setters
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user