diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 6c80ccd2..9ebcf41d 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -211,6 +211,8 @@ AA633B3324989ED500731E80 /* HeadersH2PricingTwoRows.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA633B3224989ED500731E80 /* HeadersH2PricingTwoRows.swift */; }; AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */; }; AA69AAF82445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */; }; + AA71AD3E24A32FCE00ACA76F /* HeadersH2LinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA71AD3D24A32FCE00ACA76F /* HeadersH2LinkModel.swift */; }; + AA71AD4024A32FE700ACA76F /* HeadersH2Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA71AD3F24A32FE700ACA76F /* HeadersH2Link.swift */; }; AA7F32AB246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7F32AA246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift */; }; AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7F32AC246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift */; }; AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */; }; @@ -290,6 +292,8 @@ 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 */; }; + 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 */; }; D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; }; D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; }; @@ -665,6 +669,8 @@ AA633B3224989ED500731E80 /* HeadersH2PricingTwoRows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2PricingTwoRows.swift; sourceTree = ""; }; AA69AAF52445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyText.swift; sourceTree = ""; }; AA69AAF72445BF6800AF3D3B /* ListLeftVariableCheckboxBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxBodyTextModel.swift; sourceTree = ""; }; + AA71AD3D24A32FCE00ACA76F /* HeadersH2LinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2LinkModel.swift; sourceTree = ""; }; + AA71AD3F24A32FE700ACA76F /* HeadersH2Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2Link.swift; sourceTree = ""; }; AA7F32AA246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAllTextAndLinksModel.swift; sourceTree = ""; }; AA7F32AC246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAllTextAndLinks.swift; sourceTree = ""; }; AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSwatchCollectionViewCell.swift; sourceTree = ""; }; @@ -744,6 +750,8 @@ D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = ""; }; D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = ""; }; D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = ""; }; + D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = ""; }; + D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinks.swift; sourceTree = ""; }; D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = ""; }; D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = ""; }; D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; @@ -1152,6 +1160,8 @@ 8D8067D22444473A00203BE8 /* ListRightVariablePriceChangeAllTextAndLinks.swift */, C7F8012223E846C300396FBD /* ListRVWheelModel.swift */, C7F8012023E8303200396FBD /* ListRVWheel.swift */, + D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */, + D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */, ); path = RightVariable; sourceTree = ""; @@ -1502,7 +1512,7 @@ children = ( AA104AC824472DC7004D2810 /* HeadersH1ButtonModel.swift */, AA104AC624472DB0004D2810 /* HeadersH1Button.swift */, - AA104ADB244734EA004D2810 /* HeadersH1LandingPageHeaderModel.swift */, + AA104ADB244734EA004D2810 /* HeadersH1LandingPageHeaderModel.swift */, AA104AD9244734DB004D2810 /* HeadersH1LandingPageHeader.swift */, ); path = H1; @@ -1517,8 +1527,10 @@ AA26850B244840AE00CE34CC /* HeadersH2TinyButton.swift */, AA104B1B24474A76004D2810 /* HeadersH2ButtonsModel.swift */, AA104B1924474A66004D2810 /* HeadersH2Buttons.swift */, - AA633B3024989EC000731E80 /* HeadersH2PricingTwoRowsModel.swift */, + AA633B3024989EC000731E80 /* HeadersH2PricingTwoRowsModel.swift */, AA633B3224989ED500731E80 /* HeadersH2PricingTwoRows.swift */, + AA71AD3D24A32FCE00ACA76F /* HeadersH2LinkModel.swift */, + AA71AD3F24A32FE700ACA76F /* HeadersH2Link.swift */, ); path = H2; sourceTree = ""; @@ -2143,6 +2155,7 @@ 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */, + AA71AD4024A32FE700ACA76F /* HeadersH2Link.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */, @@ -2310,6 +2323,7 @@ BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */, 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */, D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */, + D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */, 017BEB7B236763000024EF95 /* LineModel.swift in Sources */, D256E9932412880000360572 /* Header.swift in Sources */, 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */, @@ -2398,6 +2412,7 @@ 8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */, D264FAA5243F66A500D98315 /* CollectionTemplateItemProtocol.swift in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, + AA71AD3E24A32FCE00ACA76F /* HeadersH2LinkModel.swift in Sources */, 8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */, D243859923A16B1800332775 /* Container.swift in Sources */, D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */, @@ -2407,6 +2422,7 @@ AA26850E244840C300CE34CC /* HeadersH2TinyButtonModel.swift in Sources */, D260105F23D0BFFC00764D80 /* StackItem.swift in Sources */, 9432A79F23DB47BA00719041 /* EntryFieldContainer.swift in Sources */, + D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */, 01EB369323609801006832FA /* HeaderModel.swift in Sources */, 8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift index 2671fc0d..945229c7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/MultiProgress.swift @@ -63,7 +63,7 @@ import UIKit addSubview(stack) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) stack.backgroundColor = backgroundColor - stack.contentView.backgroundColor = .mvmWhite + stack.contentView.backgroundColor = .clear stack.model = StackModel(molecules: [], axis: .horizontal, spacing: 2) stack.stackModel?.horizontalAlignment = .leading @@ -111,7 +111,6 @@ import UIKit roundedCorners = multiProgressModel.roundedCorners ?? false thicknessConstraint?.constant = multiProgressModel.thickness ?? defaultHeight - stack.model?.backgroundColor = model.backgroundColor set(with: multiProgressModel.progressList, delegateObject, additionalData) } diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 17fabef7..02373958 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -44,8 +44,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) }() // Sizes are from InVision design specs. - static let containerSize = CGSize(width: 46, height: 24) - static let knobSize = CGSize(width: 22, height: 22) + static let containerSize = CGSize(width: 51, height: 31) + static let knobSize = CGSize(width: 28, height: 28) private var knobView: View = { let view = View() @@ -62,8 +62,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) didSet { isUserInteractionEnabled = isEnabled changeStateNoAnimation(isEnabled ? isOn : false) - backgroundColor = isEnabled ? (isOn ? containerTintColor.on : containerTintColor.off) : disabledTintColor.container - knobView.backgroundColor = isEnabled ? (isOn ? knobTintColor.on : knobTintColor.off) : disabledTintColor.knob + setToggleAppearanceFromState() + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: isEnabled ? "AccToggleHint" : "AccDisabled") } } @@ -96,8 +96,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) }, completion: nil) } else { - backgroundColor = isOn ? containerTintColor.on : containerTintColor.off - knobView.backgroundColor = isOn ? knobTintColor.on : knobTintColor.off + setToggleAppearanceFromState() self.constrainKnob() } @@ -143,14 +142,14 @@ public typealias ActionBlockConfirmation = () -> (Bool) private func constrainKnobOn() { - knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 1) + knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 2) knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor) } private func constrainKnobOff() { knobTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: knobView.trailingAnchor) - knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1) + knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 2) } //-------------------------------------------------- @@ -159,7 +158,6 @@ public typealias ActionBlockConfirmation = () -> (Bool) public override init(frame: CGRect) { super.init(frame: frame) - setupView() } public convenience override init() { @@ -225,7 +223,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) widthConstraint = widthAnchor.constraint(equalToConstant: Self.containerSize.width) widthConstraint?.isActive = true - layer.cornerRadius = Self.containerSize.height / 2.0 + layer.cornerRadius = Self.getContainerHeight() / 2.0 backgroundColor = containerTintColor.off addSubview(knobView) @@ -305,6 +303,16 @@ public typealias ActionBlockConfirmation = () -> (Bool) isAnimated = isAnimatedState } + override open func accessibilityActivate() -> Bool { + // Hold state in case User wanted isAnimated to remain off. + guard isUserInteractionEnabled else { return false } + let isAnimatedState = isAnimated + isAnimated = false + sendActions(for: .touchUpInside) + isAnimated = isAnimatedState + return true + } + //-------------------------------------------------- // MARK: - UIResponder //-------------------------------------------------- @@ -342,6 +350,12 @@ public typealias ActionBlockConfirmation = () -> (Bool) // MARK: - Animations //-------------------------------------------------- + public func setToggleAppearanceFromState() { + + backgroundColor = isEnabled ? isOn ? containerTintColor.on : containerTintColor.off : disabledTintColor.container + knobView.backgroundColor = isEnabled ? isOn ? knobTintColor.on : knobTintColor.off : disabledTintColor.knob + } + public func knobReformAnimation() { if isAnimated { diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index c6bb77bb..213355eb 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -180,6 +180,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableButtonAllTextAndLinks.self, viewModelClass: ListRightVariableButtonAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeBodyText.self, viewModelClass: ListRightVariablePriceChangeBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariablePriceChangeAllTextAndLinks.self, viewModelClass: ListRightVariablePriceChangeAllTextAndLinksModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListRightVariableToggleAllTextAndLinks.self, viewModelClass: ListRightVariableToggleAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self) @@ -210,6 +211,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2TinyButton.self, viewModelClass: HeadersH2TinyButtonModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Buttons.self, viewModelClass: HeadersH2ButtonsModel.self) MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2PricingTwoRows.self, viewModelClass: HeadersH2PricingTwoRowsModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2Link.self, viewModelClass: HeadersH2LinkModel.self) // Device Items MoleculeObjectMapping.shared()?.register(viewClass: ListDeviceComplexButtonMedium.self, viewModelClass: ListDeviceComplexButtonMediumModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift new file mode 100644 index 00000000..c5aaefc8 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2Link.swift @@ -0,0 +1,59 @@ +// +// HeadersH2Link.swift +// MVMCoreUI +// +// Created by Lekshmi S on 24/06/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class HeadersH2Link: HeaderView { + //-------------------------------------------------- + // MARK: - Outlets + //-------------------------------------------------- + public let headlineBody = HeadlineBody() + public let link = Link() + public let stack: Stack + + //------------------------------------------------------- + // MARK: - Initializers + //------------------------------------------------------- + public override init(frame: CGRect) { + stack = Stack.createStack(with: [headlineBody, link]) + super.init(frame: frame) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + //------------------------------------------------------- + // MARK: - Lifecycle + //------------------------------------------------------- + open override func setupView() { + super.setupView() + headlineBody.stylePageHeader() + addMolecule(stack) + stack.restack() + } + + //---------------------------------------------------- + // 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? HeadersH2LinkModel else { return } + headlineBody.set(with: model.headlineBody, delegateObject, additionalData) + link.set(with: model.link, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 121 + } + + open override func reset() { + super.reset() + headlineBody.stylePageHeader() + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift new file mode 100644 index 00000000..66189f99 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift @@ -0,0 +1,72 @@ +// +// HeadersH2LinkModel.swift +// MVMCoreUI +// +// Created by Lekshmi S on 24/06/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "headerH2Link" + public var headlineBody: HeadlineBodyModel + public var link: LinkModel + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(headlineBody: HeadlineBodyModel, link: LinkModel) { + self.headlineBody = headlineBody + self.link = link + super.init() + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + public override func setDefaults() { + if topPadding == nil { + topPadding = Padding.Component.VerticalMarginSpacing + } + if bottomPadding == nil { + bottomPadding = Padding.Component.VerticalMarginSpacing + } + super.setDefaults() + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case moleculeName + case headlineBody + case link + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody) + link = try typeContainer.decode(LinkModel.self, forKey: .link) + try super.init(from: decoder) + } + + 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.encode(headlineBody, forKey: .headlineBody) + try container.encode(link, forKey: .link) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableToggleAllTextAndLinks.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableToggleAllTextAndLinks.swift new file mode 100644 index 00000000..a631616b --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableToggleAllTextAndLinks.swift @@ -0,0 +1,114 @@ +// +// ListRightVariableToggleAllTextAndLinks.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 6/25/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ListRightVariableToggleAllTextAndLinks: TableViewCell { + //----------------------------------------------------- + // MARK: - Outlets + //----------------------------------------------------- + + public let toggle = Toggle() + public let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink() + + //----------------------------------------------------- + // MARK: - Properties + //----------------------------------------------------- + + public var stack: Stack! + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading)), + (view: toggle, model: StackItemModel(horizontalAlignment: .fill))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + + //----------------------------------------------------- + // MARK: - Lifecycle + //----------------------------------------------------- + + override open func setupView() { + super.setupView() + addMolecule(stack) + stack.restack() + } + + //----------------------------------------------------- + // MARK: - Molecular + //----------------------------------------------------- + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListRightVariableToggleAllTextAndLinksModel else { return } + toggle.set(with: model.toggle, delegateObject, additionalData) + eyebrowHeadlineBodyLink.set(with: model.eyebrowHeadlineBodyLink, delegateObject, additionalData) + updateAccessibilityLabel() + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 90 + } + + //---------------------------------------------------- + // MARK: - Accessibility + //---------------------------------------------------- + + func getAccessibilityMessage() -> String? { + guard let toggleMessage = toggle.accessibilityLabel else { + return eyebrowHeadlineBodyLink.getAccessibilityMessage() + } + guard let label = eyebrowHeadlineBodyLink.getAccessibilityMessage() else { + return toggleMessage + } + return label + ", " + toggleMessage + } + + func updateAccessibilityLabel() { + accessibilityHint = toggle.accessibilityHint + accessibilityTraits = toggle.accessibilityTraits + accessibilityValue = toggle.accessibilityValue + let linkShowing = eyebrowHeadlineBodyLink.link.titleLabel?.text?.count ?? 0 > 0 + if !linkShowing && accessoryView == nil { + // Make whole cell focusable if one action + isAccessibilityElement = true + accessibilityLabel = getAccessibilityMessage() + } else { + // Make buttons focusable. + isAccessibilityElement = false + var elements: [Any] = [] + if let accessoryView = accessoryView { + accessoryView.accessibilityLabel = eyebrowHeadlineBodyLink.getAccessibilityMessage() + elements.append(accessoryView) + } else { + toggle.accessibilityLabel = getAccessibilityMessage() + } + elements.append(toggle) + + if linkShowing { + elements.append(eyebrowHeadlineBodyLink.link) + } + accessibilityElements = elements + } + } + + open override func accessibilityActivate() -> Bool { + let activate = toggle.accessibilityActivate() + accessibilityValue = toggle.accessibilityValue + return activate + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableToggleAllTextAndLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableToggleAllTextAndLinksModel.swift new file mode 100644 index 00000000..9fdc16ca --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/RightVariable/ListRightVariableToggleAllTextAndLinksModel.swift @@ -0,0 +1,58 @@ +// +// ListRightVariableToggleAllTextAndLinksModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 6/25/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListRightVariableToggleAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "listRVTgl" + public var toggle: ToggleModel + public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(toggle: ToggleModel, eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel) { + self.toggle = toggle + self.eyebrowHeadlineBodyLink = eyebrowHeadlineBodyLink + super.init() + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case moleculeName + case toggle + case eyebrowHeadlineBodyLink + } + + //-------------------------------------------------- + // MARK: - codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + toggle = try typeContainer.decode(ToggleModel.self, forKey: .toggle) + eyebrowHeadlineBodyLink = try typeContainer.decode(EyebrowHeadlineBodyLinkModel.self, forKey: .eyebrowHeadlineBodyLink) + try super.init(from: decoder) + } + + 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.encode(toggle, forKey: .toggle) + try container.encode(eyebrowHeadlineBodyLink, forKey: .eyebrowHeadlineBodyLink) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift index 15a83552..1b9ce0dc 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift @@ -20,6 +20,7 @@ import Foundation public var peakingUI: Bool? public var peakingArrowColor: Color? + public var analyticsData: JSONValueDictionary? //-------------------------------------------------- // MARK: - Keys @@ -28,6 +29,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case peakingUI case peakingArrowColor + case analyticsData } //-------------------------------------------------- @@ -38,6 +40,7 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI) peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor) + analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData) try super.init(from: decoder) } @@ -46,5 +49,6 @@ import Foundation var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(peakingUI, forKey: .peakingUI) try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor) + try container.encodeIfPresent(analyticsData, forKey: .analyticsData) } } diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index c0ee897c..d7d677fa 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -18,7 +18,7 @@ public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProt public var backgroundColor: Color? public var tintColor: Color public var line: LineModel? - public var alwaysShowBackButton = false + public var alwaysShowBackButton: Bool? public var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)? = NavigationImageButtonModel(with: "nav_back", action: ActionBackModel()) public var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? public var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? @@ -52,7 +52,7 @@ public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProt backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white) tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .standard) - alwaysShowBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowBackButton) ?? false + alwaysShowBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowBackButton) if let backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol) = try typeContainer.decodeModelIfPresent(codingKey: .backButton) { self.backButton = backButton } @@ -68,7 +68,7 @@ public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProt try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encode(tintColor, forKey: .tintColor) try container.encodeIfPresent(line, forKey: .line) - try container.encode(alwaysShowBackButton, forKey: .alwaysShowBackButton) + try container.encodeIfPresent(alwaysShowBackButton, forKey: .alwaysShowBackButton) try container.encodeModelIfPresent(backButton, forKey: .backButton) try container.encodeModelsIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons) try container.encodeModelsIfPresent(additionalRightButtons, forKey: .additionalRightButtons) diff --git a/MVMCoreUI/Atomic/Organisms/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel.swift index abc0e74b..808c370e 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel.swift @@ -297,6 +297,12 @@ open class Carousel: View { cell.accessibilityElementsHidden = true } } + + func trackSwipeActionAnalyticsforIndex(_ index : Int){ + guard let itemModel = molecules?[index], + let viewControllerObject = delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol else { return } + MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: viewControllerObject, actionInformation: itemModel.toJSON(), additionalData: nil) + } } extension Carousel: UICollectionViewDelegateFlowLayout { @@ -454,5 +460,7 @@ extension Carousel: UIScrollViewDelegate { // Cycle to other end if on buffer cell. pagingView?.currentIndex = pageIndex showPeaking(true) + // track analyticsData + trackSwipeActionAnalyticsforIndex(pageIndex) } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift index 198cf80d..c2ade02d 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/CarouselItemModelProtocol.swift @@ -10,4 +10,12 @@ import Foundation public protocol CarouselItemModelProtocol: ContainerModelProtocol { + var analyticsData: JSONValueDictionary? { get set } +} +public extension CarouselItemModelProtocol { + + var analyticsData: JSONValueDictionary? { + get { return nil } + set { analyticsData = newValue } + } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift index 30db2aa6..084509e0 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift @@ -14,7 +14,7 @@ public protocol NavigationItemModelProtocol { var backgroundColor: Color? { get set } var tintColor: Color { get set } var line: LineModel? { get set } - var alwaysShowBackButton: Bool { get set } + var alwaysShowBackButton: Bool? { get set } var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)? { get set } var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set } var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 12d70634..2803792f 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -47,13 +47,15 @@ import UIKit public static func setNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) { let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject var leftItems: [UIBarButtonItem] = [] - if let backButtonModel = navigationItemModel.backButton, - navigationController.viewControllers.count > 1 || navigationItemModel.alwaysShowBackButton { - leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) - } - if let leftItemModels = navigationItemModel.additionalLeftButtons { - for item in leftItemModels { - leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) + if navigationItemModel.alwaysShowBackButton != false { + if let backButtonModel = navigationItemModel.backButton, + navigationController.viewControllers.count > 1 || navigationItemModel.alwaysShowBackButton ?? false { + leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) + } + if let leftItemModels = navigationItemModel.additionalLeftButtons { + for item in leftItemModels { + leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) + } } } viewController.navigationItem.leftBarButtonItems = leftItems.count > 0 ? leftItems : nil diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index bfbe19ac..e62efa29 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -48,13 +48,15 @@ public extension MVMCoreUISplitViewController { let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject // Add back button first. - if let backButtonModel = navigationItemModel?.backButton { - if navigationController.viewControllers.count > 1 || navigationItemModel!.alwaysShowBackButton { - leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) + if navigationItemModel?.alwaysShowBackButton != false { + if let backButtonModel = navigationItemModel?.backButton { + if navigationController.viewControllers.count > 1 || navigationItemModel!.alwaysShowBackButton ?? false { + leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil)) + } + } else if let backButton = backButton, + navigationController.viewControllers.count > 1 { + leftItems.append(backButton) } - } else if let backButton = backButton, - navigationController.viewControllers.count > 1 { - leftItems.append(backButton) } // Add the panel button after the back button. diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index da55d597..74b907e3 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -9,7 +9,7 @@ // MARK: Accessibility "AccCloseButton" = "Close"; "swipe_to_select_with_action_hint" = "swipe up or down to select action, then double tap to select."; - +"AccDisabled" = "Disabled"; // MARK: Tab "AccTab" = ", tab"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings index 0a9eadb9..b3b6298c 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings @@ -8,6 +8,7 @@ // Accessibility "swipe_to_select_with_action_hint" = "deslízate hacia arriba o hacia abajo para seleccionar la acción, luego toca dos veces para seleccionar."; +"AccDisabled" = "desactivado"; "AccCloseButton" = "Cerrar"; // Tab diff --git a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings index bbc45f4a..8e0dbd02 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings @@ -8,6 +8,7 @@ // Accessibility "swipe_to_select_with_action_hint" = "deslízate hacia arriba o hacia abajo para seleccionar la acción, luego toca dos veces para seleccionar."; +"AccDisabled" = "desactivado"; "AccCloseButton" = "Cerrar"; // Tab