From ef56ed6cb3832a44bd0e5f71ab51db6549682474 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 18 Dec 2020 12:46:46 -0500 Subject: [PATCH 01/37] Margin and max header width --- .../Atomic/Molecules/HeadersAndFooters/Header.swift | 6 ++++++ .../HeadersAndFooters/MoleculeHeaderView.swift | 10 ++++++++++ MVMCoreUI/Styles/MFStyler.m | 8 ++++++-- MVMCoreUI/Styles/Padding.swift | 10 +++++++--- MVMCoreUI/Utility/Sizing/MFSizeObject.h | 1 + MVMCoreUI/Utility/Sizing/MFSizeObject.m | 2 ++ 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift index 63a13fbc..6c8e2c55 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift @@ -23,6 +23,12 @@ open class HeaderView: Container { addSubview(molecule) containerHelper.constrainView(molecule) self.molecule = molecule + guard let margins = molecule.superview?.layoutMarginsGuide else { return } + containerHelper.rightConstraint?.isActive = false + containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) + containerHelper.rightConstraint?.priority = .defaultHigh + containerHelper.rightConstraint?.isActive = true + molecule.widthAnchor.constraint(equalToConstant: 596).isActive = true } // MARK: - MVMCoreViewProtocol diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift index 291540af..2d4f84ff 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift @@ -24,6 +24,16 @@ public class MoleculeHeaderView: MoleculeContainer { // MARK: - MVMCoreViewProtocol //-------------------------------------------------- + public override func addMolecule(_ molecule: UIView) { + super.addMolecule(molecule) + guard let margins = molecule.superview?.layoutMarginsGuide else { return } + containerHelper.rightConstraint?.isActive = false + containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) + containerHelper.rightConstraint?.priority = .defaultHigh + containerHelper.rightConstraint?.isActive = true + molecule.widthAnchor.constraint(lessThanOrEqualToConstant: 596).isActive = true + } + open override func updateView(_ size: CGFloat) { super.updateView(size) line.updateView(size) diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index e8d58a26..e1ffe314 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -77,7 +77,9 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - Spacing Defaults + (CGFloat)defaultHorizontalPaddingForApplicationWidth { - return [[MFSizeObject sizeObjectWithScalingStandardSize:PaddingDefaultHorizontalSpacing] getValueBasedOnApplicationWidth]; + MFSizeObject *sizeObject = [MFSizeObject sizeObjectWithStandardSize:16]; + [sizeObject addLargerThanCustomSize:32 forThreshold:MFSizeMostlySweetSpotThreshold]; + return [sizeObject getValueBasedOnApplicationWidth]; } + (CGFloat)defaultVerticalPaddingForApplicationWidth { @@ -85,7 +87,9 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; } + (CGFloat)defaultHorizontalPaddingForSize:(CGFloat)size { - return [[MFSizeObject sizeObjectWithScalingStandardSize:PaddingDefaultHorizontalSpacing] getValueBasedOnSize:size]; + MFSizeObject *sizeObject = [MFSizeObject sizeObjectWithStandardSize:16]; + [sizeObject addLargerThanCustomSize:32 forThreshold:MFSizeMostlySweetSpotThreshold]; + return [sizeObject getValueBasedOnSize:size]; } + (CGFloat)defaultVerticalPaddingForSize:(CGFloat)size { diff --git a/MVMCoreUI/Styles/Padding.swift b/MVMCoreUI/Styles/Padding.swift index 0dd9ff6e..bc29882e 100644 --- a/MVMCoreUI/Styles/Padding.swift +++ b/MVMCoreUI/Styles/Padding.swift @@ -25,12 +25,14 @@ public struct Padding { public struct Component { public static let Standard: CGFloat = 24 - public static let HorizontalMarginSpacing: CGFloat = 32 + public static let HorizontalMarginSpacing: CGFloat = 16 public static let LargeVerticalMarginSpacing: CGFloat = 32 public static let VerticalMarginSpacing: CGFloat = 24 public static var horizontalPaddingForApplicationWidth: CGFloat { - return MFSizeObject(scalingStandardSize: HorizontalMarginSpacing)?.getValueBasedOnApplicationWidth() ?? HorizontalMarginSpacing + let sizeObject = MFSizeObject(standardSize: 16)! + sizeObject.addLargerThanCustomSize(32, forThreshold: MFSizeMostlySweetSpotThreshold) + return sizeObject.getValueBasedOnApplicationWidth() } public static var verticalPaddingForApplicationWidth: CGFloat { @@ -38,7 +40,9 @@ public struct Padding { } public static func horizontalPaddingForSize(_ size: CGFloat) -> CGFloat { - return MFSizeObject(scalingStandardSize: HorizontalMarginSpacing)?.getValueBased(onSize: size) ?? HorizontalMarginSpacing + let sizeObject = MFSizeObject(standardSize: 16)! + sizeObject.addLargerThanCustomSize(32, forThreshold: MFSizeMostlySweetSpotThreshold) + return sizeObject.getValueBased(onSize: size) } public static func verticalPaddingForSize(_ size: CGFloat) -> CGFloat { diff --git a/MVMCoreUI/Utility/Sizing/MFSizeObject.h b/MVMCoreUI/Utility/Sizing/MFSizeObject.h index 781feb4c..5c40dafe 100644 --- a/MVMCoreUI/Utility/Sizing/MFSizeObject.h +++ b/MVMCoreUI/Utility/Sizing/MFSizeObject.h @@ -17,6 +17,7 @@ extern CGFloat const MFSizeLargeiPhoneThreshold; extern CGFloat const MFSizeStandardiPadPortraitThreshold; extern CGFloat const MFSizeStandardiPadLandscapeThreshold; extern CGFloat const MFSizeiPadProLandscapeThreshold; +extern CGFloat const MFSizeMostlySweetSpotThreshold; @interface MFSizeObject : NSObject diff --git a/MVMCoreUI/Utility/Sizing/MFSizeObject.m b/MVMCoreUI/Utility/Sizing/MFSizeObject.m index 792e2d81..3379a1ce 100644 --- a/MVMCoreUI/Utility/Sizing/MFSizeObject.m +++ b/MVMCoreUI/Utility/Sizing/MFSizeObject.m @@ -18,6 +18,8 @@ CGFloat const MFSizeLargeiPhoneThreshold = 400; CGFloat const MFSizeStandardiPadPortraitThreshold = 600; CGFloat const MFSizeStandardiPadLandscapeThreshold = 1000; CGFloat const MFSizeiPadProLandscapeThreshold = 1300; +CGFloat const MFSizeMostlySweetSpotThreshold = 750; + @interface MFSizeObject () From ba6f52e18242c17b88469b66afcbd42a1351d0a0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 25 Mar 2021 10:53:08 -0400 Subject: [PATCH 02/37] update padding between primary buttons --- .../Molecules/HorizontalCombinationViews/TwoButtonView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 00b63ae4..13fcb279 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -51,7 +51,7 @@ import UIKit stack.addArrangedSubview(primaryButton) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) stack.axis = .horizontal - stack.spacing = 10 + stack.spacing = 12 equalWidthConstraint = secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1) equalWidthConstraint?.isActive = true } From 9cde90fdf408dd78823a9e46d675862a81ada9f4 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 25 Mar 2021 13:44:21 -0400 Subject: [PATCH 03/37] Gutter and margin fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +++ .../RadioButtonLabel.swift | 2 +- .../HorizontalCombinationViews/Tabs.swift | 10 +++--- .../TwoButtonView.swift | 2 +- MVMCoreUI/Atomic/Organisms/StackModel.swift | 10 +++--- .../NSLayoutConstraintExtension.swift | 2 +- .../Styles/MFStyler+PaddingExtension.swift | 36 +++++++++++++++++++ MVMCoreUI/Styles/MFStyler.m | 28 ++++++--------- MVMCoreUI/Styles/Padding.swift | 27 +++++++++----- 9 files changed, 84 insertions(+), 37 deletions(-) create mode 100644 MVMCoreUI/Styles/MFStyler+PaddingExtension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 9ba02cb8..fb0a0e32 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -346,6 +346,7 @@ 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 */; }; + D23A8FD9260CE004007E14CE /* MFStyler+PaddingExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FD5260CDF01007E14CE /* MFStyler+PaddingExtension.swift */; }; D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */; }; D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */; }; D23EA800247EBD6C00D60C34 /* LabelBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */; }; @@ -902,6 +903,7 @@ 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 = ""; }; + D23A8FD5260CDF01007E14CE /* MFStyler+PaddingExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFStyler+PaddingExtension.swift"; sourceTree = ""; }; D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemProtocol.swift; sourceTree = ""; }; D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationLabelButtonModel.swift; sourceTree = ""; }; D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelBarButtonItem.swift; sourceTree = ""; }; @@ -2000,6 +2002,7 @@ D29DF13921E68637003B2FB9 /* MFStyler.m */, 0A6682A92435125F00AD3CA1 /* Styler.swift */, 0A6682AB243531C300AD3CA1 /* Padding.swift */, + D23A8FD5260CDF01007E14CE /* MFStyler+PaddingExtension.swift */, ); path = Styles; sourceTree = ""; @@ -2843,6 +2846,7 @@ D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */, D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */, + D23A8FD9260CE004007E14CE /* MFStyler+PaddingExtension.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift index 918871e7..eb7266a9 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift @@ -32,7 +32,7 @@ import UIKit if let rightView = createRightView() { addSubview(rightView) - rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true + rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: Padding.Component.gutterForApplicationWidth).isActive = true rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true var constraint = rightView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 1ddd9412..b9225488 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -44,7 +44,7 @@ import UIKit //constant let TabCellId = "TabCell" - public let sectionPadding: CGFloat = 20.0 + public let sectionPadding: CGFloat = Padding.Component.gutterForApplicationWidth public let cellSpacing: CGFloat = 34.0 public let cellHeight: CGFloat = 27.0 public let selectionLineHeight: CGFloat = 4.0 @@ -198,11 +198,13 @@ extension Tabs: UICollectionViewDelegateFlowLayout { } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { - if !paddingBeforeFirstTab && section == 0 { - return .zero - } else { + guard section == 0 else { return UIEdgeInsets(top: 0, left: sectionPadding, bottom: 0, right: 0) } + guard paddingBeforeFirstTab else { + return .zero + } + return UIEdgeInsets(top: 0, left: Padding.Component.horizontalPaddingForApplicationWidth, bottom: 0, right: 0) } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift index 13fcb279..5f846730 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TwoButtonView.swift @@ -51,7 +51,7 @@ import UIKit stack.addArrangedSubview(primaryButton) NSLayoutConstraint.constraintPinSubview(toSuperview: stack) stack.axis = .horizontal - stack.spacing = 12 + stack.spacing = Padding.Component.gutterForApplicationWidth equalWidthConstraint = secondaryButton.widthAnchor.constraint(equalTo: primaryButton.widthAnchor, multiplier: 1) equalWidthConstraint?.isActive = true } diff --git a/MVMCoreUI/Atomic/Organisms/StackModel.swift b/MVMCoreUI/Atomic/Organisms/StackModel.swift index d96da035..dae6fad8 100644 --- a/MVMCoreUI/Atomic/Organisms/StackModel.swift +++ b/MVMCoreUI/Atomic/Organisms/StackModel.swift @@ -11,9 +11,7 @@ //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - static let defaultSpacing: CGFloat = 16.0 - + public class var identifier: String { return "stack" } @@ -21,7 +19,7 @@ public var backgroundColor: Color? public var molecules: [StackItemModelProtocol & MoleculeModelProtocol] public var axis: NSLayoutConstraint.Axis = .vertical - public var spacing: CGFloat = StackModel.defaultSpacing + public var spacing: CGFloat = Padding.Four public var useStackSpacingBeforeFirstItem = false //-------------------------------------------------- @@ -35,6 +33,8 @@ } if let spacing = spacing { self.spacing = spacing + } else if axis == .horizontal { + self.spacing = Padding.Component.gutterForApplicationWidth } super.init() } @@ -63,6 +63,8 @@ } if let spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) { self.spacing = spacing + } else if axis == .horizontal { + self.spacing = Padding.Component.gutterForApplicationWidth } backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) diff --git a/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift b/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift index 242e3fc0..43928769 100644 --- a/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift +++ b/MVMCoreUI/Categories/NSLayoutConstraintExtension.swift @@ -55,6 +55,6 @@ public extension NSLayoutConstraint { } leftView.leadingAnchor.constraint(equalTo: superView.layoutMarginsGuide.leadingAnchor).isActive = true superView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: rightView.trailingAnchor).isActive = true - rightView.leftAnchor.constraint(greaterThanOrEqualTo: leftView.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true + rightView.leftAnchor.constraint(greaterThanOrEqualTo: leftView.rightAnchor, constant: Padding.Component.gutterForApplicationWidth).isActive = true } } diff --git a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift new file mode 100644 index 00000000..d4bf8ebf --- /dev/null +++ b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift @@ -0,0 +1,36 @@ +// +// MFStyler+PaddingExtension.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/25/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objc public extension MFStyler { + + @objc static func bridgeGetGutterSizeForForApplicationWidth() -> CGFloat { + Padding.Component.gutterForApplicationWidth + } + + @objc static func bridgeGetGutterSize(for size: CGFloat) -> CGFloat { + Padding.Component.gutterFor(size: size) + } + + @objc static func bridgeHorizontalPaddingFor(size: CGFloat) -> CGFloat { + Padding.Component.horizontalPaddingForSize(size) + } + + @objc static func bridgeVerticalPaddingFor(size: CGFloat) -> CGFloat { + Padding.Component.verticalPaddingForSize(size) + } + + @objc static func bridgeSetDefaultMarginsFor(view: UIView, size: CGFloat, horizontal: Bool = true, vertical: Bool = false) { + Styler.setDefaultMarginsFor(view, size: size, horizontal: horizontal, vertical: vertical) + } + + @objc static func bridgeSetMarginsFor(view: UIView, size: CGFloat, horizontal: CGFloat, top: CGFloat, bottom: CGFloat) { + Styler.setMarginsFor(view, size: size, horizontal: horizontal, top: top, bottom: bottom) + } +} diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index e1ffe314..17b3e7f1 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -14,6 +14,7 @@ #import "MVMCoreUISplitViewController.h" @import MVMCore.MVMCoreDispatchUtility; #import +#import CGFloat const PaddingDefault = 24; CGFloat const PaddingDefaultHorizontalSpacing = 32; @@ -26,7 +27,7 @@ CGFloat const PaddingVerticalWhiteGrayView = 72; CGFloat const PaddingVerticalHeadlineAlternate = 48; CGFloat const PaddingPrimaryButtonTop = 36; -CGFloat const PaddingHorizontalBetweenRelatedItems = 16; +CGFloat const PaddingHorizontalBetweenRelatedItems = 12; CGFloat const PaddingOne = 6; CGFloat const PaddingTwo = 12; CGFloat const PaddingThree = 18; @@ -77,23 +78,19 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - Spacing Defaults + (CGFloat)defaultHorizontalPaddingForApplicationWidth { - MFSizeObject *sizeObject = [MFSizeObject sizeObjectWithStandardSize:16]; - [sizeObject addLargerThanCustomSize:32 forThreshold:MFSizeMostlySweetSpotThreshold]; - return [sizeObject getValueBasedOnApplicationWidth]; + return [self bridgeHorizontalPaddingForSize:[MVMCoreUISplitViewController getApplicationViewWidth]]; } + (CGFloat)defaultVerticalPaddingForApplicationWidth { - return [[MFSizeObject sizeObjectWithScalingStandardSize:PaddingDefaultVerticalSpacing] getValueBasedOnApplicationWidth]; + return [self bridgeVerticalPaddingForSize:[MVMCoreUISplitViewController getApplicationViewWidth]]; } + (CGFloat)defaultHorizontalPaddingForSize:(CGFloat)size { - MFSizeObject *sizeObject = [MFSizeObject sizeObjectWithStandardSize:16]; - [sizeObject addLargerThanCustomSize:32 forThreshold:MFSizeMostlySweetSpotThreshold]; - return [sizeObject getValueBasedOnSize:size]; + return [self bridgeHorizontalPaddingForSize:size]; } + (CGFloat)defaultVerticalPaddingForSize:(CGFloat)size { - return [[MFSizeObject sizeObjectWithScalingStandardSize:PaddingDefaultVerticalSpacing] getValueBasedOnSize:size]; + return [self bridgeVerticalPaddingForSize:size]; } + (void)setDefaultMarginsForView:(nullable UIView *)view size:(CGFloat)size { @@ -101,18 +98,13 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; } + (void)setDefaultMarginsForView:(nullable UIView *)view size:(CGFloat)size horizontal:(BOOL)horizontal vertical:(BOOL)vertical { - CGFloat horizontalPadding = horizontal ? [MFStyler defaultHorizontalPaddingForSize:size] : 0; - CGFloat verticalPadding = vertical ? PaddingDefaultVerticalSpacing3 : 0; - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [MVMCoreUIUtility setMarginsForView:view leading:horizontalPadding top:verticalPadding trailing:horizontalPadding bottom:verticalPadding]; - }]; + if (!view) { return; } + [self bridgeSetDefaultMarginsForView:view size:size horizontal:horizontal vertical:vertical]; } + (void)setMarginsForView:(nullable UIView *)view size:(CGFloat)size defaultHorizontal:(BOOL)horizontal top:(CGFloat)top bottom:(CGFloat)bottom { - CGFloat horizontalPadding = horizontal ? [MFStyler defaultHorizontalPaddingForSize:size] : 0; - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [MVMCoreUIUtility setMarginsForView:view leading:horizontalPadding top:top trailing:horizontalPadding bottom:bottom]; - }]; + if (!view) { return; } + [self bridgeSetMarginsForView:view size:size horizontal:horizontal top:top bottom:bottom]; } #pragma mark - 3.0 fonts diff --git a/MVMCoreUI/Styles/Padding.swift b/MVMCoreUI/Styles/Padding.swift index 83afe777..2b158739 100644 --- a/MVMCoreUI/Styles/Padding.swift +++ b/MVMCoreUI/Styles/Padding.swift @@ -24,27 +24,38 @@ public struct Padding { public struct Component { public static let Standard: CGFloat = 24 public static let HorizontalMarginSpacing: CGFloat = 16 - public static let LargeVerticalMarginSpacing: CGFloat = 32 + public static let LargeMarginSpacingLarge: CGFloat = 32 public static let VerticalMarginSpacing: CGFloat = 24 - + public static let LargeVerticalMarginSpacing: CGFloat = 32 + public static let HorizontalGutterSpacing: CGFloat = 12 + public static let LargeHorizontalGutterSpacing: CGFloat = 24 + public static var horizontalPaddingForApplicationWidth: CGFloat { - let sizeObject = MFSizeObject(standardSize: 16)! - sizeObject.addLargerThanCustomSize(32, forThreshold: MFSizeMostlySweetSpotThreshold) - return sizeObject.getValueBasedOnApplicationWidth() + horizontalPaddingForSize(MVMCoreUISplitViewController.getApplicationViewWidth()) } public static var verticalPaddingForApplicationWidth: CGFloat { - MFSizeObject(scalingStandardSize: VerticalMarginSpacing)?.getValueBasedOnApplicationWidth() ?? VerticalMarginSpacing + verticalPaddingForSize(MVMCoreUISplitViewController.getApplicationViewWidth()) + } + + public static var gutterForApplicationWidth: CGFloat { + gutterFor(size: MVMCoreUISplitViewController.getApplicationViewWidth()) } public static func horizontalPaddingForSize(_ size: CGFloat) -> CGFloat { - let sizeObject = MFSizeObject(standardSize: 16)! - sizeObject.addLargerThanCustomSize(32, forThreshold: MFSizeMostlySweetSpotThreshold) + let sizeObject = MFSizeObject(standardSize: HorizontalMarginSpacing)! + sizeObject.addLargerThanCustomSize(LargeMarginSpacingLarge, forThreshold: MFSizeMostlySweetSpotThreshold) return sizeObject.getValueBased(onSize: size) } public static func verticalPaddingForSize(_ size: CGFloat) -> CGFloat { MFSizeObject(scalingStandardSize: VerticalMarginSpacing)?.getValueBased(onSize: size) ?? VerticalMarginSpacing } + + public static func gutterFor(size: CGFloat) -> CGFloat { + let sizeObject = MFSizeObject(standardSize: HorizontalGutterSpacing)! + sizeObject.addLargerThanCustomSize(LargeHorizontalGutterSpacing, forThreshold: MFSizeMostlySweetSpotThreshold) + return sizeObject.getValueBased(onSize: size) + } } } From 9c8df31662f64390c19a8e91cdb7ea9da7e39a7a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 25 Mar 2021 14:00:05 -0400 Subject: [PATCH 04/37] Undo tabs and links changes --- .../Atomic/Molecules/HorizontalCombinationViews/Tabs.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index b9225488..f3ce24e5 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -44,7 +44,7 @@ import UIKit //constant let TabCellId = "TabCell" - public let sectionPadding: CGFloat = Padding.Component.gutterForApplicationWidth + public let sectionPadding: CGFloat = 20.0 public let cellSpacing: CGFloat = 34.0 public let cellHeight: CGFloat = 27.0 public let selectionLineHeight: CGFloat = 4.0 From dfdeecfd38c7e85f67da585bb40065e2998fb322 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 25 Mar 2021 14:00:23 -0400 Subject: [PATCH 05/37] iPad same margin as iOS --- MVMCoreUI/Styles/Padding.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Styles/Padding.swift b/MVMCoreUI/Styles/Padding.swift index 2b158739..5c53c39e 100644 --- a/MVMCoreUI/Styles/Padding.swift +++ b/MVMCoreUI/Styles/Padding.swift @@ -44,7 +44,6 @@ public struct Padding { public static func horizontalPaddingForSize(_ size: CGFloat) -> CGFloat { let sizeObject = MFSizeObject(standardSize: HorizontalMarginSpacing)! - sizeObject.addLargerThanCustomSize(LargeMarginSpacingLarge, forThreshold: MFSizeMostlySweetSpotThreshold) return sizeObject.getValueBased(onSize: size) } From c406e9b755e53b20ca6b09e7b46a2e223af9183b Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 25 Mar 2021 14:05:49 -0400 Subject: [PATCH 06/37] typo fix. Remove iPad gutter size --- MVMCoreUI/Styles/Padding.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/Styles/Padding.swift b/MVMCoreUI/Styles/Padding.swift index 5c53c39e..3bf81563 100644 --- a/MVMCoreUI/Styles/Padding.swift +++ b/MVMCoreUI/Styles/Padding.swift @@ -24,7 +24,7 @@ public struct Padding { public struct Component { public static let Standard: CGFloat = 24 public static let HorizontalMarginSpacing: CGFloat = 16 - public static let LargeMarginSpacingLarge: CGFloat = 32 + public static let LargeHorizontalMarginSpacing: CGFloat = 32 public static let VerticalMarginSpacing: CGFloat = 24 public static let LargeVerticalMarginSpacing: CGFloat = 32 public static let HorizontalGutterSpacing: CGFloat = 12 @@ -53,7 +53,6 @@ public struct Padding { public static func gutterFor(size: CGFloat) -> CGFloat { let sizeObject = MFSizeObject(standardSize: HorizontalGutterSpacing)! - sizeObject.addLargerThanCustomSize(LargeHorizontalGutterSpacing, forThreshold: MFSizeMostlySweetSpotThreshold) return sizeObject.getValueBased(onSize: size) } } From b4cfca0cb255c9732cdb097e011a5b9b7bd85aae Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Thu, 25 Mar 2021 15:55:31 -0400 Subject: [PATCH 07/37] fix bridge mismatch --- MVMCoreUI/Styles/MFStyler+PaddingExtension.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift index d4bf8ebf..a38dd3d7 100644 --- a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift +++ b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift @@ -30,7 +30,7 @@ import Foundation Styler.setDefaultMarginsFor(view, size: size, horizontal: horizontal, vertical: vertical) } - @objc static func bridgeSetMarginsFor(view: UIView, size: CGFloat, horizontal: CGFloat, top: CGFloat, bottom: CGFloat) { - Styler.setMarginsFor(view, size: size, horizontal: horizontal, top: top, bottom: bottom) + @objc static func bridgeSetMarginsFor(view: UIView, size: CGFloat, horizontal: Bool, top: CGFloat, bottom: CGFloat) { + Styler.setMarginsFor(view, size: size, horizontal: horizontal ? nil : 0, top: top, bottom: bottom) } } From 2e75f8638c4b4cc4f0111e49944f6f68d8f8b8ab Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 29 Mar 2021 18:44:26 -0400 Subject: [PATCH 08/37] iterate throw all rules --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 7 ++++- .../Rules/Rules/RuleAnyRequiredModel.swift | 20 +++++++++----- .../Rules/RuleAnyValueChangedModel.swift | 16 ++++++++--- .../Rules/RuleEqualsIgnoreCaseModel.swift | 19 +++++++++---- .../Rules/Rules/RuleEqualsModel.swift | 17 ++++++++---- .../Rules/Rules/RulesProtocol.swift | 27 ++++++++++++------- 6 files changed, 75 insertions(+), 31 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index a0785c41..090202c0 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -96,8 +96,13 @@ import MVMCore public func validateGroup(_ group: FormGroupRule) -> Bool { // Validate each rule. var valid = true + var previousValidity: [String: Bool] = [:] for rule in group.rules { - valid = valid && rule.validate(fields) + let tuple = rule.validate(fields, previousValidity) + let temp = tuple.0 + let returnedValidity = tuple.1 + previousValidity = previousValidity.merging(returnedValidity) { (_, new) in new } + valid = valid && temp } // Notify the group watchers of validity. diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 7f153e83..2addbf90 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -36,15 +36,23 @@ public class RuleAnyRequiredModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } - - if isValid(formField) { - return true + + var fieldValidity = isValid(formField) + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false } + + if fieldValidity { + return (fieldValidity, previousValidity) + } + previousValidity[formKey] = false } - return false + return (false, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index 07cf451f..d7413419 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -27,13 +27,21 @@ public class RuleAnyValueChangedModel: RulesProtocol { return formField.baseValue != formField.formFieldValue() } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } - if isValid(formField) { - return true + var fieldValidity = isValid(formField) + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false } + + if fieldValidity { + return (true, previousValidity) + } + previousValidity[formKey] = false } - return false + return (false, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift index 5e014cff..4979adf2 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -27,10 +27,11 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = false - var compareText: String? + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var valid = false + var compareText: String? + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } @@ -42,16 +43,24 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { if let fieldValue = formField.formFieldValue() as? String, compareString.caseInsensitiveCompare(fieldValue) == .orderedSame { valid = true + + var fieldValidity = valid + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false + } + for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } (formField as? FormRuleWatcherFieldProtocol)?.setValidity(true, rule: self) } break } - + + previousValidity[formKey] = valid (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) } - return valid + return (valid, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index fa73ed51..7795ab39 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -27,9 +27,10 @@ public class RuleEqualsModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = true - var compareValue: AnyHashable? + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var valid = true + var compareValue: AnyHashable? + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } @@ -41,13 +42,19 @@ public class RuleEqualsModel: RulesProtocol { if compareValue != formField.formFieldValue() { valid = false + previousValidity[formKey] = valid (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) break } else { - (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) + var fieldValidity = valid + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false + } + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) } } - return valid + return (valid, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index 5a8b47a8..c48fd111 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -26,7 +26,7 @@ public protocol RulesProtocol: ModelProtocol { func isValid(_ formField: FormFieldProtocol) -> Bool // Validates the rule and returns the result. - func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) } public extension RulesProtocol { @@ -38,14 +38,21 @@ public extension RulesProtocol { static var categoryName: String { "\(RulesProtocol.self)" } // Individual rule can override the function to validate based on the rule type. - func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = true - for formKey in fields { - guard let formField = fieldMolecules[formKey] else { continue } - let fieldValidity = isValid(formField) - (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) - valid = valid && fieldValidity - } - return valid + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var valid = true + var previousValidity: [String: Bool] = [:] + for formKey in fields { + guard let formField = fieldMolecules[formKey] else { continue } + + var fieldValidity = isValid(formField) + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false + } + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) + valid = valid && fieldValidity + previousValidity[formKey] = fieldValidity + } + return (valid, previousValidity) } } From 766ba93499ab32b848f2e62852ce37cdc0d0b1ba Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 30 Mar 2021 12:12:12 -0400 Subject: [PATCH 09/37] code review --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 6 +++--- .../Rules/Rules/RuleAnyRequiredModel.swift | 6 +++--- .../Rules/Rules/RuleAnyValueChangedModel.swift | 8 ++++---- .../Rules/Rules/RuleEqualsIgnoreCaseModel.swift | 7 +++---- .../FormUIHelpers/Rules/Rules/RuleEqualsModel.swift | 7 +++---- .../FormUIHelpers/Rules/Rules/RulesProtocol.swift | 12 ++++++------ 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 090202c0..bed97391 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -99,10 +99,10 @@ import MVMCore var previousValidity: [String: Bool] = [:] for rule in group.rules { let tuple = rule.validate(fields, previousValidity) - let temp = tuple.0 - let returnedValidity = tuple.1 + let isValidRule = tuple.valid + let returnedValidity = tuple.fieldValidity previousValidity = previousValidity.merging(returnedValidity) { (_, new) in new } - valid = valid && temp + valid = valid && isValidRule } // Notify the group watchers of validity. diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 2addbf90..0df84c4a 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -36,7 +36,7 @@ public class RuleAnyRequiredModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var previousValidity: [String: Bool] = [:] for formKey in fields { @@ -44,7 +44,7 @@ public class RuleAnyRequiredModel: RulesProtocol { var fieldValidity = isValid(formField) // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } @@ -53,6 +53,6 @@ public class RuleAnyRequiredModel: RulesProtocol { } previousValidity[formKey] = false } - return (false, previousValidity) + return (valid: false, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index d7413419..2a982e45 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -27,13 +27,13 @@ public class RuleAnyValueChangedModel: RulesProtocol { return formField.baseValue != formField.formFieldValue() } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } var fieldValidity = isValid(formField) // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } @@ -41,7 +41,7 @@ public class RuleAnyValueChangedModel: RulesProtocol { return (true, previousValidity) } previousValidity[formKey] = false - } - return (false, previousValidity) + } + return (valid: false, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift index 4979adf2..ee165b9a 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -27,7 +27,7 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var valid = false var compareText: String? @@ -46,7 +46,7 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { var fieldValidity = valid // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } @@ -60,7 +60,6 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { previousValidity[formKey] = valid (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) } - - return (valid, previousValidity) + return (valid: valid, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index 7795ab39..7a8c25e4 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -27,7 +27,7 @@ public class RuleEqualsModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var valid = true var compareValue: AnyHashable? var previousValidity: [String: Bool] = [:] @@ -48,13 +48,12 @@ public class RuleEqualsModel: RulesProtocol { } else { var fieldValidity = valid // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) } } - - return (valid, previousValidity) + return (valid: valid, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index c48fd111..db8614ac 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -26,7 +26,7 @@ public protocol RulesProtocol: ModelProtocol { func isValid(_ formField: FormFieldProtocol) -> Bool // Validates the rule and returns the result. - func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) } public extension RulesProtocol { @@ -38,21 +38,21 @@ public extension RulesProtocol { static var categoryName: String { "\(RulesProtocol.self)" } // Individual rule can override the function to validate based on the rule type. - func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var valid = true var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } - var fieldValidity = isValid(formField) - // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + var fieldValidity = isValid(formField) + // If past rule is invalid for a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) valid = valid && fieldValidity previousValidity[formKey] = fieldValidity } - return (valid, previousValidity) + return (valid: valid, fieldValidity: previousValidity) } } From 9eb28ff675029a566b1149c28397b67a554cebc2 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 30 Mar 2021 16:36:08 -0400 Subject: [PATCH 10/37] top alert margins --- .../CollapsableNotificationModel.swift | 4 ++-- .../Molecules/TopNotification/Notification.swift | 10 ++-------- .../TopNotification/NotificationModel.swift | 14 ++++++++++---- MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m | 10 ++++++---- .../MVMCoreUICommonViewsUtility+Extension.swift | 4 ++-- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift index 17b1aef7..bdcd3fe1 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift @@ -24,8 +24,8 @@ open class CollapsableNotificationModel: NotificationModel { super.init(with: headline) } - open override func setDefault() { - super.setDefault() + open override func setDefaults() { + super.setDefaults() if topLabel.textColor == nil { topLabel.textColor = Color(uiColor: .white) } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift index 09edbbcc..c17f43e0 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift @@ -8,7 +8,7 @@ import Foundation -@objcMembers open class NotificationView: View { +@objcMembers open class NotificationView: Container { //-------------------------------------------------- // MARK: - Outlets //-------------------------------------------------- @@ -43,19 +43,13 @@ import Foundation labelStack = Stack.createStack(with: [headline, body], spacing: 0) horizontalStack = Stack.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) + addAndContain(horizontalStack) labelStack.restack() horizontalStack.restack() heightAnchor.constraint(equalToConstant: Self.viewHeight).isActive = true } - open override func updateView(_ size: CGFloat) { - super.updateView(size) - horizontalStack.updateView(size) - } - open override func reset() { super.reset() backgroundColor = .mvmGreen() diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift index 3d02cecd..1e77e61d 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift @@ -7,7 +7,7 @@ // -open class NotificationModel: MoleculeModelProtocol { +open class NotificationModel: ContainerModel, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -26,13 +26,19 @@ open class NotificationModel: MoleculeModelProtocol { public init(with headline: LabelModel) { self.headline = headline + super.init() } //-------------------------------------------------- // MARK: - Default //-------------------------------------------------- - open func setDefault() { + open override func setDefaults() { + useHorizontalMargins = true + useVerticalMargins = true + topPadding = PaddingTwo + bottomPadding = PaddingTwo + if backgroundColor == nil { backgroundColor = Color(uiColor: .mvmGreen) } @@ -76,10 +82,10 @@ open class NotificationModel: MoleculeModelProtocol { 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() + super.init() } - open func encode(to encoder: Encoder) throws { + open override 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) diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m index 44f248f3..fa96630f 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertMainView.m @@ -164,18 +164,19 @@ [self.iconView removeFromSuperview]; } + CGFloat horizontalPadding = [MFStyler defaultHorizontalPaddingForApplicationWidth]; if (imageURL) { LoadImageView *imageView = [[LoadImageView alloc] init]; imageView.translatesAutoresizingMaskIntoConstraints = NO; [imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; [self addSubview:imageView]; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=space-[imageView]->=space-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingFive)} views:NSDictionaryOfVariableBindings(imageView)]]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-space-[imageView]-space-[centerView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingThree)} views:NSDictionaryOfVariableBindings(imageView,centerView)]]; + [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-space-[imageView]-space-[centerView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(horizontalPadding)} views:NSDictionaryOfVariableBindings(imageView,centerView)]]; [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES; self.iconView = imageView; [imageView loadImageWithName:imageURL width:@(32)]; } else { - [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:PaddingThree].active = YES; + [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:horizontalPadding].active = YES; } } @@ -193,6 +194,7 @@ - (void)setupWithButton:(BOOL)showButton { // Setup the button. + CGFloat horizontalPadding = [MFStyler defaultHorizontalPaddingForApplicationWidth]; if (showButton) { if (!self.button) { @@ -210,7 +212,7 @@ [self addSubview:button]; [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES; [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:PaddingThree].active = YES; - [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)].active = YES; + [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : horizontalPadding)].active = YES; self.button = button; } } else { @@ -222,7 +224,7 @@ } if (!self.labelRightConstraint) { - self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : PaddingFive)]; + self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : horizontalPadding)]; } self.labelRightConstraint.active = YES; } diff --git a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift index d1173250..60e57d75 100644 --- a/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift +++ b/MVMCoreUI/Utility/MVMCoreUICommonViewsUtility+Extension.swift @@ -23,11 +23,11 @@ public extension MVMCoreUICommonViewsUtility { view.addSubview(button) var constraints: [NSLayoutConstraint] = [] if centeredVertically { - constraints.append(view.rightAnchor.constraint(equalTo: button.rightAnchor, constant: PaddingTwo)) + constraints.append(view.rightAnchor.constraint(equalTo: button.rightAnchor, constant: Padding.Component.horizontalPaddingForApplicationWidth)) constraints.append(view.centerYAnchor.constraint(equalTo: button.centerYAnchor)) } else { constraints.append(button.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: PaddingOne)) - constraints.append(view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: button.rightAnchor, constant: PaddingTwo)) + constraints.append(view.safeAreaLayoutGuide.rightAnchor.constraint(equalTo: button.rightAnchor, constant: Padding.Component.horizontalPaddingForApplicationWidth)) } NSLayoutConstraint.activate(constraints) return button From 758ccff930f7c1a6b93d5dda848a8159bde0cef8 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 5 Apr 2021 10:57:04 -0400 Subject: [PATCH 11/37] loading spinner bounds fix --- MVMCoreUI/BaseControllers/MFLoadingViewController.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/BaseControllers/MFLoadingViewController.m b/MVMCoreUI/BaseControllers/MFLoadingViewController.m index aad2383e..56ad6d3b 100644 --- a/MVMCoreUI/BaseControllers/MFLoadingViewController.m +++ b/MVMCoreUI/BaseControllers/MFLoadingViewController.m @@ -34,8 +34,7 @@ [view addSubview:activityIndicatorView]; self.activityIndicator = activityIndicatorView; self.activityIndicator.accessibilityIdentifier = @"Loader"; - - [NSLayoutConstraint constraintPinView:activityIndicatorView heightConstraint:YES heightConstant:PaddingSix widthConstraint:YES widthConstant:PaddingSix]; + [activityIndicatorView pinWidthAndHeight]; // Sets the constraints for the activityIndicatorView [NSLayoutConstraint constraintPinSubview:activityIndicatorView pinCenterX:YES pinCenterY:YES]; From f29878e1748f274d980f7dbdb28d3811fb335f27 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 6 Apr 2021 16:54:36 -0400 Subject: [PATCH 12/37] button width to column changes --- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 12 ++++++++---- MVMCoreUI/Styles/MFStyler+PaddingExtension.swift | 8 ++++++++ MVMCoreUI/Styles/Padding.swift | 4 ++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index 8eefe1d7..1bdf0234 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -168,10 +168,14 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { } open override var intrinsicContentSize: CGSize { - - let size = super.intrinsicContentSize - let width = size.width + (2 * getInnerPadding()) - return CGSize(width: max(width, getMinimumWidth()), height: getHeight()) + if buttonSize == .tiny { + let size = super.intrinsicContentSize + let width = size.width + (2 * getInnerPadding()) + return CGSize(width: max(width, getMinimumWidth()), height: getHeight()) + } else { + let width = Padding.Component.gutterForApplicationWidth + (2.0 * Padding.Component.columnFor(size: MVMCoreUISplitViewController.getApplicationViewWidth())) + return CGSize(width: min(292, width), height: getHeight()) + } } //-------------------------------------------------- diff --git a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift index a38dd3d7..37fa4a9f 100644 --- a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift +++ b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift @@ -18,6 +18,14 @@ import Foundation Padding.Component.gutterFor(size: size) } + @objc static func bridgeGetColumnSizeForForApplicationWidth() -> CGFloat { + Padding.Component.columnFor(size: MVMCoreUISplitViewController.getApplicationViewWidth()) + } + + @objc static func bridgeGetColumnSize(for size: CGFloat) -> CGFloat { + Padding.Component.columnFor(size: size) + } + @objc static func bridgeHorizontalPaddingFor(size: CGFloat) -> CGFloat { Padding.Component.horizontalPaddingForSize(size) } diff --git a/MVMCoreUI/Styles/Padding.swift b/MVMCoreUI/Styles/Padding.swift index 3bf81563..f7e5b407 100644 --- a/MVMCoreUI/Styles/Padding.swift +++ b/MVMCoreUI/Styles/Padding.swift @@ -55,5 +55,9 @@ public struct Padding { let sizeObject = MFSizeObject(standardSize: HorizontalGutterSpacing)! return sizeObject.getValueBased(onSize: size) } + + public static func columnFor(size: CGFloat) -> CGFloat { + return (size - (3.0 * gutterFor(size: size)) - (2.0 * horizontalPaddingForSize(size))) / 4.0 + } } } From dfa40752ea59ee78cf22e6134f56155ffeddfd0f Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 7 Apr 2021 11:14:10 -0400 Subject: [PATCH 13/37] radio box gutter --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift index 4a596a35..e8f940a2 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift @@ -14,7 +14,7 @@ open class RadioBoxes: View { public var collectionViewHeight: NSLayoutConstraint! private let boxWidth: CGFloat = 151.0 private let boxHeight: CGFloat = 64.0 - private let itemSpacing: CGFloat = 8.0 + private var itemSpacing: CGFloat = 12.0 private var numberOfColumns: CGFloat = 2.0 private var radioBoxesModel: RadioBoxesModel? { return model as? RadioBoxesModel @@ -71,6 +71,7 @@ open class RadioBoxes: View { @objc override open func updateView(_ size: CGFloat) { super.updateView(size) self.size = size + itemSpacing = Padding.Component.gutterFor(size: size) collectionView.updateView(size) } From 45afb5525882fb0ac3a9af41b7c2186d33d5b1d1 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 7 Apr 2021 11:38:23 -0400 Subject: [PATCH 14/37] two column margin --- .../List/TwoColumn/ListTwoColumnCompareChanges.swift | 3 +-- .../List/TwoColumn/ListTwoColumnDropdownSelectors.swift | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift index 9f7895af..42284af9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnCompareChanges.swift @@ -20,7 +20,6 @@ //------------------------------------------------------ let containingStack: Stack - let stackSpacing: CGFloat = 5.0 //------------------------------------------------------ // MARK: - Initializers @@ -31,7 +30,7 @@ (view: rightHeadlineBodyLink, model: StackItemModel(percent: 50, verticalAlignment: .leading))], axis: .horizontal) - containingStack = Stack.createStack(with: [stackHeadline1], spacing: 0) + containingStack = Stack.createStack(with: [stackHeadline1], spacing: Padding.Component.gutterForApplicationWidth) super.init(style: style, reuseIdentifier: reuseIdentifier) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift index eb8fb0ea..93350a63 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/TwoColumn/ListTwoColumnDropdownSelectors.swift @@ -23,7 +23,7 @@ public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { stack = Stack.createStack(with: [(view: leftDropDown, model: StackItemModel(percent: 50, horizontalAlignment: .fill)), (view: rightDropDown, model: StackItemModel(percent: 50, horizontalAlignment: .fill))], - axis: .horizontal, spacing: 9) + axis: .horizontal, spacing: Padding.Component.gutterForApplicationWidth) super.init(style: style, reuseIdentifier: reuseIdentifier) } From a50e3346e7220099d456dd34da8e62be8ef06038 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 8 Apr 2021 15:34:21 -0400 Subject: [PATCH 15/37] code review --- MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift | 2 +- .../FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift | 2 +- MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 0df84c4a..3a9b3871 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -43,7 +43,7 @@ public class RuleAnyRequiredModel: RulesProtocol { guard let formField = fieldMolecules[formKey] else { continue } var fieldValidity = isValid(formField) - // If past rule is invalid forr a field, the current rule should not flip the validity of a field + // If past rule is invalid for a field, the current rule should not flip the validity of a field if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift index ee165b9a..8326cf4f 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -45,7 +45,7 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { valid = true var fieldValidity = valid - // If past rule is invalid forr a field, the current rule should not flip the validity of a field + // If past rule is invalid for a field, the current rule should not flip the validity of a field if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index 7a8c25e4..a405e2e7 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -47,7 +47,7 @@ public class RuleEqualsModel: RulesProtocol { break } else { var fieldValidity = valid - // If past rule is invalid forr a field, the current rule should not flip the validity of a field + // If past rule is invalid for a field, the current rule should not flip the validity of a field if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } From d3fb26f00551759c1e557e7877c2e613266c1ecf Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 12 Apr 2021 14:34:15 -0400 Subject: [PATCH 16/37] review fixes --- MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift | 2 +- .../Molecules/HeadersAndFooters/MoleculeHeaderView.swift | 2 +- MVMCoreUI/Styles/MFStyler+PaddingExtension.swift | 4 ++-- MVMCoreUI/Styles/MFStyler.h | 2 ++ MVMCoreUI/Styles/MFStyler.m | 3 +++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift index ff9a6766..f02586e5 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift @@ -27,7 +27,7 @@ open class HeaderView: Container { containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) containerHelper.rightConstraint?.priority = .defaultHigh containerHelper.rightConstraint?.isActive = true - molecule.widthAnchor.constraint(equalToConstant: 596).isActive = true + molecule.widthAnchor.constraint(equalToConstant: HeaderMaxWidth).isActive = true } // MARK: - MVMCoreViewProtocol diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift index 1bbb78f9..5f3a0914 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift @@ -31,7 +31,7 @@ public class MoleculeHeaderView: MoleculeContainer { containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) containerHelper.rightConstraint?.priority = .defaultHigh containerHelper.rightConstraint?.isActive = true - molecule.widthAnchor.constraint(lessThanOrEqualToConstant: 596).isActive = true + molecule.widthAnchor.constraint(lessThanOrEqualToConstant: HeaderMaxWidth).isActive = true } open override func updateView(_ size: CGFloat) { diff --git a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift index 37fa4a9f..bb96af26 100644 --- a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift +++ b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift @@ -10,7 +10,7 @@ import Foundation @objc public extension MFStyler { - @objc static func bridgeGetGutterSizeForForApplicationWidth() -> CGFloat { + @objc static func bridgeGetGutterSizeForApplicationWidth() -> CGFloat { Padding.Component.gutterForApplicationWidth } @@ -18,7 +18,7 @@ import Foundation Padding.Component.gutterFor(size: size) } - @objc static func bridgeGetColumnSizeForForApplicationWidth() -> CGFloat { + @objc static func bridgeGetColumnSizeForApplicationWidth() -> CGFloat { Padding.Component.columnFor(size: MVMCoreUISplitViewController.getApplicationViewWidth()) } diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index a3827044..d8676016 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -57,6 +57,8 @@ extern CGFloat const HeightTableSeperatorHeight; extern CGFloat const MFHeightForSwitch; extern CGFloat const MFMFWidthForSwitch; +extern CGFloat const HeaderMaxWidth; + // Color constants extern CGFloat const DisableOppacity; extern CGFloat const PaymentMethodViewHeightWidthMultiplier; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 17b3e7f1..8b9db95f 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -46,6 +46,9 @@ CGFloat const HeightTableSeperatorHeight = 1; CGFloat const MFHeightForSwitch = 22; CGFloat const MFWidthForSwitch = 42; + +CGFloat const HeaderMaxWidth = 596; + CGFloat const DisableOppacity = 0.5; CGFloat const PaymentMethodViewHeightWidthMultiplier = 0.55; CGFloat const MinCellHeight = 96; From 7e4c8d709ff436b527d5bf122598e0b74c1c4d55 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 13 Apr 2021 13:42:36 -0400 Subject: [PATCH 17/37] review changes --- MVMCoreUI/Styles/MFStyler+PaddingExtension.swift | 8 ++++---- MVMCoreUI/Styles/MFStyler.m | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift index bb96af26..6da298e2 100644 --- a/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift +++ b/MVMCoreUI/Styles/MFStyler+PaddingExtension.swift @@ -26,19 +26,19 @@ import Foundation Padding.Component.columnFor(size: size) } - @objc static func bridgeHorizontalPaddingFor(size: CGFloat) -> CGFloat { + @objc static func bridgeHorizontalPadding(for size: CGFloat) -> CGFloat { Padding.Component.horizontalPaddingForSize(size) } - @objc static func bridgeVerticalPaddingFor(size: CGFloat) -> CGFloat { + @objc static func bridgeVerticalPadding(for size: CGFloat) -> CGFloat { Padding.Component.verticalPaddingForSize(size) } - @objc static func bridgeSetDefaultMarginsFor(view: UIView, size: CGFloat, horizontal: Bool = true, vertical: Bool = false) { + @objc static func bridgeSetDefaultMargins(for view: UIView, size: CGFloat, horizontal: Bool = true, vertical: Bool = false) { Styler.setDefaultMarginsFor(view, size: size, horizontal: horizontal, vertical: vertical) } - @objc static func bridgeSetMarginsFor(view: UIView, size: CGFloat, horizontal: Bool, top: CGFloat, bottom: CGFloat) { + @objc static func bridgeSetMargins(for view: UIView, size: CGFloat, horizontal: Bool, top: CGFloat, bottom: CGFloat) { Styler.setMarginsFor(view, size: size, horizontal: horizontal ? nil : 0, top: top, bottom: bottom) } } diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 8b9db95f..48ca21a8 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -81,19 +81,19 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; #pragma mark - Spacing Defaults + (CGFloat)defaultHorizontalPaddingForApplicationWidth { - return [self bridgeHorizontalPaddingForSize:[MVMCoreUISplitViewController getApplicationViewWidth]]; + return [self bridgeHorizontalPaddingFor:[MVMCoreUISplitViewController getApplicationViewWidth]]; } + (CGFloat)defaultVerticalPaddingForApplicationWidth { - return [self bridgeVerticalPaddingForSize:[MVMCoreUISplitViewController getApplicationViewWidth]]; + return [self bridgeVerticalPaddingFor:[MVMCoreUISplitViewController getApplicationViewWidth]]; } + (CGFloat)defaultHorizontalPaddingForSize:(CGFloat)size { - return [self bridgeHorizontalPaddingForSize:size]; + return [self bridgeHorizontalPaddingFor:size]; } + (CGFloat)defaultVerticalPaddingForSize:(CGFloat)size { - return [self bridgeVerticalPaddingForSize:size]; + return [self bridgeVerticalPaddingFor:size]; } + (void)setDefaultMarginsForView:(nullable UIView *)view size:(CGFloat)size { @@ -102,12 +102,12 @@ CGFloat const LabelWithInternalButtonLineSpace = 2; + (void)setDefaultMarginsForView:(nullable UIView *)view size:(CGFloat)size horizontal:(BOOL)horizontal vertical:(BOOL)vertical { if (!view) { return; } - [self bridgeSetDefaultMarginsForView:view size:size horizontal:horizontal vertical:vertical]; + [self bridgeSetDefaultMarginsFor:view size:size horizontal:horizontal vertical:vertical]; } + (void)setMarginsForView:(nullable UIView *)view size:(CGFloat)size defaultHorizontal:(BOOL)horizontal top:(CGFloat)top bottom:(CGFloat)bottom { if (!view) { return; } - [self bridgeSetMarginsForView:view size:size horizontal:horizontal top:top bottom:bottom]; + [self bridgeSetMarginsFor:view size:size horizontal:horizontal top:top bottom:bottom]; } #pragma mark - 3.0 fonts From 2204e2fd777935748d068d4b382ce85a8f996d55 Mon Sep 17 00:00:00 2001 From: Damodaram Date: Thu, 22 Apr 2021 19:27:54 +0530 Subject: [PATCH 18/37] swap contact name changes --- ...eIconWithRightCaretAllTextLinksModel.swift | 7 +++- .../BaseControllers/ViewController.swift | 2 +- MVMCoreUI/Behaviors/GetContactBehavior.swift | 33 ++++++++++++------- .../Protocols/PageBehaviorProtocol.swift | 6 ++++ 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift index 9d9291e8..3f48a2d6 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift @@ -6,7 +6,8 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -public class ListLeftVariableIconWithRightCaretAllTextLinksModel: ListItemModel, MoleculeModelProtocol { +public class ListLeftVariableIconWithRightCaretAllTextLinksModel: ListItemModel, ParentMoleculeModelProtocol { + //----------------------------------------------------- // MARK: - Properties //----------------------------------------------------- @@ -16,6 +17,10 @@ public class ListLeftVariableIconWithRightCaretAllTextLinksModel: ListItemModel, public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel public var rightLabel: LabelModel + public var children: [MoleculeModelProtocol] { + return [image, eyebrowHeadlineBodyLink,rightLabel] + } + //----------------------------------------------------- // MARK: - Methods //----------------------------------------------------- diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 293bd49f..20ba4a66 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -653,7 +653,7 @@ import UIKit // MARK: - Behavior Execution //-------------------------------------------------- - func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { + public func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } } } diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index 2c6205f2..6ea969ac 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -21,7 +21,8 @@ public class PageGetContactBehaviorModel: PageBehaviorModelProtocol { public init() {} } -public class PageGetContactBehavior: PageVisibilityBehavior { +public class PageGetContactBehavior: PageVisibilityBehavior,PageNextBatchActionBehavior { + var delegate: MVMCoreUIDelegateObject? public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { @@ -32,24 +33,34 @@ public class PageGetContactBehavior: PageVisibilityBehavior { // Ask for permission CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in guard access, - error == nil, - let rootMolecules = self?.delegate?.moleculeDelegate?.getRootMolecules() else { return } + error == nil else { return } // Iterate models and provide contact - let store = CNContactStore() - let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() - for consumer in consumers { - guard let parameters = consumer.getMatchParameters(), - let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } - consumer.consume(contacts: contacts) - } + self?.getContacts() // Tell template to update MVMCoreDispatchUtility.performBlock(onMainThread: { // TODO: move to protocol function instead - (self?.delegate?.moleculeDelegate as? ViewController)?.handleNewData() + (self?.delegate?.moleculeDelegate as? ViewController)?.handleNewDataAndUpdateUI() }) } } + func getContacts() { + guard let rootMolecules = self.delegate?.moleculeDelegate?.getRootMolecules() else { return } + let store = CNContactStore() + let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() + for consumer in consumers { + guard let parameters = consumer.getMatchParameters(), + let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } + consumer.consume(contacts: contacts) + } + } + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {} + + public func nextBatchAction(_ delegateObject: MVMCoreUIDelegateObject?) { + if CNContactStore.authorizationStatus(for: .contacts) == .authorized { + getContacts() + } + } } diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift index e7db54bc..87df7007 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift @@ -39,6 +39,12 @@ public protocol PageLocalDataShareBehavior: PageBehaviorProtocol { func receiveLocalPageData(_ data:[AnyHashable: Any], _ delegateObject: MVMCoreUIDelegateObject) } +public protocol PageNextBatchActionBehavior: PageBehaviorProtocol { + + func nextBatchAction(_ delegateObject: MVMCoreUIDelegateObject?) + +} + public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol { func handleAction(type actionType: String?, information: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) -> Bool From f583a06725f5f6eb8060c4e15dec035ad0a66789 Mon Sep 17 00:00:00 2001 From: Damodaram Date: Thu, 22 Apr 2021 20:01:37 +0530 Subject: [PATCH 19/37] review changes --- MVMCoreUI/Behaviors/GetContactBehavior.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index 6ea969ac..eaf3d5d9 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -46,7 +46,7 @@ public class PageGetContactBehavior: PageVisibilityBehavior,PageNextBatchActionB } func getContacts() { - guard let rootMolecules = self.delegate?.moleculeDelegate?.getRootMolecules() else { return } + guard let rootMolecules = delegate?.moleculeDelegate?.getRootMolecules() else { return } let store = CNContactStore() let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() for consumer in consumers { From c8b382cc892b5ab131b2c84c9aa85458a70ded01 Mon Sep 17 00:00:00 2001 From: Damodaram Date: Thu, 22 Apr 2021 20:44:42 +0530 Subject: [PATCH 20/37] moved behaviour --- MVMCoreUI/Behaviors/GetContactBehavior.swift | 10 ++-------- .../Behaviors/Protocols/PageBehaviorProtocol.swift | 6 ------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index eaf3d5d9..b36f778b 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -21,7 +21,7 @@ public class PageGetContactBehaviorModel: PageBehaviorModelProtocol { public init() {} } -public class PageGetContactBehavior: PageVisibilityBehavior,PageNextBatchActionBehavior { +public class PageGetContactBehavior: PageVisibilityBehavior { var delegate: MVMCoreUIDelegateObject? @@ -45,7 +45,7 @@ public class PageGetContactBehavior: PageVisibilityBehavior,PageNextBatchActionB } } - func getContacts() { + public func getContacts() { guard let rootMolecules = delegate?.moleculeDelegate?.getRootMolecules() else { return } let store = CNContactStore() let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() @@ -57,10 +57,4 @@ public class PageGetContactBehavior: PageVisibilityBehavior,PageNextBatchActionB } public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {} - - public func nextBatchAction(_ delegateObject: MVMCoreUIDelegateObject?) { - if CNContactStore.authorizationStatus(for: .contacts) == .authorized { - getContacts() - } - } } diff --git a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift index 87df7007..e7db54bc 100644 --- a/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift +++ b/MVMCoreUI/Behaviors/Protocols/PageBehaviorProtocol.swift @@ -39,12 +39,6 @@ public protocol PageLocalDataShareBehavior: PageBehaviorProtocol { func receiveLocalPageData(_ data:[AnyHashable: Any], _ delegateObject: MVMCoreUIDelegateObject) } -public protocol PageNextBatchActionBehavior: PageBehaviorProtocol { - - func nextBatchAction(_ delegateObject: MVMCoreUIDelegateObject?) - -} - public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol { func handleAction(type actionType: String?, information: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) -> Bool From a225cf81e3db515a61fd26b42450413045403b74 Mon Sep 17 00:00:00 2001 From: Damodaram Date: Thu, 22 Apr 2021 20:54:44 +0530 Subject: [PATCH 21/37] review changes --- .../ListLeftVariableIconWithRightCaretAllTextLinksModel.swift | 2 +- MVMCoreUI/BaseControllers/ViewController.swift | 2 +- MVMCoreUI/Behaviors/GetContactBehavior.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift index 3f48a2d6..3129776b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconWithRightCaretAllTextLinksModel.swift @@ -18,7 +18,7 @@ public class ListLeftVariableIconWithRightCaretAllTextLinksModel: ListItemModel, public var rightLabel: LabelModel public var children: [MoleculeModelProtocol] { - return [image, eyebrowHeadlineBodyLink,rightLabel] + return [image, eyebrowHeadlineBodyLink, rightLabel] } //----------------------------------------------------- diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 20ba4a66..8a22e23a 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -653,7 +653,7 @@ import UIKit // MARK: - Behavior Execution //-------------------------------------------------- - public func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { + public func executeBehaviors(_ behaviorBlock: (_ behavior: T) -> Void) { behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } } } diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index b36f778b..c7327a1c 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -48,7 +48,7 @@ public class PageGetContactBehavior: PageVisibilityBehavior { public func getContacts() { guard let rootMolecules = delegate?.moleculeDelegate?.getRootMolecules() else { return } let store = CNContactStore() - let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() + let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() for consumer in consumers { guard let parameters = consumer.getMatchParameters(), let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } From 96c275d51c4af7b863dfef628a31d40868c3d75c Mon Sep 17 00:00:00 2001 From: Damodaram Date: Fri, 23 Apr 2021 09:46:00 +0530 Subject: [PATCH 22/37] added molecules parameter --- MVMCoreUI/Behaviors/GetContactBehavior.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index c7327a1c..1bb27ac7 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -33,9 +33,10 @@ public class PageGetContactBehavior: PageVisibilityBehavior { // Ask for permission CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in guard access, - error == nil else { return } + error == nil, + let rootMolecules = self?.delegate?.moleculeDelegate?.getRootMolecules() else { return } // Iterate models and provide contact - self?.getContacts() + self?.getContacts(for: rootMolecules) // Tell template to update MVMCoreDispatchUtility.performBlock(onMainThread: { @@ -45,10 +46,9 @@ public class PageGetContactBehavior: PageVisibilityBehavior { } } - public func getContacts() { - guard let rootMolecules = delegate?.moleculeDelegate?.getRootMolecules() else { return } + public func getContacts(for molecules: [MoleculeModelProtocol]) { + let consumers: [PageGetContactBehaviorConsumerProtocol] = molecules.allMoleculesOfType() let store = CNContactStore() - let consumers: [PageGetContactBehaviorConsumerProtocol] = rootMolecules.allMoleculesOfType() for consumer in consumers { guard let parameters = consumer.getMatchParameters(), let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } From a813313a925fcd1f7864ade7258244eadb0347ed Mon Sep 17 00:00:00 2001 From: Damodaram Date: Mon, 26 Apr 2021 12:48:11 +0530 Subject: [PATCH 23/37] body to generic model --- .../VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index ec646f86..83f5b4bd 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -73,7 +73,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMolecule backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) headline = try typeContainer.decodeMoleculeIfPresent(codingKey: .headline) - body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) + body = try typeContainer.decodeMoleculeIfPresent(codingKey: .body) link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) setDefaults() // TODO: This class initializers should ensure that atleast one item is set. From 0673c5b3a8bab0da08a48eac72d25f14475d9d84 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 30 Apr 2021 13:28:49 -0400 Subject: [PATCH 24/37] style for notification --- .../TopNotification/NotificationModel.swift | 76 +++++++++++++++++-- .../TopNotification/NotificationXButton.swift | 2 +- .../NotificationXButtonModel.swift | 4 +- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift index 3d02cecd..267f17d2 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift @@ -8,6 +8,21 @@ open class NotificationModel: MoleculeModelProtocol { + + /** + The style of the notification: + - success, green background, white content + - error, orange background, black content + - \warning, yellow background, black content + - information, blue background, white content + */ + public enum Style: String, Codable { + case success + case error + case warning + case information + } + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -19,6 +34,7 @@ open class NotificationModel: MoleculeModelProtocol { public var body: LabelModel? public var button: ButtonModel? public var closeButton: NotificationXButtonModel? + public var style: NotificationModel.Style = .success //-------------------------------------------------- // MARK: - Initializer @@ -34,20 +50,63 @@ open class NotificationModel: MoleculeModelProtocol { open func setDefault() { if backgroundColor == nil { - backgroundColor = Color(uiColor: .mvmGreen) + switch style { + case .error: + backgroundColor = Color(uiColor: .mvmOrange) + case .warning: + backgroundColor = Color(uiColor: .mvmYellow) + case .information: + backgroundColor = Color(uiColor: .mvmBlue) + default: + backgroundColor = Color(uiColor: .mvmGreen) + } } if headline.textColor == nil { - headline.textColor = Color(uiColor: .mvmWhite) + switch style { + case .error, .warning: + headline.textColor = Color(uiColor: .mvmBlack) + default: + headline.textColor = Color(uiColor: .mvmWhite) + } } if body?.textColor == nil { - body?.textColor = Color(uiColor: .mvmWhite) + switch style { + case .error, .warning: + body?.textColor = Color(uiColor: .mvmBlack) + default: + body?.textColor = Color(uiColor: .mvmWhite) + } + } + + button?.size = .tiny + if button?.enabledTextColor == nil { + switch style { + case .error, .warning: + button?.enabledTextColor = Color(uiColor: .mvmBlack) + default: + button?.enabledTextColor = Color(uiColor: .mvmWhite) + } + } + if button?.enabledBorderColor == nil { + switch style { + case .error, .warning: + button?.enabledBorderColor = Color(uiColor: .mvmBlack) + default: + button?.enabledBorderColor = Color(uiColor: .mvmWhite) + } } if button?.style == nil { button?.style = .secondary } - button?.size = .tiny - button?.enabledTextColor = Color(uiColor: .mvmWhite) - button?.enabledBorderColor = Color(uiColor: .mvmWhite) + + if closeButton?.color == nil { + switch style { + case .error, .warning: + closeButton?.color = Color(uiColor: .mvmBlack) + default: + closeButton?.color = Color(uiColor: .mvmWhite) + } + } } //-------------------------------------------------- @@ -62,6 +121,7 @@ open class NotificationModel: MoleculeModelProtocol { case body case button case closeButton + case style } //-------------------------------------------------- @@ -76,6 +136,9 @@ open class NotificationModel: MoleculeModelProtocol { 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 style = try typeContainer.decodeIfPresent(NotificationModel.Style.self, forKey: .style) { + self.style = style + } setDefault() } @@ -88,5 +151,6 @@ open class NotificationModel: MoleculeModelProtocol { try container.encodeIfPresent(body, forKey: .body) try container.encodeIfPresent(button, forKey: .button) try container.encodeIfPresent(closeButton, forKey: .closeButton) + try container.encode(style, forKey: .style) } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift index d2696722..204785cb 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift @@ -33,7 +33,7 @@ import Foundation 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 + tintColor = model.color?.uiColor ?? .white // TODO: Temporary, consider action for dismissing top alert if model.action.actionType == ActionNoopModel.identifier { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index 81dae17e..9661d9b3 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -11,7 +11,7 @@ import Foundation public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public static var identifier: String = "notificationXButton" public var backgroundColor: Color? - public var color = Color(uiColor: .white) + public var color: Color? public var action: ActionModelProtocol = ActionNoopModel() private enum CodingKeys: String, CodingKey { @@ -33,7 +33,7 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(color, forKey: .color) + try container.encodeIfPresent(color, forKey: .color) try container.encodeModel(action, forKey: .action) } } From eedd4e8174b4f837921fe7f7e2a69f3410ef6d35 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 30 Apr 2021 14:47:35 -0400 Subject: [PATCH 25/37] fix missed color for notifications --- .../Molecules/TopNotification/NotificationXButtonModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index 9661d9b3..59da1868 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -24,7 +24,7 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco public required init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) ?? Color(uiColor: .white) + color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) { self.action = action } From c5bbed2fb2f421f1717d46d889c58a1135beea98 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 3 May 2021 17:22:26 -0400 Subject: [PATCH 26/37] don't dismiss top alert when focus is nil --- .../Molecules/TopNotification/CollapsableNotification.swift | 2 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m | 2 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 8539c817..82983f4d 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -160,7 +160,7 @@ import Foundation /// Collapse if focus is no longer on this top alert. @objc func accessibilityFocusChanged(notification: Notification) { - if !MVMCoreUIUtility.viewContainsAccessiblityFocus(self) { + if (notification.userInfo?[UIAccessibility.focusedElementUserInfoKey] != nil) && !MVMCoreUIUtility.viewContainsAccessiblityFocus(self) { NotificationCenter.default.removeObserver(self, name: UIAccessibility.elementFocusedNotification, object: nil) collapse() } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m index 46ecd793..405dd781 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m @@ -423,7 +423,7 @@ } - (void)accessibilityFocusChanged:(NSNotification *)notification { - if (![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { + if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil]; [self collapse]; } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index ad0a833f..eba4cfcc 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -335,7 +335,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; /// If the voice over user leaves top alert focus, hide. - (void)accessibilityFocusChanged:(NSNotification *)notification { - if (![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { + if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil]; [self hideAlertView:YES completionHandler:self.hideCompletionHandler]; self.hideCompletionHandler = nil; From d77fdd5411d72a7195758eca127964fb77633e4e Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 6 May 2021 14:04:08 -0400 Subject: [PATCH 27/37] ActionOpenPageProtocol --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index a0785c41..82022b4c 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -141,7 +141,7 @@ public extension FormValidator { for actionItem in groupWatchers { if let buttonModel = actionItem as? ButtonModel, - pageType == (buttonModel.action as? ActionOpenPageModel)?.pageType { + pageType == (buttonModel.action as? ActionOpenPageProtocol)?.pageType { return buttonModel.groupName } } From 085c990475044a4d40077540679702181ce4271f Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 7 May 2021 12:05:11 -0400 Subject: [PATCH 28/37] fix --- MVMCoreUI/BaseClasses/Button.swift | 2 +- .../BaseControllers/ViewController.swift | 6 ++-- MVMCoreUI/FormUIHelpers/FormValidator.swift | 29 ++++--------------- 3 files changed, 10 insertions(+), 27 deletions(-) diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift index 1802e25d..a94cafe8 100644 --- a/MVMCoreUI/BaseClasses/Button.swift +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -79,7 +79,7 @@ public typealias ButtonAction = (Button) -> () addActionBlock(event: .touchUpInside) { [weak self] sender in 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, sourceModel: self.model) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 8a22e23a..3cbd2e50 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -449,8 +449,8 @@ import UIKit } /// Override this method to avoid adding form params. - open func addFormParams(_ requestParameters: MVMCoreRequestParameters) { - formValidator?.addFormParams(requestParameters: requestParameters) + open func addFormParams(requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { + formValidator?.addFormParams(requestParameters: requestParameters, model: additionalData?[KeySourceModel] as? MoleculeModelProtocol & FormFieldProtocol) } public func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { @@ -472,7 +472,7 @@ import UIKit //-------------------------------------------------- open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { - addFormParams(requestParameters) + addFormParams(requestParameters: requestParameters, actionInformation: actionInformation, additionalData: additionalData) requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType") var pageForwardedData = additionalData ?? [:] executeBehaviors { (behavior: PageLocalDataShareBehavior) in diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 82022b4c..28029397 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -112,20 +112,19 @@ import MVMCore // MARK: Form params // TODO: Temporary hacks, rewrite architecture to support this. -@objc public extension FormValidator { +public extension FormValidator { - @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { - let groupName = getGroupName(forPageType: requestParameters.pageType) ?? FormValidator.defaultGroupName - let formParams = self.getFormParams(forGroup: groupName) + func addFormParams(requestParameters: MVMCoreRequestParameters, model: (MoleculeModelProtocol & FormFieldProtocol)?) { + let groupName = model?.groupName ?? FormValidator.defaultGroupName + let formParams = getFormParams(forGroup: groupName) requestParameters.add(formParams) } - @objc func getFormParams( forGroup groupName: String) -> [String: Any] { + @objc func getFormParams(forGroup groupName: String) -> [String: Any] { var extraParam: [String: Any] = [:] for (fieldKey, field) in fields { - if let formFieldValue = field.formFieldValue(), - groupName == field.groupName { + if let formFieldValue = field.formFieldValue(), groupName == field.groupName { extraParam[fieldKey] = formFieldValue } } @@ -133,19 +132,3 @@ import MVMCore return extraParam } } - -// TODO: Temporary hacks, rewrite architecture to support this. -public extension FormValidator { - - func getGroupName(forPageType pageType: String?) -> String? { - - for actionItem in groupWatchers { - if let buttonModel = actionItem as? ButtonModel, - pageType == (buttonModel.action as? ActionOpenPageProtocol)?.pageType { - return buttonModel.groupName - } - } - - return nil - } -} From 39ba2c9c842c28dea7420e6c7baffe4805c19950 Mon Sep 17 00:00:00 2001 From: "Tondapu, Alekhya" Date: Thu, 13 May 2021 23:19:53 +0530 Subject: [PATCH 29/37] caretLink reload causing crash issue fixed --- MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index 5ae68241..caa356cf 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -59,12 +59,6 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { // MARK: - Lifecycle //------------------------------------------------------ - override open func layoutSubviews() { - - addCaretImageView() - super.layoutSubviews() - } - override public var isEnabled: Bool { didSet { changeCaretColor() } } @@ -135,7 +129,7 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { //------------------------------------------------------ public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - + addCaretImageView() guard let model = model as? CaretLinkModel else { return } if let color = model.backgroundColor { @@ -150,6 +144,11 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { setTitle(model.title, for: .normal) } + open override func reset() { + super.reset() + rightView?.removeFromSuperview() + } + public func needsToBeConstrained() -> Bool { true } open func horizontalAlignment() -> UIStackView.Alignment { .leading } From fe41350999e427d044f2a8962366adbaab5faad0 Mon Sep 17 00:00:00 2001 From: "Tondapu, Alekhya" Date: Thu, 13 May 2021 23:36:36 +0530 Subject: [PATCH 30/37] Indentation fix --- MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift index caa356cf..702c3238 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/CaretLink.swift @@ -145,8 +145,8 @@ open class CaretLink: Button, MVMCoreUIViewConstrainingProtocol { } open override func reset() { - super.reset() - rightView?.removeFromSuperview() + super.reset() + rightView?.removeFromSuperview() } public func needsToBeConstrained() -> Bool { true } From 9998a514f3f28077a2eb3bea2bd2885b4d2a0883 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 May 2021 16:31:23 -0400 Subject: [PATCH 31/37] get groupName from model --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 28029397..f27bb968 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -114,8 +114,8 @@ import MVMCore // TODO: Temporary hacks, rewrite architecture to support this. public extension FormValidator { - func addFormParams(requestParameters: MVMCoreRequestParameters, model: (MoleculeModelProtocol & FormFieldProtocol)?) { - let groupName = model?.groupName ?? FormValidator.defaultGroupName + func addFormParams(requestParameters: MVMCoreRequestParameters, model: (MoleculeModelProtocol & FormItemProtocol)?) { + let groupName = model?.groupName ?? getGroupName(forPageType: requestParameters.pageType) ?? FormValidator.defaultGroupName let formParams = getFormParams(forGroup: groupName) requestParameters.add(formParams) } @@ -132,3 +132,20 @@ public extension FormValidator { return extraParam } } + +// TODO: Temporary hacks, rewrite architecture to support this. +public extension FormValidator { + + func getGroupName(forPageType pageType: String?) -> String? { + + for actionItem in groupWatchers { + if let buttonModel = actionItem as? ButtonModel, + pageType == (buttonModel.action as? ActionOpenPageProtocol)?.pageType { + return buttonModel.groupName + } + } + + return nil + } +} + From 150db410768574f8c43595380ca667d364627d04 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 May 2021 17:03:29 -0400 Subject: [PATCH 32/37] remvoe newline --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index f27bb968..34623976 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -124,7 +124,8 @@ public extension FormValidator { var extraParam: [String: Any] = [:] for (fieldKey, field) in fields { - if let formFieldValue = field.formFieldValue(), groupName == field.groupName { + if let formFieldValue = field.formFieldValue(), + groupName == field.groupName { extraParam[fieldKey] = formFieldValue } } From 6a08f57626f482760d6e4f1082da4891afc6e4bf Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 17 May 2021 17:11:55 -0400 Subject: [PATCH 33/37] FormFieldProtocol to FormItemProtocol --- MVMCoreUI/BaseControllers/ViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 3cbd2e50..cd67632f 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -450,7 +450,7 @@ import UIKit /// Override this method to avoid adding form params. open func addFormParams(requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { - formValidator?.addFormParams(requestParameters: requestParameters, model: additionalData?[KeySourceModel] as? MoleculeModelProtocol & FormFieldProtocol) + formValidator?.addFormParams(requestParameters: requestParameters, model: additionalData?[KeySourceModel] as? MoleculeModelProtocol & FormItemProtocol) } public func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { From acb18d12b8923162ca0abb5c8dd3fcb4175f3935 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 19 May 2021 10:09:53 -0400 Subject: [PATCH 34/37] main thread fixes header width fixes --- MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift | 2 +- .../Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift index 912a60cb..72b1e7c0 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift @@ -25,7 +25,7 @@ open class HeaderView: Container { guard let margins = molecule.superview?.layoutMarginsGuide else { return } containerHelper.rightConstraint?.isActive = false containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) - containerHelper.rightConstraint?.priority = .defaultHigh + containerHelper.rightConstraint?.priority = UILayoutPriority(rawValue: 999) containerHelper.rightConstraint?.isActive = true molecule.widthAnchor.constraint(equalToConstant: HeaderMaxWidth).isActive = true } diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift index 5f3a0914..e7a29e8a 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift @@ -29,7 +29,7 @@ public class MoleculeHeaderView: MoleculeContainer { guard let margins = molecule.superview?.layoutMarginsGuide else { return } containerHelper.rightConstraint?.isActive = false containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) - containerHelper.rightConstraint?.priority = .defaultHigh + containerHelper.rightConstraint?.priority = UILayoutPriority(rawValue: 999) containerHelper.rightConstraint?.isActive = true molecule.widthAnchor.constraint(lessThanOrEqualToConstant: HeaderMaxWidth).isActive = true } From 06407930ab57fff0e5c9c36aba9d4e10603dacd3 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 21 May 2021 09:22:17 -0400 Subject: [PATCH 35/37] revert max header width until wee can properly do it --- .../Atomic/Molecules/HeadersAndFooters/Header.swift | 6 ------ .../HeadersAndFooters/MoleculeHeaderView.swift | 10 ---------- 2 files changed, 16 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift index 72b1e7c0..73b42dea 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/Header.swift @@ -22,12 +22,6 @@ open class HeaderView: Container { addSubview(molecule) containerHelper.constrainView(molecule) self.molecule = molecule - guard let margins = molecule.superview?.layoutMarginsGuide else { return } - containerHelper.rightConstraint?.isActive = false - containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) - containerHelper.rightConstraint?.priority = UILayoutPriority(rawValue: 999) - containerHelper.rightConstraint?.isActive = true - molecule.widthAnchor.constraint(equalToConstant: HeaderMaxWidth).isActive = true } // MARK: - MVMCoreViewProtocol diff --git a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift index e7a29e8a..9e4afed6 100644 --- a/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift +++ b/MVMCoreUI/Atomic/Molecules/HeadersAndFooters/MoleculeHeaderView.swift @@ -24,16 +24,6 @@ public class MoleculeHeaderView: MoleculeContainer { // MARK: - MVMCoreViewProtocol //-------------------------------------------------- - public override func addMolecule(_ molecule: UIView) { - super.addMolecule(molecule) - guard let margins = molecule.superview?.layoutMarginsGuide else { return } - containerHelper.rightConstraint?.isActive = false - containerHelper.rightConstraint = margins.rightAnchor.constraint(equalTo: molecule.rightAnchor) - containerHelper.rightConstraint?.priority = UILayoutPriority(rawValue: 999) - containerHelper.rightConstraint?.isActive = true - molecule.widthAnchor.constraint(lessThanOrEqualToConstant: HeaderMaxWidth).isActive = true - } - open override func updateView(_ size: CGFloat) { super.updateView(size) line.updateView(size) From d90e68e263e43170970c8c246ec0a35ec95e7bc8 Mon Sep 17 00:00:00 2001 From: "Christiano, Kevin" Date: Mon, 24 May 2021 14:53:31 +0000 Subject: [PATCH 36/37] Checking bars indicator --- .../CarouselIndicator/BarsIndicatorView.swift | 191 +++++++++++++----- .../CarouselIndicator/CarouselIndicator.swift | 31 ++- .../NumericIndicatorView.swift | 2 +- .../Atomic/Organisms/Carousel/Carousel.swift | 127 ++++++------ 4 files changed, 228 insertions(+), 123 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift index f2b87c0a..975c7ebb 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/BarsIndicatorView.swift @@ -14,6 +14,37 @@ open class BarsIndicatorView: CarouselIndicator { // MARK: - Stored Properties //-------------------------------------------------- + /// Represents the data of each individual bar. + private class IndicatorBar: View { + // Dimensions are based on InVision Design Guidelines. + static let width: CGFloat = 24 + static let selectedHeight: CGFloat = 4 + static let unselectedHeight: CGFloat = 1 + + var constraint: NSLayoutConstraint? + + init() { + super.init(frame: .zero) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + fatalError("init(model:_:_:) has not been implemented") + } + + override func setupView() { + super.setupView() + isAccessibilityElement = true + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint") + widthAnchor.constraint(equalToConstant: BarsIndicatorView.IndicatorBar.width).isActive = true + accessibilityTraits = .button + } + } + + /// Structured container to hold and layout the indicator bars. public let stackView: UIStackView = { let stackView = UIStackView() stackView.translatesAutoresizingMaskIntoConstraints = false @@ -25,11 +56,8 @@ open class BarsIndicatorView: CarouselIndicator { return stackView }() - public var barReferences: [(view: View, constraint: NSLayoutConstraint)] = [] - - // Dimensions are based on InVision Design Guidelines. - public static let indicatorBarWidth: CGFloat = 24 - public static let indicatorBarHeight: (selected: CGFloat, unselected: CGFloat) = (selected: 4, unselected: 1) + /// Reference to each bar displayed. + private var barReferences: [IndicatorBar] = [] //-------------------------------------------------- // MARK: - Computed Properties @@ -37,16 +65,16 @@ open class BarsIndicatorView: CarouselIndicator { /// Convenience to access the model. public var barsCarouselIndicatorModel: BarsCarouselIndicatorModel? { - return model as? BarsCarouselIndicatorModel + model as? BarsCarouselIndicatorModel } open override var isEnabled: Bool { didSet { - for (i, bar) in barReferences.enumerated() { + for (i, indicatorBar) in barReferences.enumerated() { if i == currentIndex { - bar.view.backgroundColor = isEnabled ? currentIndicatorColor : disabledIndicatorColor + indicatorBar.backgroundColor = isEnabled ? currentIndicatorColor : disabledIndicatorColor } else { - bar.view.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor + indicatorBar.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor } } } @@ -54,21 +82,22 @@ open class BarsIndicatorView: CarouselIndicator { /// Colors the currently selected index, unique from other indicators public var currentIndicatorColor: UIColor { - get { return barsCarouselIndicatorModel?.currentIndicatorColor.uiColor ?? indicatorColor } - set (newColor) { - barsCarouselIndicatorModel?.currentIndicatorColor = Color(uiColor: newColor) + get { barsCarouselIndicatorModel?.currentIndicatorColor.uiColor ?? indicatorColor } + set { + barsCarouselIndicatorModel?.currentIndicatorColor = Color(uiColor: newValue) if isEnabled && !barReferences.isEmpty { - barReferences[currentIndex].view.backgroundColor = newColor + barReferences[currentIndex].backgroundColor = newValue } } } + /// The color of the indicator bars. public override var indicatorColor: UIColor { - get { return super.indicatorColor } - set (newColor) { - super.indicatorColor = newColor - refreshBarColors(with: newColor) + get { super.indicatorColor } + set { + super.indicatorColor = newValue + refreshBarColors(with: newValue) } } @@ -84,7 +113,7 @@ open class BarsIndicatorView: CarouselIndicator { isAccessibilityElement = false NSLayoutConstraint.activate([ - stackView.heightAnchor.constraint(equalToConstant: 4), + stackView.heightAnchor.constraint(equalToConstant: Padding.One), heightAnchor.constraint(equalTo: stackView.heightAnchor), stackView.leadingAnchor.constraint(equalTo: leadingAnchor), stackView.topAnchor.constraint(equalTo: topAnchor), @@ -97,44 +126,95 @@ open class BarsIndicatorView: CarouselIndicator { // MARK: - Methods //-------------------------------------------------- + /// Updates the color of all indicator bars. private func refreshBarColors(with color: UIColor) { - if isEnabled { - for (i, barTuple) in barReferences.enumerated() { - barTuple.view.backgroundColor = i == currentIndex ? currentIndicatorColor : color - } + guard isEnabled else { return } + + for (i, indicatorBar) in barReferences.enumerated() { + indicatorBar.backgroundColor = i == currentIndex ? currentIndicatorColor : color } } + /// Creates all the indicato bars for display. func generateBars() { - var bars = [(View, NSLayoutConstraint)]() + var bars = [IndicatorBar]() for i in 0.. 0 { + // If positive, add n bars. + var copyBars = barReferences + + for _ in 0.. IndicatorBar { + + let bar = IndicatorBar() + setAccessibilityLabel(view: bar, index: index) + bar.backgroundColor = isEnabled ? (index == currentIndex ? currentIndicatorColor : indicatorColor) : disabledIndicatorColor + let barHeight = index == currentIndex ? BarsIndicatorView.IndicatorBar.selectedHeight : BarsIndicatorView.IndicatorBar.unselectedHeight + let heightConstraint = bar.heightAnchor.constraint(equalToConstant: barHeight) + heightConstraint.isActive = true + bar.constraint = heightConstraint + + return bar + } + + /// Refreshes the accessibility labels to read "x of n". + private func refreshAccessibilityLabels() { + for i in 0..= touchPoint_X && $0.0.frame.minX <= touchPoint_X } ?? 0 + currentIndex = barReferences.firstIndex { $0.frame.maxX >= touchPoint_X && $0.frame.minX <= touchPoint_X } ?? 0 performAction() } @@ -152,27 +232,40 @@ open class BarsIndicatorView: CarouselIndicator { public override func reset() { super.reset() - barReferences.forEach { $0.view.removeFromSuperview() } + barReferences.forEach { $0.removeFromSuperview() } barReferences = [] } public override func updateUI(previousIndex: Int, newIndex: Int, totalCount: Int, isAnimated: Bool) { - guard newIndex < totalCount else { return } - + // Ensure that at least one bar exists. guard !barReferences.isEmpty else { generateBars() return } - let expression = { - self.barReferences[previousIndex].view.backgroundColor = self.isEnabled ? self.indicatorColor : self.disabledIndicatorColor - self.barReferences[newIndex].view.backgroundColor = self.isEnabled ? self.currentIndicatorColor : self.disabledIndicatorColor - self.barReferences[previousIndex].constraint.constant = BarsIndicatorView.indicatorBarHeight.unselected - self.barReferences[newIndex].constraint.constant = BarsIndicatorView.indicatorBarHeight.selected - self.layoutIfNeeded() + guard newIndex < totalCount else { return } + + // Ensure the number of pages matches the number of bar references. + if (totalCount - barReferences.count) != 0 { + barReferences.forEach { + $0.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor + $0.constraint?.constant = IndicatorBar.unselectedHeight + } + + balanceBarCount(numberOfPages - barReferences.count) + refreshAccessibilityLabels() } - isAnimated ? UIView.animate(withDuration: 0.3) { expression() } : expression() + let expression = { [self] in + barReferences[previousIndex].backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor + barReferences[previousIndex].constraint?.constant = IndicatorBar.unselectedHeight + barReferences[newIndex].backgroundColor = isEnabled ? currentIndicatorColor : disabledIndicatorColor + barReferences[newIndex].constraint?.constant = IndicatorBar.selectedHeight + layoutIfNeeded() + } + + // Perform the animation. + isAnimated ? UIView.animate(withDuration: 0.25) { expression() } : expression() } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift index 040657c5..6a82ef80 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift @@ -6,8 +6,6 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -import Foundation - open class CarouselIndicator: Control, CarouselPageControlProtocol { //-------------------------------------------------- @@ -25,7 +23,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { /// Convenience to access the model. public var carouselIndicatorModel: CarouselIndicatorModel? { - return model as? CarouselIndicatorModel + model as? CarouselIndicatorModel } /// Set this closure to perform an action when a different indicator was selected. @@ -43,7 +41,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { private(set) var previousIndex = 0 public var currentIndex: Int { - get { return carouselIndicatorModel?.currentIndex ?? 0 } + get { carouselIndicatorModel?.currentIndex ?? 0 } set (newIndex) { previousIndex = currentIndex carouselIndicatorModel?.currentIndex = newIndex @@ -58,22 +56,22 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { /// Holds the total number of pages displayed by the carousel. /// Updating this property will potentially update the UI. public var numberOfPages: Int { - get { return carouselIndicatorModel?.numberOfPages ?? 0 } - set (newTotal) { - guard numberOfPages != newTotal else { return } + get { carouselIndicatorModel?.numberOfPages ?? 0 } + set { + guard numberOfPages != newValue else { return } - carouselIndicatorModel?.numberOfPages = newTotal + carouselIndicatorModel?.numberOfPages = newValue reset() - isHidden = (carouselIndicatorModel?.hidesForSinglePage ?? false) && newTotal <= 1 + isHidden = (carouselIndicatorModel?.hidesForSinglePage ?? false) && newValue <= 1 updateUI(previousIndex: previousIndex, newIndex: currentIndex, - totalCount: newTotal, + totalCount: newValue, isAnimated: carouselIndicatorModel?.animated ?? true) } } public var disabledIndicatorColor: UIColor { - get { return carouselIndicatorModel?.disabledIndicatorColor.uiColor ?? .mvmCoolGray3 } + get { carouselIndicatorModel?.disabledIndicatorColor.uiColor ?? .mvmCoolGray3 } set { carouselIndicatorModel?.disabledIndicatorColor = Color(uiColor: newValue) } } @@ -92,7 +90,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { } var accessibilityValueFormat: String? { - return MVMCoreUIUtility.hardcodedString(withKey: (carouselIndicatorModel?.accessibilityHasSlidesInsteadOfPage ?? false) ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") + MVMCoreUIUtility.hardcodedString(withKey: (carouselIndicatorModel?.accessibilityHasSlidesInsteadOfPage ?? false) ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") } //-------------------------------------------------- @@ -175,12 +173,14 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { assessTouchOf(touchPoint_X) } + /// Determines where a touch in the indicator translate to an index selection. func assessTouchOf(_ touchPoint_X: CGFloat) { } //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- + /// Called to update the Indicator UI with the latest values. open func updateUI(previousIndex: Int, newIndex: Int, totalCount: Int, isAnimated: Bool) { } public func performAction() { @@ -200,6 +200,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { guard let model = model as? CarouselIndicatorModel else { return } + previousIndex = 0 indicatorColor = model.inverted ? model.indicatorColor_inverted.uiColor : model.indicatorColor.uiColor disabledIndicatorColor = model.disabledIndicatorColor.uiColor currentIndex = model.currentIndex @@ -214,20 +215,18 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol { //-------------------------------------------------- open override func accessibilityIncrement() { - adjustAccessibility(toPage: currentIndex + 1) } open override func accessibilityDecrement() { - adjustAccessibility(toPage: currentIndex - 1) } func formatAccessibilityValue(index: Int, total: Int) { guard let accessibleFormat = accessibilityValueFormat, - let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index)) - else { return } + let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index)) + else { return } accessibilityValue = String(format: accessibleFormat, accessibleIndex, total) } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift index afbe30d4..eb3a8ebd 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/NumericIndicatorView.swift @@ -47,7 +47,7 @@ open class NumericIndicatorView: CarouselIndicator { /// Sets the color for pageCount text, left arrow and right arrow. public override var indicatorColor: UIColor { - get { return super.indicatorColor } + get { super.indicatorColor } set (newColor) { super.indicatorColor = newColor diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift index 38081287..67e024ca 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/Carousel.swift @@ -17,7 +17,7 @@ public protocol CarouselPageControlProtocol { } open class Carousel: View { - + public let collectionView: CollectionView = { let layout = CarouselCollectionLayout() layout.scrollDirection = .horizontal @@ -25,7 +25,7 @@ open class Carousel: View { layout.minimumLineSpacing = 0 return CollectionView(frame: .zero, collectionViewLayout: layout) }() - + /// The current index of the collection view. Includes dummy cells when looping. public var currentIndex = 0 @@ -53,8 +53,8 @@ open class Carousel: View { public var collectionViewHeight: NSLayoutConstraint? /// The view that we use for paging - public var pagingView: (UIView & CarouselPageControlProtocol)? - + public var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? + /// If the carousel should loop after scrolling past the first and final cells. public var loop = false @@ -85,10 +85,10 @@ open class Carousel: View { open func layoutCollection() { collectionView.collectionViewLayout.invalidateLayout() showPeaking(false) - + // Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled. guard let model = model as? CarouselModel, - (model.paging == true || loop == true) else { return } + (model.paging == true || loop == true) else { return } DispatchQueue.main.async { self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false) self.collectionView.layoutIfNeeded() @@ -152,12 +152,12 @@ open class Carousel: View { collectionView.layer.borderWidth = (carouselModel.border ?? false) ? 1 : 0 (collectionView.collectionViewLayout as? CarouselCollectionLayout)?.useLines = carouselModel.border ?? false (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing = carouselModel.spacing ?? 0 - + itemWidthPercent = carouselModel.itemWidthPercent / 100.0 if let alignment = carouselModel.itemAlignment { itemAlignment = alignment } - + if let height = carouselModel.height { collectionViewHeight?.constant = height collectionViewHeight?.isActive = true @@ -168,7 +168,7 @@ open class Carousel: View { registerCells(with: carouselModel, delegateObject: delegateObject) prepareMolecules(with: carouselModel) FormValidator.setupValidation(for: carouselModel, delegate: delegateObject?.formHolderDelegate) - + setupPagingMolecule(carouselModel.pagingMolecule, delegateObject: delegateObject) pageIndex = carouselModel.index @@ -197,7 +197,7 @@ open class Carousel: View { if carouselModel?.loop ?? false && newMolecules.count > 1 && !UIAccessibility.isVoiceOverRunning { // Sets up the row data with buffer cells on each side (for illusion of endless scroll... also has one more buffer cell on each side in case we can peek that cell). loop = true - + molecules?.insert(contentsOf: newMolecules.suffix(2), at: 0) molecules?.append(contentsOf: newMolecules.prefix(2)) } else { @@ -207,12 +207,25 @@ open class Carousel: View { pageIndex = 0 } + var pagingMoleculeName: String? + /// Sets up the paging molecule open func setupPagingMolecule(_ molecule: (CarouselPagingModelProtocol & MoleculeModelProtocol)?, delegateObject: MVMCoreUIDelegateObject?) { - var pagingView: (UIView & CarouselPageControlProtocol)? = nil + if let molecule = molecule, - (!molecule.hidesForSinglePage || numberOfPages > 1) { - pagingView = ModelRegistry.createMolecule(molecule, delegateObject: delegateObject) as? (UIView & CarouselPageControlProtocol) + molecule.moleculeName == pagingMoleculeName { + pagingView?.set(with: molecule, delegateObject, nil) + pagingView?.numberOfPages = numberOfPages + return + } + + var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? = nil + if let molecule = molecule, + (!molecule.hidesForSinglePage || numberOfPages > 1) { + pagingView = ModelRegistry.createMolecule(molecule, delegateObject: delegateObject) as? (MoleculeViewProtocol & CarouselPageControlProtocol) + pagingMoleculeName = molecule.moleculeName + } else { + pagingMoleculeName = nil } addPaging(view: pagingView, position: molecule?.position ?? 20) @@ -239,7 +252,7 @@ open class Carousel: View { } /// Adds a paging view. Centers it horizontally with the collection view. The position is the vertical distance from the center of the page view to the bottom of the collection view. - open func addPaging(view: (UIView & CarouselPageControlProtocol)?, position: CGFloat) { + open func addPaging(view: (MoleculeViewProtocol & CarouselPageControlProtocol)?, position: CGFloat) { pagingView?.removeFromSuperview() bottomPin?.isActive = false @@ -296,7 +309,7 @@ open class Carousel: View { func trackSwipeActionAnalyticsforIndex(_ index : Int){ guard let itemModel = molecules?[index], - let viewControllerObject = delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol else { return } + let viewControllerObject = delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol else { return } MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: viewControllerObject, actionInformation: itemModel.toJSON(), additionalData: nil) } @@ -352,7 +365,7 @@ open class Carousel: View { carouselAccessibilityElement.accessibilityFrameInContainerSpace = collectionView.frame self.carouselAccessibilityElement = carouselAccessibilityElement } - + if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) { _accessibilityElements = [currentCell, carouselAccessibilityElement] } else { @@ -378,11 +391,11 @@ extension Carousel: UICollectionViewDataSource { open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return molecules?.count ?? 0 } - + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let molecule = molecules?[indexPath.row], - let moleculeInfo = getMoleculeInfo(with: molecule, delegateObject: nil) - else { return UICollectionViewCell() } + let moleculeInfo = getMoleculeInfo(with: molecule, delegateObject: nil) + else { return UICollectionViewCell() } let cell = collectionView.dequeueReusableCell(withReuseIdentifier: moleculeInfo.identifier, for: indexPath) if let protocolCell = cell as? MoleculeViewProtocol { @@ -445,22 +458,22 @@ extension Carousel: UIScrollViewDelegate { if translatedPoint > 0 { // Moving left, see if we are moving passed the first left buffer card and adjust if let threshold = collectionView.layoutAttributesForItem(at: IndexPath(item: 1, section: 0))?.frame.minX, - scrollView.contentOffset.x < threshold, - let newOffset = collectionView.layoutAttributesForItem(at: IndexPath(item: numberOfPages + 1, section: 0))?.frame.minX { + scrollView.contentOffset.x < threshold, + let newOffset = collectionView.layoutAttributesForItem(at: IndexPath(item: numberOfPages + 1, section: 0))?.frame.minX { scrollView.contentOffset.x = newOffset } } else if translatedPoint < 0 { // Moving right, see if we are moving passed the first right buffer card and adjust if let threshold = collectionView.layoutAttributesForItem(at: IndexPath(item: numberOfPages + 2, section: 0))?.frame.maxX, - scrollView.contentOffset.x + scrollView.bounds.width > threshold, - let newEndOffset = collectionView.layoutAttributesForItem(at: IndexPath(item: 2, section: 0))?.frame.maxX { + scrollView.contentOffset.x + scrollView.bounds.width > threshold, + let newEndOffset = collectionView.layoutAttributesForItem(at: IndexPath(item: 2, section: 0))?.frame.maxX { scrollView.contentOffset.x = newEndOffset - scrollView.bounds.width } } } - + open func scrollViewDidScroll(_ scrollView: UIScrollView) { - + // Adjust for looping if loop == true { adjustOffsetForLooping(scrollView) @@ -474,7 +487,7 @@ extension Carousel: UIScrollViewDelegate { // Disable peaking when dragging. dragging = true - + showPeaking(false) } @@ -484,7 +497,7 @@ extension Carousel: UIScrollViewDelegate { // This is for setting up smooth custom paging. (Since UICollectionView only handles paging based on collection view size and not cell size). Math requires that we are using UICollectionViewFlowLayout. guard (model as? CarouselModel)?.paging == true, - let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return } + let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return } let separatorWidth = layout.minimumLineSpacing let itemWidth = collectionView.bounds.width * itemWidthPercent @@ -529,7 +542,7 @@ extension Carousel: UIScrollViewDelegate { } else { targetContentOffset.pointee = scrollView.contentOffset } - + // Cap the index. let lastCellIndex = collectionView(collectionView, numberOfItemsInSection: 0) - 1 goTo(min(max(cellToSwipeTo, 0), lastCellIndex), animated: true) @@ -548,35 +561,35 @@ extension Carousel: UIScrollViewDelegate { // Adapted from: https://developer.apple.com/documentation/uikit/accessibility_for_ios_and_tvos/delivering_an_exceptional_accessibility_experience /// Ensures a good accessibility experience. Adds adjustable swiping for cards. class CarouselAccessibilityElement: UIAccessibilityElement { - + /// This indicates to the user what exactly this element is supposed to be. override var accessibilityLabel: String? { get { guard let containerView = accessibilityContainer as? Carousel, - let accessibilityLabel = containerView.accessibilityLabel else { return super.accessibilityLabel } + let accessibilityLabel = containerView.accessibilityLabel else { return super.accessibilityLabel } return accessibilityLabel } set { super.accessibilityLabel = newValue } } - + override var accessibilityValue: String? { get { // Read which card we are on. guard let containerView = accessibilityContainer as? Carousel, - let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"), - let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: containerView.currentIndex + 1)) else { + let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"), + let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: containerView.currentIndex + 1)) else { return super.accessibilityValue } return String(format: format, indexString, containerView.numberOfPages) } - + set { super.accessibilityValue = newValue } } - + // This tells VoiceOver that our element will support the increment and decrement callbacks. /// - Tag: accessibility_traits override var accessibilityTraits: UIAccessibilityTraits { @@ -587,41 +600,41 @@ class CarouselAccessibilityElement: UIAccessibilityElement { super.accessibilityTraits = newValue } } - + /** - A convenience for forward scrolling in both `accessibilityIncrement` and `accessibilityScroll`. - It returns a `Bool` because `accessibilityScroll` needs to know if the scroll was successful. - */ + A convenience for forward scrolling in both `accessibilityIncrement` and `accessibilityScroll`. + It returns a `Bool` because `accessibilityScroll` needs to know if the scroll was successful. + */ func accessibilityScrollForward() -> Bool { guard let containerView = accessibilityContainer as? Carousel else { return false } - + let newIndex = containerView.currentIndex + 1 guard newIndex < containerView.numberOfPages else { return false } - + containerView.goTo(newIndex, animated: false) return true } - + /** - A convenience for backward scrolling in both `accessibilityIncrement` and `accessibilityScroll`. - It returns a `Bool` because `accessibilityScroll` needs to know if the scroll was successful. - */ + A convenience for backward scrolling in both `accessibilityIncrement` and `accessibilityScroll`. + It returns a `Bool` because `accessibilityScroll` needs to know if the scroll was successful. + */ func accessibilityScrollBackward() -> Bool { guard let containerView = accessibilityContainer as? Carousel else { return false } - + let newIndex = containerView.currentIndex - 1 guard newIndex >= 0 else { return false } - + containerView.goTo(newIndex, animated: false) - + return true } - + /* - Overriding the following two methods allows the user to perform increment and decrement actions - (done by swiping up or down). - */ + Overriding the following two methods allows the user to perform increment and decrement actions + (done by swiping up or down). + */ /// - Tag: accessibility_increment_decrement override func accessibilityIncrement() { // This causes the picker to move forward one if the user swipes up. @@ -632,12 +645,12 @@ class CarouselAccessibilityElement: UIAccessibilityElement { // This causes the picker to move back one if the user swipes down. _ = accessibilityScrollBackward() } - + /* - This will cause the picker to move forward or backwards on when the user does a 3-finger swipe, - depending on the direction of the swipe. The return value indicates whether or not the scroll was successful, - so that VoiceOver can alert the user if it was not. - */ + This will cause the picker to move forward or backwards on when the user does a 3-finger swipe, + depending on the direction of the swipe. The return value indicates whether or not the scroll was successful, + so that VoiceOver can alert the user if it was not. + */ override func accessibilityScroll(_ direction: UIAccessibilityScrollDirection) -> Bool { if direction == .left { return accessibilityScrollForward() From 6842a08276e172d8694cd695cc8cfb7ebf574656 Mon Sep 17 00:00:00 2001 From: Sourabh Bhardwaj <> Date: Tue, 25 May 2021 23:09:03 +0530 Subject: [PATCH 37/37] Fixed back button not showing in call filter CXTDT-181208 --- MVMCoreUI/Behaviors/GetContactBehavior.swift | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift index 1bb27ac7..9b488e68 100644 --- a/MVMCoreUI/Behaviors/GetContactBehavior.swift +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -41,7 +41,20 @@ public class PageGetContactBehavior: PageVisibilityBehavior { // Tell template to update MVMCoreDispatchUtility.performBlock(onMainThread: { // TODO: move to protocol function instead - (self?.delegate?.moleculeDelegate as? ViewController)?.handleNewDataAndUpdateUI() + guard let controller = self?.delegate?.moleculeDelegate as? ViewController else { return } + controller.handleNewDataAndUpdateUI() + + if MVMCoreUIUtility.getCurrentVisibleController() == controller { + // Update navigation bar if showing. + controller.setNavigationBar() + controller.manager?.refreshNavigationUI() + } + + // Update splitview properties + if controller == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() { + MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(controller.bottomProgress() ?? 0) + controller.updateTabBar() + } }) } }