molecular
This commit is contained in:
parent
b01a34365b
commit
ea50b838d2
@ -318,6 +318,7 @@
|
|||||||
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
|
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
|
||||||
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.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 */; };
|
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 */; };
|
D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; };
|
||||||
D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */; };
|
D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */; };
|
||||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; };
|
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; };
|
||||||
@ -481,6 +482,9 @@
|
|||||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; };
|
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; };
|
||||||
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; };
|
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; };
|
||||||
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 */; };
|
||||||
|
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
||||||
|
D2FA83D62515021F00564112 /* NotificationStatusBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* NotificationStatusBar.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 */; };
|
||||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
|
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB06250A2293456500B72DD3 /* LeftRightLabelView.swift */; };
|
||||||
@ -806,6 +810,7 @@
|
|||||||
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = "<group>"; };
|
||||||
@ -970,6 +975,9 @@
|
|||||||
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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 /* NotificationStatusBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationStatusBar.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>"; };
|
||||||
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>"; };
|
||||||
@ -2077,9 +2085,13 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */,
|
D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */,
|
||||||
|
D2FA83D12513EA6900564112 /* NotificationXButton.swift */,
|
||||||
D2CAC7CC251104FE00C75681 /* NotificationModel.swift */,
|
D2CAC7CC251104FE00C75681 /* NotificationModel.swift */,
|
||||||
|
D23118B225124E18001C8440 /* Notification.swift */,
|
||||||
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */,
|
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */,
|
||||||
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */,
|
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */,
|
||||||
|
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */,
|
||||||
|
D2FA83D52515021F00564112 /* NotificationStatusBar.swift */,
|
||||||
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */,
|
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */,
|
||||||
);
|
);
|
||||||
path = TopNotification;
|
path = TopNotification;
|
||||||
@ -2460,6 +2472,7 @@
|
|||||||
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
||||||
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */,
|
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */,
|
||||||
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
|
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
|
||||||
|
D23118B325124E18001C8440 /* Notification.swift in Sources */,
|
||||||
AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */,
|
AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */,
|
||||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
||||||
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
||||||
@ -2515,6 +2528,7 @@
|
|||||||
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */,
|
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */,
|
||||||
C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */,
|
C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */,
|
||||||
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */,
|
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */,
|
||||||
|
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */,
|
||||||
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */,
|
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */,
|
||||||
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */,
|
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */,
|
||||||
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */,
|
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */,
|
||||||
@ -2560,6 +2574,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 */,
|
||||||
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 */,
|
||||||
@ -2605,6 +2620,7 @@
|
|||||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
||||||
|
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */,
|
||||||
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
||||||
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
|
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
|
||||||
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */,
|
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */,
|
||||||
|
|||||||
@ -233,8 +233,8 @@ import Foundation
|
|||||||
MoleculeObjectMapping.shared()?.register(viewClass: LockupsPlanSMLXL.self, viewModelClass: LockupsPlanSMLXLModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: LockupsPlanSMLXL.self, viewModelClass: LockupsPlanSMLXLModel.self)
|
||||||
|
|
||||||
// MARK: - Top Notifications
|
// MARK: - Top Notifications
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: MVMCoreUITopAlertMainView.self, viewModelClass: NotificationModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: NotificationView.self, viewModelClass: NotificationModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: MVMCoreUITopAlertExpandableView.self, viewModelClass: CollapsableNotificationModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: CollapsableNotification.self, viewModelClass: CollapsableNotificationModel.self)
|
||||||
|
|
||||||
// MARK:- Helper models
|
// MARK:- Helper models
|
||||||
try? ModelRegistry.register(RuleRequiredModel.self)
|
try? ModelRegistry.register(RuleRequiredModel.self)
|
||||||
|
|||||||
@ -0,0 +1,168 @@
|
|||||||
|
//
|
||||||
|
// 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 = NotificationStatusBar()
|
||||||
|
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)
|
||||||
|
bottomView.set(with: model, delegateObject, additionalData)
|
||||||
|
updateAccessibilityLabel()
|
||||||
|
|
||||||
|
topView.isHidden = !model.alwaysShowTopLabel && !model.initiallyCollapsed
|
||||||
|
topView.button.isUserInteractionEnabled = model.initiallyCollapsed
|
||||||
|
bottomView.isHidden = model.initiallyCollapsed
|
||||||
|
verticalStack.layoutIfNeeded()
|
||||||
|
|
||||||
|
if !model.initiallyCollapsed {
|
||||||
|
collapse(with: .now() + DispatchTimeInterval.seconds(model.collapseTime))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open func collapse(with delay: DispatchTime) {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: delay) { [weak self] in
|
||||||
|
self?.collapse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open func collapse(animated: Bool = true) {
|
||||||
|
let animation = { [weak self] in
|
||||||
|
self?.topView.isHidden = false
|
||||||
|
self?.bottomView.isHidden = true
|
||||||
|
self?.verticalStack.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.5, animations: animation) { [weak self] (finished) in
|
||||||
|
self?.topView.button.isUserInteractionEnabled = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
animation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open func expand(topViewShowing: Bool = false, animated: Bool = true) {
|
||||||
|
topView.button.isUserInteractionEnabled = false
|
||||||
|
let animation = { [weak self] in
|
||||||
|
self?.topView.isHidden = !topViewShowing
|
||||||
|
self?.bottomView.isHidden = false
|
||||||
|
self?.verticalStack.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.5, animations: animation) { [weak self] (finished) in
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
animation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
|
return 96
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
func getAccessibilityMessage() -> String? {
|
||||||
|
|
||||||
|
guard let leftImageLabel = leftImage.imageView.accessibilityLabel else {
|
||||||
|
return eyebrowHeadlineBodyLink.getAccessibilityMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,16 +8,12 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class CollapsableNotificationModel: MoleculeModelProtocol {
|
public class CollapsableNotificationModel: NotificationModel {
|
||||||
public static var identifier: String = "collapsableNotification"
|
public class override var identifier: String {
|
||||||
public var moleculeName: String = CollapsableNotificationModel.identifier
|
return "collapsableNotification"
|
||||||
public var backgroundColor: Color?
|
}
|
||||||
public var topLabel: LabelModel
|
public var topLabel: LabelModel
|
||||||
public var topAction: ActionModelProtocol?
|
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 alwaysShowTopLabel = false
|
||||||
public var collapseTime: Int = 5
|
public var collapseTime: Int = 5
|
||||||
public var initiallyCollapsed = false
|
public var initiallyCollapsed = false
|
||||||
@ -25,18 +21,23 @@ public class CollapsableNotificationModel: MoleculeModelProtocol {
|
|||||||
|
|
||||||
init(with topLabel: LabelModel, headline: LabelModel) {
|
init(with topLabel: LabelModel, headline: LabelModel) {
|
||||||
self.topLabel = topLabel
|
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 {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case moleculeName
|
case moleculeName
|
||||||
case backgroundColor
|
|
||||||
case topLabel
|
case topLabel
|
||||||
case topAction
|
case topAction
|
||||||
case headline
|
|
||||||
case body
|
|
||||||
case button
|
|
||||||
case closeButton
|
|
||||||
case alwaysShowTopLabel
|
case alwaysShowTopLabel
|
||||||
case collapseTime
|
case collapseTime
|
||||||
case initiallyCollapsed
|
case initiallyCollapsed
|
||||||
@ -46,12 +47,7 @@ public class CollapsableNotificationModel: MoleculeModelProtocol {
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
topLabel = try typeContainer.decode(LabelModel.self, forKey: .topLabel)
|
topLabel = try typeContainer.decode(LabelModel.self, forKey: .topLabel)
|
||||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
|
||||||
topAction = try typeContainer.decodeModelIfPresent(codingKey: .topAction)
|
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) {
|
if let alwaysShowTopLabel = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowTopLabel) {
|
||||||
self.alwaysShowTopLabel = alwaysShowTopLabel
|
self.alwaysShowTopLabel = alwaysShowTopLabel
|
||||||
}
|
}
|
||||||
@ -62,18 +58,15 @@ public class CollapsableNotificationModel: MoleculeModelProtocol {
|
|||||||
self.initiallyCollapsed = initiallyCollapsed
|
self.initiallyCollapsed = initiallyCollapsed
|
||||||
}
|
}
|
||||||
pages = try typeContainer.decodeIfPresent([String].self, forKey: .pages)
|
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)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
|
||||||
try container.encode(topLabel, forKey: .topLabel)
|
try container.encode(topLabel, forKey: .topLabel)
|
||||||
try container.encodeModelIfPresent(topAction, forKey: .topAction)
|
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(alwaysShowTopLabel, forKey: .alwaysShowTopLabel)
|
||||||
try container.encode(collapseTime, forKey: .collapseTime)
|
try container.encode(collapseTime, forKey: .collapseTime)
|
||||||
try container.encode(initiallyCollapsed, forKey: .initiallyCollapsed)
|
try container.encode(initiallyCollapsed, forKey: .initiallyCollapsed)
|
||||||
|
|||||||
117
MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift
Normal file
117
MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
//
|
||||||
|
// 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>!
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// 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: 96).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)
|
||||||
|
|
||||||
|
updateAccessibilityLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
|
return 96
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
func getAccessibilityMessage() -> String? {
|
||||||
|
|
||||||
|
guard let leftImageLabel = leftImage.imageView.accessibilityLabel else {
|
||||||
|
return eyebrowHeadlineBodyLink.getAccessibilityMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,8 +9,9 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class NotificationModel: MoleculeModelProtocol {
|
public class NotificationModel: MoleculeModelProtocol {
|
||||||
public static var identifier: String = "notification"
|
public class var identifier: String {
|
||||||
public var moleculeName: String = NotificationModel.identifier
|
return "notification"
|
||||||
|
}
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
public var headline: LabelModel
|
public var headline: LabelModel
|
||||||
public var body: LabelModel?
|
public var body: LabelModel?
|
||||||
@ -20,4 +21,51 @@ public class NotificationModel: MoleculeModelProtocol {
|
|||||||
init(with headline: LabelModel) {
|
init(with headline: LabelModel) {
|
||||||
self.headline = headline
|
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,56 @@
|
|||||||
|
//
|
||||||
|
// NotificationStatusBar.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 9/18/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers open class NotificationStatusBar: 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
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func pressed(_ sender: Notification) {
|
||||||
|
button.callActionBlock(button)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
|
||||||
|
// temporary
|
||||||
|
if model.action.actionType == ActionNoopModel.identifier {
|
||||||
|
addActionBlock(event: .touchUpInside) { (button) in
|
||||||
|
(button as? NotificationXButton)?.closeTopAlert()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,27 +8,32 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class NotificationXButtonModel: Codable {
|
public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||||
public var color: Color?
|
public static var identifier: String = "notificationXButton"
|
||||||
public var action: ActionModelProtocol?
|
public var backgroundColor: Color?
|
||||||
|
public var color = Color(uiColor: .white)
|
||||||
|
public var action: ActionModelProtocol = ActionNoopModel()
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case moleculeName
|
||||||
case color
|
case color
|
||||||
case action
|
case action
|
||||||
}
|
}
|
||||||
|
|
||||||
public init() {
|
public init() {}
|
||||||
}
|
|
||||||
|
|
||||||
public required init(from decoder: Decoder) throws {
|
public required init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color)
|
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) ?? Color(uiColor: .white)
|
||||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encodeIfPresent(color, forKey: .color)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeModelIfPresent(action, forKey: .action)
|
try container.encode(color, forKey: .color)
|
||||||
|
try container.encodeModel(action, forKey: .action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,12 +72,12 @@ public typealias ButtonAction = (Button) -> ()
|
|||||||
buttonAction?(self)
|
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
|
self.actionModel = actionModel
|
||||||
buttonDelegate = delegateObject?.buttonDelegate
|
buttonDelegate = delegateObject?.buttonDelegate
|
||||||
|
|
||||||
addActionBlock(event: .touchUpInside) { [weak self] sender in
|
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)
|
Self.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,21 +56,23 @@ public extension MVMCoreUITopAlertView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the top alert molecule to use and status bar color legacy style.
|
/// 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 {
|
do {
|
||||||
let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
|
let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
|
||||||
guard let json = topAlertObject.json else { return nil }
|
guard let json = topAlertObject.json else { return nil }
|
||||||
let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject)
|
let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject)
|
||||||
guard let molecule = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil),
|
guard let molecule = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil)/*,
|
||||||
let view = molecule as? MVMCoreUITopAlertBaseView else {
|
let view = molecule as? MVMCoreUITopAlertBaseView*/ else {
|
||||||
throw ModelRegistry.Error.decoderOther(message: "Molecule not a top alert")
|
throw ModelRegistry.Error.decoderOther(message: "Molecule not a top alert")
|
||||||
}
|
}
|
||||||
if let castView = view as? StatusBarUI {
|
if let castView = molecule as? StatusBarUI {
|
||||||
let (color, style) = castView.getStatusBarUI()
|
let (color, style) = castView.getStatusBarUI()
|
||||||
statusBarColor?.pointee = color
|
statusBarColor?.pointee = color
|
||||||
statusBarStyle?.pointee = style
|
statusBarStyle?.pointee = style
|
||||||
}
|
}
|
||||||
return view
|
// Temporary
|
||||||
|
molecule.heightAnchor.constraint(lessThanOrEqualToConstant: 150).isActive = true
|
||||||
|
return molecule
|
||||||
} catch {
|
} catch {
|
||||||
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") {
|
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") {
|
||||||
MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject)
|
MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject)
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
#import <MVMCoreUI/ButtonDelegateProtocol.h>
|
#import <MVMCoreUI/ButtonDelegateProtocol.h>
|
||||||
|
|
||||||
@class MVMCoreTopAlertObject;
|
@class MVMCoreTopAlertObject;
|
||||||
@class MVMCoreUITopAlertBaseView;
|
|
||||||
|
|
||||||
@interface MVMCoreUITopAlertView : UIView <MVMCoreViewProtocol, MVMCoreTopAlertViewProtocol, MVMCoreLoadDelegateProtocol, MVMCoreActionDelegateProtocol, MVMCorePresentationDelegateProtocol, ButtonDelegateProtocol>
|
@interface MVMCoreUITopAlertView : UIView <MVMCoreViewProtocol, MVMCoreTopAlertViewProtocol, MVMCoreLoadDelegateProtocol, MVMCoreActionDelegateProtocol, MVMCorePresentationDelegateProtocol, ButtonDelegateProtocol>
|
||||||
|
|
||||||
@ -45,7 +44,7 @@
|
|||||||
- (void)resetDefaultBackgroundColor:(nullable UIColor *)backgroundColor basedOnStatusBarStyle:(UIStatusBarStyle)style;
|
- (void)resetDefaultBackgroundColor:(nullable UIColor *)backgroundColor basedOnStatusBarStyle:(UIStatusBarStyle)style;
|
||||||
|
|
||||||
// Can be subclassed for custom views.
|
// 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
|
/// Get the background color based on the type
|
||||||
- (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)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) {
|
if (topAlertObject.json) {
|
||||||
return [self moleculeFor:topAlertObject statusBarColor:statusBarColor statusBarStyle:statusBarStyle];
|
return [self moleculeFor:topAlertObject statusBarColor:statusBarColor statusBarStyle:statusBarStyle];
|
||||||
} else {
|
} else {
|
||||||
@ -169,8 +169,10 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
|
|
||||||
UIColor *statusBarColor = nil;
|
UIColor *statusBarColor = nil;
|
||||||
UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault;
|
UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault;
|
||||||
MVMCoreUITopAlertBaseView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle];
|
UIView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle];
|
||||||
[view updateView:CGRectGetWidth(self.bounds)];
|
if ([view conformsToProtocol:@protocol(MVMCoreViewProtocol)]) {
|
||||||
|
[((UIView <MVMCoreViewProtocol>*)view) updateView:CGRectGetWidth(self.bounds)];
|
||||||
|
}
|
||||||
if (!statusBarColor) {
|
if (!statusBarColor) {
|
||||||
statusBarColor = [UIColor whiteColor];
|
statusBarColor = [UIColor whiteColor];
|
||||||
}
|
}
|
||||||
@ -185,7 +187,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
[[MVMCoreUISession sharedGlobal].splitViewController.parentViewController setNeedsStatusBarAppearanceUpdate];
|
[[MVMCoreUISession sharedGlobal].splitViewController.parentViewController setNeedsStatusBarAppearanceUpdate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showAlertView:(nullable MVMCoreUITopAlertBaseView *)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;
|
||||||
MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) {
|
MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) {
|
||||||
@ -205,8 +207,10 @@ 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];
|
||||||
[view handleAccessibility];
|
if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) {
|
||||||
|
[((MVMCoreUITopAlertBaseView *)view) handleAccessibility];
|
||||||
|
}
|
||||||
|
|
||||||
[MVMCoreDispatchUtility performBlockInBackground:^{
|
[MVMCoreDispatchUtility performBlockInBackground:^{
|
||||||
if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewShown:topAlertObject:)]) {
|
if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewShown:topAlertObject:)]) {
|
||||||
[weakSelf.topAlertObject.delegate topAlertViewShown:view topAlertObject:topAlertObject];
|
[weakSelf.topAlertObject.delegate topAlertViewShown:view topAlertObject:topAlertObject];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user