Merge branch 'feature/molecule_top_notification' into 'release/8_1_0'
Feature/molecule top notification See merge request BPHV_MIPS/mvm_core_ui!598
This commit is contained in:
commit
9cab5e3796
@ -318,6 +318,7 @@
|
||||
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
|
||||
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; };
|
||||
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
|
||||
D23118B325124E18001C8440 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* Notification.swift */; };
|
||||
D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; };
|
||||
D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */; };
|
||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; };
|
||||
@ -481,8 +482,12 @@
|
||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; };
|
||||
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; };
|
||||
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; };
|
||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; };
|
||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
||||
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */; };
|
||||
D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FB151A23A2B65B00C20E10 /* MoleculeContainer.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 */; };
|
||||
DBC4391822442197001AB423 /* CaretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391622442196001AB423 /* CaretView.swift */; };
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBC4391722442197001AB423 /* DashLine.swift */; };
|
||||
@ -806,6 +811,7 @@
|
||||
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = "<group>"; };
|
||||
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D23118B225124E18001C8440 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||
D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = "<group>"; };
|
||||
@ -970,8 +976,12 @@
|
||||
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
|
||||
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.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>"; };
|
||||
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotification.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -1059,6 +1069,7 @@
|
||||
children = (
|
||||
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */,
|
||||
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */,
|
||||
D2FD4A4825199BD9000C28A9 /* AccessibilityProtocol.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
@ -2077,9 +2088,13 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */,
|
||||
D2FA83D12513EA6900564112 /* NotificationXButton.swift */,
|
||||
D2CAC7CC251104FE00C75681 /* NotificationModel.swift */,
|
||||
D23118B225124E18001C8440 /* Notification.swift */,
|
||||
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */,
|
||||
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */,
|
||||
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */,
|
||||
D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */,
|
||||
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */,
|
||||
);
|
||||
path = TopNotification;
|
||||
@ -2388,6 +2403,7 @@
|
||||
AA633B3124989EC000731E80 /* HeadersH2PricingTwoRowsModel.swift in Sources */,
|
||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */,
|
||||
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */,
|
||||
D2FD4A4925199BD9000C28A9 /* AccessibilityProtocol.swift in Sources */,
|
||||
D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */,
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
||||
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
|
||||
@ -2460,6 +2476,7 @@
|
||||
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
||||
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */,
|
||||
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
|
||||
D23118B325124E18001C8440 /* Notification.swift in Sources */,
|
||||
AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */,
|
||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
||||
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
||||
@ -2515,6 +2532,7 @@
|
||||
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */,
|
||||
C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */,
|
||||
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */,
|
||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */,
|
||||
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */,
|
||||
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */,
|
||||
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */,
|
||||
@ -2560,6 +2578,7 @@
|
||||
AAB8549824DC01BD00477C40 /* ListThreeColumnBillHistoryDividerModel.swift in Sources */,
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */,
|
||||
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */,
|
||||
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */,
|
||||
0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */,
|
||||
AA56A211243C5EFC00303286 /* ListTwoColumnSubsectionDivider.swift in Sources */,
|
||||
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */,
|
||||
@ -2605,6 +2624,7 @@
|
||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */,
|
||||
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
||||
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
|
||||
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */,
|
||||
|
||||
@ -233,8 +233,8 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: LockupsPlanSMLXL.self, viewModelClass: LockupsPlanSMLXLModel.self)
|
||||
|
||||
// MARK: - Top Notifications
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MVMCoreUITopAlertMainView.self, viewModelClass: NotificationModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: MVMCoreUITopAlertExpandableView.self, viewModelClass: CollapsableNotificationModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: NotificationView.self, viewModelClass: NotificationModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: CollapsableNotification.self, viewModelClass: CollapsableNotificationModel.self)
|
||||
|
||||
// MARK:- Helper models
|
||||
try? ModelRegistry.register(RuleRequiredModel.self)
|
||||
|
||||
@ -0,0 +1,182 @@
|
||||
//
|
||||
// CollapsableNotification.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 9/18/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class CollapsableNotification: View {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
|
||||
public let topView = CollapsableNotificationTopView()
|
||||
public let bottomView = NotificationView()
|
||||
public var verticalStack: UIStackView!
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Life Cycle
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
verticalStack = UIStackView(arrangedSubviews: [topView, bottomView])
|
||||
verticalStack.translatesAutoresizingMaskIntoConstraints = false
|
||||
verticalStack.axis = .vertical
|
||||
verticalStack.alignment = .fill
|
||||
verticalStack.distribution = .fill
|
||||
addSubview(verticalStack)
|
||||
NSLayoutConstraint.constraintPinSubview(verticalStack, pinTop: true, topConstant: 0, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0)
|
||||
|
||||
reset()
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
verticalStack.updateView(size)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
verticalStack.reset()
|
||||
backgroundColor = .mvmGreen()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? CollapsableNotificationModel else { return }
|
||||
|
||||
topView.label.set(with: model.topLabel, delegateObject, additionalData)
|
||||
topView.button.set(with: model.topAction, delegateObject: delegateObject, additionalData: additionalData)
|
||||
topView.updateAccessibility()
|
||||
|
||||
bottomView.set(with: model, delegateObject, additionalData)
|
||||
|
||||
// Set initial collapse/expand state.
|
||||
topView.isHidden = !model.alwaysShowTopLabel && !model.initiallyCollapsed
|
||||
topView.button.isUserInteractionEnabled = model.initiallyCollapsed
|
||||
bottomView.isHidden = model.initiallyCollapsed
|
||||
verticalStack.layoutIfNeeded()
|
||||
|
||||
if !model.initiallyCollapsed {
|
||||
autoCollapse()
|
||||
}
|
||||
}
|
||||
|
||||
open func performBlockOperation(with block: @escaping (MVMCoreBlockOperation) -> Void) {
|
||||
let operation = MVMCoreBlockOperation(block: block)!
|
||||
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 self = self else { return }
|
||||
if MVMCoreUIUtility.viewContainsAccessiblityFocus(self) {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(self.accessibilityFocusChanged(notification:)), name: UIAccessibility.elementFocusedNotification, object: nil)
|
||||
} else {
|
||||
self.collapse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collapses to show just the top view.
|
||||
open func collapse(animated: Bool = true) {
|
||||
guard !bottomView.isHidden else { return }
|
||||
performBlockOperation { [weak self] (operation) in
|
||||
let strongSelf = self
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded()
|
||||
let animation = {
|
||||
strongSelf?.topView.isHidden = false
|
||||
strongSelf?.bottomView.isHidden = true
|
||||
strongSelf?.verticalStack.layoutIfNeeded()
|
||||
}
|
||||
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) {
|
||||
guard bottomView.isHidden else { return }
|
||||
performBlockOperation { [weak self] (operation) in
|
||||
let strongSelf = self
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded()
|
||||
strongSelf?.topView.button.isUserInteractionEnabled = false
|
||||
let animation = {
|
||||
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 {
|
||||
UIView.animate(withDuration: 0.5, animations: animation, completion: completion)
|
||||
} else {
|
||||
animation()
|
||||
completion(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 120
|
||||
}
|
||||
|
||||
/// Collapse if focus is no longer on this top alert.
|
||||
@objc func accessibilityFocusChanged(notification: Notification) {
|
||||
if !MVMCoreUIUtility.viewContainsAccessiblityFocus(self) {
|
||||
NotificationCenter.default.removeObserver(self, name: UIAccessibility.elementFocusedNotification, object: nil)
|
||||
collapse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CollapsableNotification: StatusBarUI {
|
||||
func getStatusBarUI() -> (color: UIColor, style: UIStatusBarStyle) {
|
||||
let color = backgroundColor ?? UIColor.mvmGreen
|
||||
var greyScale: CGFloat = 0
|
||||
topView.label.textColor.getWhite(&greyScale, alpha: nil)
|
||||
return (color, greyScale > 0.5 ? .lightContent : .default)
|
||||
}
|
||||
}
|
||||
|
||||
extension CollapsableNotification: AccessibilityProtocol {
|
||||
public func getAccessibilityLayoutChangedArgument() -> Any? {
|
||||
if !topView.isHidden {
|
||||
return topView
|
||||
} else {
|
||||
return bottomView.headline
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,16 +8,12 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class CollapsableNotificationModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "collapsableNotification"
|
||||
public var moleculeName: String = CollapsableNotificationModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public class CollapsableNotificationModel: NotificationModel {
|
||||
public class override var identifier: String {
|
||||
return "collapsableNotification"
|
||||
}
|
||||
public var topLabel: LabelModel
|
||||
public var topAction: ActionModelProtocol?
|
||||
public var headline: LabelModel
|
||||
public var body: LabelModel?
|
||||
public var button: ButtonModel?
|
||||
public var closeButton: NotificationXButtonModel?
|
||||
public var alwaysShowTopLabel = false
|
||||
public var collapseTime: Int = 5
|
||||
public var initiallyCollapsed = false
|
||||
@ -25,18 +21,23 @@ public class CollapsableNotificationModel: MoleculeModelProtocol {
|
||||
|
||||
init(with topLabel: LabelModel, headline: LabelModel) {
|
||||
self.topLabel = topLabel
|
||||
self.headline = headline
|
||||
super.init(with: headline)
|
||||
}
|
||||
|
||||
override func setDefault() {
|
||||
super.setDefault()
|
||||
if topLabel.textColor == nil {
|
||||
topLabel.textColor = Color(uiColor: .white)
|
||||
}
|
||||
if topLabel.textAlignment == nil {
|
||||
topLabel.textAlignment = .center
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case topLabel
|
||||
case topAction
|
||||
case headline
|
||||
case body
|
||||
case button
|
||||
case closeButton
|
||||
case alwaysShowTopLabel
|
||||
case collapseTime
|
||||
case initiallyCollapsed
|
||||
@ -46,12 +47,7 @@ public class CollapsableNotificationModel: MoleculeModelProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
topLabel = try typeContainer.decode(LabelModel.self, forKey: .topLabel)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
topAction = try typeContainer.decodeModelIfPresent(codingKey: .topAction)
|
||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
|
||||
closeButton = try typeContainer.decodeIfPresent(NotificationXButtonModel.self, forKey: .closeButton)
|
||||
if let alwaysShowTopLabel = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowTopLabel) {
|
||||
self.alwaysShowTopLabel = alwaysShowTopLabel
|
||||
}
|
||||
@ -62,18 +58,15 @@ public class CollapsableNotificationModel: MoleculeModelProtocol {
|
||||
self.initiallyCollapsed = initiallyCollapsed
|
||||
}
|
||||
pages = try typeContainer.decodeIfPresent([String].self, forKey: .pages)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(topLabel, forKey: .topLabel)
|
||||
try container.encodeModelIfPresent(topAction, forKey: .topAction)
|
||||
try container.encode(headline, forKey: .headline)
|
||||
try container.encodeIfPresent(body, forKey: .body)
|
||||
try container.encodeIfPresent(button, forKey: .button)
|
||||
try container.encodeIfPresent(closeButton, forKey: .closeButton)
|
||||
try container.encode(alwaysShowTopLabel, forKey: .alwaysShowTopLabel)
|
||||
try container.encode(collapseTime, forKey: .collapseTime)
|
||||
try container.encode(initiallyCollapsed, forKey: .initiallyCollapsed)
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
//
|
||||
// CollapsableNotificationTopView.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 9/18/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class CollapsableNotificationTopView: View {
|
||||
public let label: Label = {
|
||||
let label = Label(fontStyle: .BoldBodySmall)
|
||||
label.numberOfLines = 1
|
||||
label.textAlignment = .center
|
||||
label.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||
return label
|
||||
}()
|
||||
|
||||
public let button: Button = {
|
||||
let button = Button(type: .custom)
|
||||
button.backgroundColor = .clear
|
||||
button.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
|
||||
button.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
|
||||
return button
|
||||
}()
|
||||
|
||||
public override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
addSubview(label)
|
||||
NSLayoutConstraint.constraintPinSubview(label, pinTop: true, topConstant: 0, pinBottom: true, bottomConstant: 0, pinLeft: true, leftConstant: PaddingThree, pinRight: true, rightConstant: PaddingThree)
|
||||
|
||||
addSubview(button)
|
||||
NSLayoutConstraint.constraintPinSubview(button, pinTop: true, topConstant: 0, pinBottom: true, bottomConstant: -5, pinLeft: true, leftConstant: 0, pinRight: true, rightConstant: 0)
|
||||
|
||||
// Listen for status bar touches.
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(pressed(_:)), name: NSNotification.Name(rawValue: NotificationStatusBarTouched), object: nil)
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
label.updateView(size)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
label.setFontStyle(.BoldBodySmall)
|
||||
label.textColor = .white
|
||||
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) {
|
||||
button.callActionBlock(button)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
//
|
||||
// Notification.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 9/16/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class NotificationView: View {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
|
||||
public let headline = Label(fontStyle: .BoldBodySmall)
|
||||
public let body = Label(fontStyle: .RegularBodySmall)
|
||||
public let button = PillButton(asPrimaryButton: false, makeTiny: true)
|
||||
public let closeButton = NotificationXButton()
|
||||
public var labelStack: Stack<StackModel>!
|
||||
public var horizontalStack: Stack<StackModel>!
|
||||
|
||||
// Legacy constant
|
||||
private static let viewHeight: CGFloat = 96.0
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Life Cycle
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func setupView() {
|
||||
super.setupView()
|
||||
reset()
|
||||
|
||||
labelStack = Stack<StackModel>.createStack(with: [headline, body], spacing: 0)
|
||||
horizontalStack = Stack<StackModel>.createStack(with: [(view: labelStack, model: StackItemModel()),(view: button, model: StackItemModel(horizontalAlignment: .fill)),(view: closeButton, model: StackItemModel(horizontalAlignment: .fill))], axis: .horizontal)
|
||||
addSubview(horizontalStack)
|
||||
NSLayoutConstraint.constraintPinSubview(horizontalStack, pinTop: true, topConstant: PaddingTwo, pinBottom: true, bottomConstant: PaddingTwo, pinLeft: true, leftConstant: PaddingThree, pinRight: true, rightConstant: PaddingThree)
|
||||
labelStack.restack()
|
||||
horizontalStack.restack()
|
||||
|
||||
heightAnchor.constraint(equalToConstant: Self.viewHeight).isActive = true
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
horizontalStack.updateView(size)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .mvmGreen()
|
||||
headline.textColor = .white
|
||||
body.textColor = .white
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? NotificationModel else { return }
|
||||
labelStack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, nil)
|
||||
horizontalStack.updateContainedMolecules(with: [labelStack.stackModel, model.button, model.closeButton], delegateObject, nil)
|
||||
updateAccessibility()
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return viewHeight
|
||||
}
|
||||
|
||||
open func updateAccessibility() {
|
||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: headline)
|
||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: body)
|
||||
MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: button)
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationView: AccessibilityProtocol {
|
||||
public func getAccessibilityLayoutChangedArgument() -> Any? {
|
||||
return headline
|
||||
}
|
||||
}
|
||||
@ -9,8 +9,9 @@
|
||||
import Foundation
|
||||
|
||||
public class NotificationModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "notification"
|
||||
public var moleculeName: String = NotificationModel.identifier
|
||||
public class var identifier: String {
|
||||
return "notification"
|
||||
}
|
||||
public var backgroundColor: Color?
|
||||
public var headline: LabelModel
|
||||
public var body: LabelModel?
|
||||
@ -20,4 +21,51 @@ public class NotificationModel: MoleculeModelProtocol {
|
||||
init(with headline: LabelModel) {
|
||||
self.headline = headline
|
||||
}
|
||||
|
||||
func setDefault() {
|
||||
if backgroundColor == nil {
|
||||
backgroundColor = Color(uiColor: .mvmGreen())
|
||||
}
|
||||
if headline.textColor == nil {
|
||||
headline.textColor = Color(uiColor: .white)
|
||||
}
|
||||
if body?.textColor == nil {
|
||||
body?.textColor = Color(uiColor: .white)
|
||||
}
|
||||
if button?.style == nil {
|
||||
button?.style = .secondary
|
||||
}
|
||||
button?.size = .tiny
|
||||
button?.enabledTextColor = Color(uiColor: .white)
|
||||
button?.enabledBorderColor = Color(uiColor: .white)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case headline
|
||||
case body
|
||||
case button
|
||||
case closeButton
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
|
||||
closeButton = try typeContainer.decodeIfPresent(NotificationXButtonModel.self, forKey: .closeButton)
|
||||
setDefault()
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(headline, forKey: .headline)
|
||||
try container.encodeIfPresent(body, forKey: .body)
|
||||
try container.encodeIfPresent(button, forKey: .button)
|
||||
try container.encodeIfPresent(closeButton, forKey: .closeButton)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
//
|
||||
// NotificationXButton.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 9/17/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class NotificationXButton: Button {
|
||||
|
||||
open func closeTopAlert() {
|
||||
if let delegate = MVMCoreUITopAlertView.sharedGlobal()?.animationDelegate {
|
||||
delegate.topAlertCloseButtonPressed()
|
||||
} else {
|
||||
MVMCoreUISession.sharedGlobal()?.topAlertView?.hideAlertView(true, completionHandler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
open override func setupView() {
|
||||
if let image = MVMCoreUIUtility.imageNamed("nav_close")?.withRenderingMode(.alwaysTemplate) {
|
||||
setImage(image, for: .normal)
|
||||
}
|
||||
tintColor = .white
|
||||
adjustsImageWhenHighlighted = false
|
||||
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "AccCloseButton")
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? NotificationXButtonModel else { return }
|
||||
tintColor = model.color.uiColor
|
||||
|
||||
// TODO: Temporary, consider action for dismissing top alert
|
||||
if model.action.actionType == ActionNoopModel.identifier {
|
||||
addActionBlock(event: .touchUpInside) { (button) in
|
||||
(button as? NotificationXButton)?.closeTopAlert()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,27 +8,32 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class NotificationXButtonModel: Codable {
|
||||
public var color: Color?
|
||||
public var action: ActionModelProtocol?
|
||||
public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
public static var identifier: String = "notificationXButton"
|
||||
public var backgroundColor: Color?
|
||||
public var color = Color(uiColor: .white)
|
||||
public var action: ActionModelProtocol = ActionNoopModel()
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case color
|
||||
case action
|
||||
}
|
||||
|
||||
public init() {
|
||||
}
|
||||
public init() {}
|
||||
|
||||
public required init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color)
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) ?? Color(uiColor: .white)
|
||||
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
|
||||
self.action = action
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(color, forKey: .color)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,12 +72,12 @@ public typealias ButtonAction = (Button) -> ()
|
||||
buttonAction?(self)
|
||||
}
|
||||
|
||||
open func set(with actionModel: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
open func set(with actionModel: ActionModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
self.actionModel = actionModel
|
||||
buttonDelegate = delegateObject?.buttonDelegate
|
||||
|
||||
addActionBlock(event: .touchUpInside) { [weak self] sender in
|
||||
guard let self = self else { return }
|
||||
guard let self = self, let actionModel = actionModel else { return }
|
||||
Self.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
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 *viewController = self.navigationController.topViewController;
|
||||
if ([viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) {
|
||||
viewController = [viewController performSelector:@selector(getCurrentViewController)];
|
||||
}
|
||||
__block UIViewController *viewController = nil;
|
||||
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
|
||||
viewController = self.navigationController.topViewController;
|
||||
if ([viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) {
|
||||
viewController = [viewController performSelector:@selector(getCurrentViewController)];
|
||||
}
|
||||
}];
|
||||
return viewController;
|
||||
}
|
||||
|
||||
|
||||
@ -56,21 +56,22 @@ public extension MVMCoreUITopAlertView {
|
||||
}
|
||||
|
||||
/// Returns the top alert molecule to use and status bar color legacy style.
|
||||
@objc func molecule(for topAlertObject: MVMCoreTopAlertObject, statusBarColor: AutoreleasingUnsafeMutablePointer<UIColor?>?, statusBarStyle: UnsafeMutablePointer<UIStatusBarStyle>?) -> MVMCoreUITopAlertBaseView? {
|
||||
@objc func molecule(for topAlertObject: MVMCoreTopAlertObject, statusBarColor: AutoreleasingUnsafeMutablePointer<UIColor?>?, statusBarStyle: UnsafeMutablePointer<UIStatusBarStyle>?) -> UIView? {
|
||||
do {
|
||||
let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
|
||||
guard let json = topAlertObject.json else { return nil }
|
||||
let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject)
|
||||
guard let molecule = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil),
|
||||
let view = molecule as? MVMCoreUITopAlertBaseView else {
|
||||
throw ModelRegistry.Error.decoderOther(message: "Molecule not a top alert")
|
||||
guard let molecule = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil) else {
|
||||
throw ModelRegistry.Error.decoderOther(message: "Molecule not mapped")
|
||||
}
|
||||
if let castView = view as? StatusBarUI {
|
||||
if let castView = molecule as? StatusBarUI {
|
||||
let (color, style) = castView.getStatusBarUI()
|
||||
statusBarColor?.pointee = color
|
||||
statusBarStyle?.pointee = style
|
||||
}
|
||||
return view
|
||||
// TODO: Temporary, waiting for actual restriction from design.
|
||||
molecule.heightAnchor.constraint(lessThanOrEqualToConstant: 140).isActive = true
|
||||
return molecule
|
||||
} catch {
|
||||
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") {
|
||||
MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject)
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
#import <MVMCoreUI/ButtonDelegateProtocol.h>
|
||||
|
||||
@class MVMCoreTopAlertObject;
|
||||
@class MVMCoreUITopAlertBaseView;
|
||||
|
||||
@interface MVMCoreUITopAlertView : UIView <MVMCoreViewProtocol, MVMCoreTopAlertViewProtocol, MVMCoreLoadDelegateProtocol, MVMCoreActionDelegateProtocol, MVMCorePresentationDelegateProtocol, ButtonDelegateProtocol>
|
||||
|
||||
@ -45,7 +44,7 @@
|
||||
- (void)resetDefaultBackgroundColor:(nullable UIColor *)backgroundColor basedOnStatusBarStyle:(UIStatusBarStyle)style;
|
||||
|
||||
// Can be subclassed for custom views.
|
||||
- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle;
|
||||
- (nonnull UIView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle;
|
||||
|
||||
/// Get the background color based on the type
|
||||
- (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type;
|
||||
|
||||
@ -124,7 +124,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
}
|
||||
}
|
||||
|
||||
- (nonnull MVMCoreUITopAlertBaseView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle {
|
||||
- (nonnull UIView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle {
|
||||
if (topAlertObject.json) {
|
||||
return [self moleculeFor:topAlertObject statusBarColor:statusBarColor statusBarStyle:statusBarStyle];
|
||||
} else {
|
||||
@ -169,8 +169,10 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
|
||||
UIColor *statusBarColor = nil;
|
||||
UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault;
|
||||
MVMCoreUITopAlertBaseView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle];
|
||||
[view updateView:CGRectGetWidth(self.bounds)];
|
||||
UIView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle];
|
||||
if ([view conformsToProtocol:@protocol(MVMCoreViewProtocol)]) {
|
||||
[((UIView <MVMCoreViewProtocol>*)view) updateView:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
if (!statusBarColor) {
|
||||
statusBarColor = [UIColor whiteColor];
|
||||
}
|
||||
@ -185,7 +187,20 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
[[MVMCoreUISession sharedGlobal].splitViewController.parentViewController setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
|
||||
- (void)showAlertView:(nullable MVMCoreUITopAlertBaseView *)view topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||
- (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 {
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) {
|
||||
@ -205,8 +220,9 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
} completion:^(BOOL finished) {
|
||||
[weakSelf.superview layoutIfNeeded];
|
||||
[weakSelf.animationDelegate topAlertViewFinishAnimation];
|
||||
[view handleAccessibility];
|
||||
|
||||
[weakSelf updateAccessibilityForTopAlert:view];
|
||||
|
||||
[MVMCoreDispatchUtility performBlockInBackground:^{
|
||||
if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewShown:topAlertObject:)]) {
|
||||
[weakSelf.topAlertObject.delegate topAlertViewShown:view topAlertObject:topAlertObject];
|
||||
|
||||
@ -89,7 +89,11 @@
|
||||
if (![focusedElement isKindOfClass:[UIView class]]) {
|
||||
return NO;
|
||||
}
|
||||
return [(UIView *)focusedElement isDescendantOfView:view];
|
||||
__block BOOL containsFocus;
|
||||
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
|
||||
containsFocus = [(UIView *)focusedElement isDescendantOfView:view];
|
||||
}];
|
||||
return containsFocus;
|
||||
}
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
Loading…
Reference in New Issue
Block a user