Merge branch 'feature/develop_mvp_3' into 'develop'

Feature/develop mvp 3

See merge request BPHV_MIPS/mvm_core_ui!818
This commit is contained in:
Pfeil, Scott Robert 2022-06-24 21:02:40 +00:00
commit cb0073c9ff
105 changed files with 2049 additions and 1307 deletions

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 48;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
@ -126,6 +126,7 @@
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; };
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; };
0AF60F0926B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */; };
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */; };
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */; };
1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258726899B0B00DEBB08 /* ImageButton.swift */; };
279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; };
@ -145,6 +146,9 @@
32D2609724C19E2100B56344 /* LockupsPlanSMLXLModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D2609524C19E2100B56344 /* LockupsPlanSMLXLModel.swift */; };
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */; };
32F8804824765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */; };
444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C02821B73200DFE692 /* TitleLockup.swift */; };
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */; };
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; };
522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; };
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; };
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; };
@ -272,6 +276,8 @@
AAE7270E24AC8B9300A3ED0E /* HeadersH2CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */; };
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */; };
AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */; };
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; };
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; };
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; };
@ -711,6 +717,7 @@
0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = "<group>"; };
0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = "<group>"; };
0AF60F0826B3316E00AC3DB4 /* MVMCoreUIUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIUtility+Extension.swift"; sourceTree = "<group>"; };
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; };
1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; };
279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = "<group>"; };
@ -730,6 +737,9 @@
32D2609524C19E2100B56344 /* LockupsPlanSMLXLModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LockupsPlanSMLXLModel.swift; sourceTree = "<group>"; };
32F8804524765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinksModel.swift; sourceTree = "<group>"; };
32F8804724765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableNumberedListAllTextAndLinks.swift; sourceTree = "<group>"; };
444FB7C02821B73200DFE692 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = "<group>"; };
444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = "<group>"; };
4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = "<group>"; };
522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = "<group>"; };
522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = "<group>"; };
52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = "<group>"; };
@ -857,6 +867,8 @@
AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2CaretLink.swift; sourceTree = "<group>"; };
AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = "<group>"; };
AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = "<group>"; };
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = "<group>"; };
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = "<group>"; };
@ -1181,7 +1193,9 @@
buildActionMask = 2147483647;
files = (
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */,
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */,
9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */,
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1424,6 +1438,8 @@
525019DC2406430800EED91C /* ListProgressBarData.swift */,
AA45AA0A24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift */,
AA45AA0C24BF0276007A6EA7 /* LockUpsPlanNames.swift */,
444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */,
444FB7C02821B73200DFE692 /* TitleLockup.swift */,
);
path = LockUps;
sourceTree = "<group>";
@ -1535,6 +1551,15 @@
path = Miscellaneous;
sourceTree = "<group>";
};
AFE4A1D427DFBB2700C458D0 /* NavigationController */ = {
isa = PBXGroup;
children = (
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */,
);
path = NavigationController;
sourceTree = "<group>";
};
D202AFE2242A5F1400E5BEDF /* Extensions */ = {
isa = PBXGroup;
children = (
@ -1549,6 +1574,7 @@
D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */,
D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */,
D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */,
4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -2002,6 +2028,8 @@
D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = {
isa = PBXGroup;
children = (
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */,
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */,
D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */,
9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */,
);
@ -2072,9 +2100,9 @@
D29DF11921E68467003B2FB9 /* Containers */ = {
isa = PBXGroup;
children = (
AFE4A1D427DFBB2700C458D0 /* NavigationController */,
0ABD1369237B18EE0081388D /* Views */,
D29DF2B621E7BE66003B2FB9 /* SplitViewController */,
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
);
path = Containers;
sourceTree = "<group>";
@ -2637,6 +2665,7 @@
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */,
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */,
AAC23FAD24D92A0D009208DF /* ListThreeColumnSpeedTestModel.swift in Sources */,
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */,
@ -2644,6 +2673,7 @@
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */,
AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */,
444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */,
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */,
D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */,
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
@ -2837,6 +2867,7 @@
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
32D2609624C19E2100B56344 /* LockupsPlanSMLXL.swift in Sources */,
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */,
D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */,
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
@ -2903,6 +2934,7 @@
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */,
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */,
D23118B325124E18001C8440 /* Notification.swift in Sources */,
AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */,
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
@ -3268,7 +3300,8 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -3290,9 +3323,13 @@
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks";
INFOPLIST_FILE = MVMCoreUI/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 1.2;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCoreUI;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
@ -3317,9 +3354,13 @@
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../SharedFrameworks";
INFOPLIST_FILE = MVMCoreUI/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 1.2;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 2.0;
PRODUCT_BUNDLE_IDENTIFIER = com.vzw.MVMCoreUI;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;

View File

@ -5,7 +5,7 @@
// Created by Suresh, Kamlesh on 7/9/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class ActionAlertModel: ActionModelProtocol {
//--------------------------------------------------
@ -17,4 +17,12 @@
public var alert: AlertModel
public var extraParameters: JSONValueDictionary?
public var analyticsData: JSONValueDictionary?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(alert: AlertModel) {
self.alert = alert
}
}

View File

@ -7,6 +7,7 @@
//
import UIKit
import VDSColorTokens
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
@ -17,12 +18,12 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
//--------------------------------------------------
//Making static property as class property so that subclasses can override getter function of the property
open class var identifier: String { "button" }
public var backgroundColor: Color?
public var accessibilityIdentifier: String?
public var accessibilityText: String?
public var title: String
public var action: ActionModelProtocol
public var enabled: Bool = true
public var width: CGFloat?
public var style: Styler.Button.Style? {
didSet {
guard let style = style else { return }
@ -57,6 +58,20 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public var disabledTextColor_inverted: Color?
public var disabledBorderColor_inverted: Color?
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
return enabled ? enabledFillColor_inverted : disabledFillColor_inverted
}
return enabled ? enabledFillColor : disabledFillColor
}
set {
_backgroundColor = newValue
}
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
@ -70,18 +85,21 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
public init(with title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
setFacade(by: .primary)
}
public init(secondaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .secondary
setFacade(by: .secondary)
}
public init(primaryButtonWith title: String, action: ActionModelProtocol) {
self.title = title
self.action = action
style = .primary
setFacade(by: .primary)
}
//--------------------------------------------------
@ -114,40 +132,30 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
/// Defines the default appearance for the primary style.
func setPrimaryFacade() {
enabledFillColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledFillColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
if enabledFillColor == nil && enabledTextColor == nil {
enabledFillColor = Color(uiColor: .mvmBlack)
enabledTextColor = Color(uiColor: .mvmWhite)
}
if disabledFillColor == nil && disabledTextColor == nil {
disabledFillColor = Color(uiColor: .mvmCoolGray6)
disabledTextColor = Color(uiColor: .mvmWhite)
}
enabledFillColor_inverted = Color(uiColor: .mvmWhite)
enabledTextColor_inverted = Color(uiColor: .mvmBlack)
disabledFillColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledTextColor_inverted = Color(uiColor: .mvmBlack)
enabledFillColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledFillColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
/// Defines the default appearance for the Secondary style.
func setSecondaryFacade() {
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
enabledFillColor = Color(uiColor: UIColor.clear)
enabledBorderColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
disabledTextColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
disabledBorderColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
if enabledTextColor == nil && enabledBorderColor == nil {
enabledTextColor = Color(uiColor: .mvmBlack)
enabledBorderColor = Color(uiColor: .mvmBlack)
}
if disabledTextColor == nil && disabledBorderColor == nil {
disabledTextColor = Color(uiColor: .mvmCoolGray6)
disabledBorderColor = Color(uiColor: .mvmCoolGray6)
}
enabledTextColor_inverted = Color(uiColor: .mvmWhite)
enabledBorderColor_inverted = Color(uiColor: .mvmWhite)
disabledTextColor_inverted = Color(uiColor: .mvmCoolGray6)
disabledBorderColor_inverted = Color(uiColor: .mvmCoolGray6)
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
enabledFillColor_inverted = Color(uiColor: UIColor.clear)
enabledBorderColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
disabledTextColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
}
public func setFacade(by style: Styler.Button.Style) {
@ -183,6 +191,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
case disabledFillColor
case disabledTextColor
case disabledBorderColor
case width
}
//--------------------------------------------------
@ -192,7 +201,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
title = try typeContainer.decode(String.self, forKey: .title)
@ -206,6 +214,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
if let style = try typeContainer.decodeIfPresent(Styler.Button.Style.self, forKey: .style) {
self.style = style
setFacade(by: style)
} else {
setFacade(by: .primary)
}
if let size = try typeContainer.decodeIfPresent(Styler.Button.Size.self, forKey: .size) {
@ -247,6 +257,9 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) {
self.disabledBorderColor = disabledBorderColor
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
}
open func encode(to encoder: Encoder) throws {
@ -256,7 +269,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encode(enabled, forKey: .enabled)
try container.encode(inverted, forKey: .inverted)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
@ -268,5 +281,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(size, forKey: .size)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeIfPresent(width, forKey: .width)
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
@objcMembers open class Link: Button {
//--------------------------------------------------
@ -28,8 +28,8 @@ import UIKit
// x should be according to the text, not the button
let x = textRect.origin.x
// Line is 1 point below the text
let y = textRect.origin.y + textRect.size.height + 1
// Line is 0 point below the text
let y = textRect.origin.y + textRect.size.height
context.move(to: CGPoint(x: x, y: y))
context.addLine(to: CGPoint(x: x + textRect.size.width, y: y))
@ -38,7 +38,7 @@ import UIKit
open override var intrinsicContentSize: CGSize {
guard let size = titleLabel?.intrinsicContentSize else { return super.intrinsicContentSize }
return CGSize(width: size.width, height: size.height + 2)
return CGSize(width: size.width, height: size.height + 1)
}
//--------------------------------------------------
@ -56,7 +56,9 @@ import UIKit
}
setTitleColor((model.inverted ? model.enabledColor_inverted : model.enabledColor).uiColor, for: .normal)
setTitleColor((model.inverted ? model.disabledColor_inverted : model.disabledColor).uiColor, for: .disabled)
setTitleColor((model.inverted ? model.activeColor_inverted : model.activeColor).uiColor, for: .highlighted)
isEnabled = model.enabled
titleLabel?.font = model.getFont(model.size)
set(with: model.action, delegateObject: delegateObject, additionalData: additionalData)
}
@ -68,21 +70,15 @@ extension Link {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
var width = size
if MVMCoreGetterUtility.fequal(a: Float.leastNormalMagnitude, b: Float(size)) {
width = MVMCoreUIUtility.getWidth()
}
titleLabel?.font = MFStyler.fontB2(forWidth: width)
}
open override func setupView() {
super.setupView()
backgroundColor = .clear
contentMode = .redraw
setTitleColor(.mvmBlack, for: .normal)
setTitleColor(.mvmCoolGray6, for: .disabled)
setTitleColor(VDSColor.elementsPrimaryOnlight, for: .normal)
setTitleColor(VDSColor.interactiveDisabledOnlight, for: .disabled)
setTitleColor(VDSColor.interactiveActiveOnlight, for: .highlighted)
titleLabel?.numberOfLines = 1
titleLabel?.lineBreakMode = .byTruncatingTail
titleLabel?.textAlignment = .left

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -22,11 +22,15 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
public var accessibilityText: String?
public var action: ActionModelProtocol
public var enabled = true
public var enabledColor = Color(uiColor: .mvmBlack)
public var enabledColor_inverted = Color(uiColor: .mvmWhite)
public var disabledColor = Color(uiColor: .mvmCoolGray6)
public var disabledColor_inverted = Color(uiColor: .mvmCoolGray10)
public var enabledColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
public var enabledColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
public var disabledColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
public var disabledColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
public var activeColor = Color(uiColor: VDSColor.interactiveActiveOnlight)
public var activeColor_inverted = Color(uiColor: VDSColor.interactiveActiveOndark)
public var inverted = false
public var size:linkFontSize = linkFontSize.small
//--------------------------------------------------
// MARK: - Initializer
@ -53,9 +57,30 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
case enabledColor_inverted
case disabledColor
case disabledColor_inverted
case activeColor
case activeColor_inverted
case inverted
case size
}
public enum linkFontSize: String, Codable {
case small
case large
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------
func getFont(_ type: linkFontSize) -> UIFont {
switch type {
case .small:
return MFStyler.fontRegularBodySmall()
case .large:
return MFStyler.fontRegularBodyLarge()
}
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
@ -92,6 +117,17 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) {
self.disabledColor_inverted = disabledColor_inverted
}
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
self.activeColor = activeColor
}
if let activeColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor_inverted) {
self.activeColor_inverted = activeColor_inverted
}
if let size = try typeContainer.decodeIfPresent(linkFontSize.self, forKey: .size) {
self.size = size
}
}
public func encode(to encoder: Encoder) throws {
@ -107,5 +143,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
try container.encode(enabledColor_inverted, forKey: .enabledColor_inverted)
try container.encode(disabledColor, forKey: .disabledColor)
try container.encode(disabledColor_inverted, forKey: .disabledColor_inverted)
try container.encode(activeColor, forKey: .activeColor)
try container.encode(activeColor_inverted, forKey: .activeColor_inverted)
try container.encodeIfPresent(size, forKey: .size)
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
//--------------------------------------------------
@ -23,21 +23,29 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
/// Need to re-style on set.
open override var isEnabled: Bool {
didSet { style() }
didSet { style(with: buttonModel) }
}
open var buttonSize: Styler.Button.Size = .standard {
didSet { buttonModel?.size = buttonSize }
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
public var widthConstraint: NSLayoutConstraint?
public var minimumWidthConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@objc public convenience init(asPrimaryButton isPrimary: Bool, makeTiny istiny: Bool) {
self.init()
buttonSize = istiny ? .tiny : .standard
isPrimary ? stylePrimary() : styleSecondary()
let model = ButtonModel(with: "", action: ActionNoopModel())
model.style = isPrimary ? .primary : .secondary
model.size = istiny ? .tiny : .standard
self.init(model: model, nil, nil)
}
//--------------------------------------------------
@ -68,39 +76,26 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
/// The primary styling for a button. Should be used for main buttons
public func stylePrimary() {
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmWhite
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmWhite
layer.borderWidth = 0
backgroundColor = isEnabled ? buttonModel?.enabledColors.fill ?? .mvmBlack : buttonModel?.disabledColors.fill ?? .mvmCoolGray6
let buttonModel = ButtonModel(primaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// The secondary styling for a button. Should be used for secondary buttons
public func styleSecondary() {
enabledTitleColor = buttonModel?.enabledColors.text ?? .mvmBlack
disabledTitleColor = buttonModel?.disabledColors.text ?? .mvmCoolGray6
backgroundColor = .clear
layer.borderWidth = 1
borderColor = isEnabled ? buttonModel?.enabledColors.border ?? .mvmBlack : buttonModel?.disabledColors.border ?? .mvmCoolGray6
let buttonModel = ButtonModel(secondaryButtonWith: "", action: ActionNoopModel())
style(with: buttonModel)
}
/// Styles the button based on the model style
private func style() {
private func style(with model: ButtonModel?) {
switch buttonModel?.style {
case .secondary:
styleSecondary()
default:
stylePrimary()
}
layer.borderWidth = model?.style == .secondary ? 1 : 0
if let titleColor = buttonModel?.enabledColors.text {
if let titleColor = model?.enabledColors.text {
enabledTitleColor = titleColor
}
if let disabledTitleColor = buttonModel?.disabledColors.text {
if let disabledTitleColor = model?.disabledColors.text {
self.disabledTitleColor = disabledTitleColor
}
@ -110,72 +105,46 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
#endif
if isEnabled {
if let fillColor = buttonModel?.enabledColors.fill {
if let fillColor = model?.enabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.enabledColors.border {
layer.borderWidth = 1
if let borderColor = model?.enabledColors.border {
self.borderColor = borderColor
}
} else {
if let fillColor = buttonModel?.disabledColors.fill {
if let fillColor = model?.disabledColors.fill {
backgroundColor = fillColor
}
if let borderColor = buttonModel?.disabledColors.border {
layer.borderWidth = 1
if let borderColor = model?.disabledColors.border {
self.borderColor = borderColor
}
}
}
private func getInnerPadding() -> CGFloat {
getHeight() / 2.0
buttonSize.getHeight() / 2.0
}
private func getHeight() -> CGFloat {
PillButton.getHeight(for: buttonSize, size: size)
}
public static func getHeight(for buttonSize: Styler.Button.Size?, size: CGFloat) -> CGFloat {
private func getContentEdgeInsets() -> UIEdgeInsets {
var verticalPadding = 0.0
var horizontalPadding = 0.0
switch buttonSize {
case .standard:
verticalPadding = Padding.Three
horizontalPadding = Padding.Five
break
case .small:
verticalPadding = Padding.Two
horizontalPadding = Padding.Four
break
case .tiny:
let tinyHeight = Styler.Button.Size.tiny.getHeight()
return MFSizeObject(standardSize: tinyHeight,
standardiPadPortraitSize: 34,
iPadProLandscapeSize: 38)?.getValueBased(onSize: size) ?? tinyHeight
default:
let standardHeight = Styler.Button.Size.standard.getHeight()
return MFSizeObject(standardSize: standardHeight,
standardiPadPortraitSize: 46,
iPadProLandscapeSize: 50)?.getValueBased(onSize: size) ?? standardHeight
}
}
private func getMinimumWidth() -> CGFloat {
switch buttonSize {
case .tiny:
return MFSizeObject(standardSize: 49,
standardiPadPortraitSize: 90,
iPadProLandscapeSize: 135)?.getValueBased(onSize: size) ?? 49
default: return 151
}
}
open override var intrinsicContentSize: CGSize {
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())
verticalPadding = Padding.One
horizontalPadding = Padding.Two
break
}
return UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}
//--------------------------------------------------
@ -187,6 +156,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? ButtonModel else { return }
setTitle(model.title, for: .normal)
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
@ -206,24 +176,44 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
PillButton.getHeight(for: (model as? ButtonModel)?.size, size: MVMCoreUIUtility.getWidth())
return (model as? ButtonModel)?.size?.getHeight()
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
self.size = size
invalidateIntrinsicContentSize()
switch buttonSize {
case .tiny:
titleLabel?.font = MFFonts.mfFont75Bd(11 * (intrinsicContentSize.height / Styler.Button.Size.tiny.getHeight()))
default:
titleLabel?.font = MFFonts.mfFont75Bd(13 * (intrinsicContentSize.height / Styler.Button.Size.standard.getHeight()))
titleLabel?.font = Styler.Font.BoldMicro.getFont(false)
case .small:
titleLabel?.font = Styler.Font.BoldBodySmall.getFont(false)
case .standard:
titleLabel?.font = Styler.Font.BoldBodyLarge.getFont(false)
}
layer.cornerRadius = getInnerPadding()
contentEdgeInsets = getContentEdgeInsets()
if let contraint = buttonModel?.width {
if widthConstraint == nil {
widthConstraint = widthAnchor.constraint(equalToConstant: contraint)
} else if widthConstraint?.constant != contraint {
widthConstraint?.constant = contraint
}
widthConstraint?.isActive = true
minimumWidthConstraint?.isActive = false
} else {
if minimumWidthConstraint == nil {
minimumWidthConstraint = widthAnchor.constraint(greaterThanOrEqualToConstant: buttonSize.minimumWidth())
} else {
minimumWidthConstraint?.constant = buttonSize.minimumWidth()
}
minimumWidthConstraint?.isActive = true
widthConstraint?.isActive = false
}
}
open override func setupView() {

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class TagModel: MoleculeModelProtocol {
public static var identifier: String = "tag"
@ -27,6 +28,14 @@ import Foundation
}
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(label: LabelModel) {
self.label = label
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
label = try typeContainer.decode(LabelModel.self, forKey: .label)

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class TagsModel: MoleculeModelProtocol {
public static var identifier: String = "tags"
@ -19,6 +20,14 @@ import Foundation
case tags
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with tags: [TagModel]) {
self.tags = tags
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tags = try typeContainer.decode([TagModel].self, forKey: .tags)

View File

@ -38,6 +38,14 @@
public var displayFormat: String?
public var displayMask: String?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public override init(with text: String){
super.init(with: text)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------

View File

@ -5,7 +5,7 @@
// Created by Lekshmi S on 07/09/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
@ -38,6 +38,11 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() { }
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,6 +5,7 @@
// Created by Dhamodaram Nandi on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioBoxModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -43,6 +44,14 @@
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(text: String) {
self.text = text
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,6 +5,7 @@
// Created by Dhamodaram Nandi on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
@ -52,6 +53,14 @@
case groupName
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with boxes: [RadioBoxModel]){
self.boxes = boxes
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,7 +5,7 @@
// Created by Scott Pfeil on 4/17/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioSwatchModel: MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -42,6 +42,12 @@
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,7 +5,7 @@
// Created by Lekshmi S on 31/03/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class RadioSwatchesModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
@ -50,6 +50,14 @@
case readOnly
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with swatches: [RadioSwatchModel]){
self.swatches = swatches
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class CaretViewModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -38,6 +38,12 @@ import Foundation
case inverted
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -20,6 +20,8 @@ open class BarsIndicatorView: CarouselIndicator {
static let width: CGFloat = 24
static let selectedHeight: CGFloat = 4
static let unselectedHeight: CGFloat = 1
static let selectedCornerRadius: CGFloat = 2
static let unselectedCornerRadius: CGFloat = 0.5
var constraint: NSLayoutConstraint?
@ -38,6 +40,7 @@ open class BarsIndicatorView: CarouselIndicator {
override func setupView() {
super.setupView()
isAccessibilityElement = true
layer.cornerRadius = 2
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
widthAnchor.constraint(equalToConstant: BarsIndicatorView.IndicatorBar.width).isActive = true
accessibilityTraits = .button
@ -52,7 +55,7 @@ open class BarsIndicatorView: CarouselIndicator {
stackView.axis = .horizontal
stackView.alignment = .bottom
stackView.distribution = .equalSpacing
stackView.spacing = 6
stackView.spacing = 4
return stackView
}()
@ -189,6 +192,7 @@ open class BarsIndicatorView: CarouselIndicator {
let bar = IndicatorBar()
setAccessibilityLabel(view: bar, index: index)
bar.backgroundColor = isEnabled ? (index == currentIndex ? currentIndicatorColor : indicatorColor) : disabledIndicatorColor
bar.layer.cornerRadius = index == currentIndex ? BarsIndicatorView.IndicatorBar.selectedCornerRadius : BarsIndicatorView.IndicatorBar.unselectedCornerRadius
let barHeight = index == currentIndex ? BarsIndicatorView.IndicatorBar.selectedHeight : BarsIndicatorView.IndicatorBar.unselectedHeight
let heightConstraint = bar.heightAnchor.constraint(equalToConstant: barHeight)
heightConstraint.isActive = true
@ -251,6 +255,7 @@ open class BarsIndicatorView: CarouselIndicator {
barReferences.forEach {
$0.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor
$0.constraint?.constant = IndicatorBar.unselectedHeight
$0.layer.cornerRadius = IndicatorBar.unselectedCornerRadius
}
balanceBarCount(numberOfPages - barReferences.count)
@ -260,8 +265,10 @@ open class BarsIndicatorView: CarouselIndicator {
let expression = { [self] in
barReferences[previousIndex].backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor
barReferences[previousIndex].constraint?.constant = IndicatorBar.unselectedHeight
barReferences[previousIndex].layer.cornerRadius = IndicatorBar.unselectedCornerRadius
barReferences[newIndex].backgroundColor = isEnabled ? currentIndicatorColor : disabledIndicatorColor
barReferences[newIndex].constraint?.constant = IndicatorBar.selectedHeight
barReferences[newIndex].layer.cornerRadius = IndicatorBar.selectedCornerRadius
layoutIfNeeded()
}

View File

@ -5,7 +5,7 @@
// Created by Kevin Christiano on 1/30/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
open class CarouselIndicator: Control, CarouselPageControlProtocol {
//--------------------------------------------------
@ -71,13 +71,22 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
}
public var disabledIndicatorColor: UIColor {
get { carouselIndicatorModel?.disabledIndicatorColor.uiColor ?? .mvmCoolGray3 }
set { carouselIndicatorModel?.disabledIndicatorColor = Color(uiColor: newValue) }
get {
guard let model = carouselIndicatorModel else { return VDSColor.elementsSecondaryOnlight }
return model.inverted ? model.disabledIndicatorColor_inverted.uiColor : model.disabledIndicatorColor.uiColor
}
set {
if let model = carouselIndicatorModel, model.inverted {
model.disabledIndicatorColor_inverted = Color(uiColor: newValue)
} else {
carouselIndicatorModel?.disabledIndicatorColor = Color(uiColor: newValue)
}
}
}
public var indicatorColor: UIColor {
get {
guard let model = carouselIndicatorModel else { return .mvmBlack }
guard let model = carouselIndicatorModel else { return VDSColor.elementsPrimaryOnlight}
return model.inverted ? model.indicatorColor_inverted.uiColor : model.indicatorColor.uiColor
}
set {

View File

@ -7,7 +7,7 @@
//
import Foundation
import VDSColorTokens
open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
//--------------------------------------------------
@ -30,9 +30,10 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
public var accessibilityHasSlidesInsteadOfPage: Bool = false
public var enabled: Bool = true
public var disabledIndicatorColor: Color = Color(uiColor: .mvmCoolGray3)
public var indicatorColor: Color = Color(uiColor: .mvmBlack)
public var indicatorColor_inverted: Color = Color(uiColor: .mvmWhite)
public var disabledIndicatorColor: Color = Color(uiColor: VDSColor.elementsSecondaryOnlight)
public var disabledIndicatorColor_inverted: Color = Color(uiColor: VDSColor.elementsSecondaryOndark)
public var indicatorColor: Color = Color(uiColor: VDSColor.elementsPrimaryOnlight)
public var indicatorColor_inverted: Color = Color(uiColor: VDSColor.elementsPrimaryOndark)
public var position: CGFloat?
/// Allows sendActions() to trigger even if index is already at min/max index.

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
public enum CheckboxPosition: String, Codable {
case center
@ -16,9 +17,19 @@ public enum CheckboxPosition: String, Codable {
@objcMembers public class CheckboxLabelModel: MoleculeModelProtocol {
public static var identifier: String = "checkboxLabel"
public var moleculeName: String
public var moleculeName: String = CheckboxLabelModel.identifier
public var backgroundColor: Color?
public var checkboxAlignment: CheckboxPosition?
public var checkbox: CheckboxModel
public var label: LabelModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(checkbox: CheckboxModel, label: LabelModel) {
self.checkbox = checkbox
self.label = label
}
}

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class DashLineModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -43,6 +43,12 @@ import Foundation
case isHidden
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - codec
//--------------------------------------------------

View File

@ -256,21 +256,19 @@ public typealias ActionBlock = () -> ()
* appropriately called.
* Only other reference found of issue: https://www.thetopsites.net/article/58142205.shtml
*/
if #available(iOS 13, *) {
if let attributedText = attributedText, let text = text, !text.isEmpty {
let attributedString = NSMutableAttributedString(string: text)
let range = NSRange(location: 0, length: text.count)
for attribute in attributedText.attributes(at: 0, effectiveRange: nil) {
if attribute.key == .underlineStyle {
attributedString.addAttribute(.underlineStyle, value: 0, range: range)
}
if attribute.key == .strikethroughStyle {
attributedString.addAttribute(.strikethroughStyle, value: 0, range: range)
}
if let attributedText = attributedText, let text = text, !text.isEmpty {
let attributedString = NSMutableAttributedString(string: text)
let range = NSRange(location: 0, length: text.count)
for attribute in attributedText.attributes(at: 0, effectiveRange: nil) {
if attribute.key == .underlineStyle {
attributedString.addAttribute(.underlineStyle, value: 0, range: range)
}
if attribute.key == .strikethroughStyle {
attributedString.addAttribute(.strikethroughStyle, value: 0, range: range)
}
self.attributedText = attributedString
}
self.attributedText = attributedString
}
hero = labelModel.hero
@ -297,8 +295,8 @@ public typealias ActionBlock = () -> ()
accessibilityLabel = accessibilityText
}
if let fontStyle = labelModel.fontStyle?.rawValue {
MFStyler.styleLabel(self, withStyle: fontStyle, genericScaling: false)
if let fontStyle = labelModel.fontStyle {
fontStyle.styleLabel(self, genericScaling: false)
standardFontSize = font.pointSize
} else {
let fontSize = labelModel.fontSize
@ -430,7 +428,7 @@ public typealias ActionBlock = () -> ()
label.accessibilityLabel = json?.optionalStringForKey("accessibilityText")
if let fontStyle = json?.optionalStringForKey("fontStyle") {
MFStyler.styleLabel(label, withStyle: fontStyle, genericScaling: mvmLabel == nil)
MFStyler.style(label: label, styleString: fontStyle, genericScaling: mvmLabel == nil)
mvmLabel?.standardFontSize = label.font.pointSize
} else {
let fontSize = json?["fontSize"] as? CGFloat
@ -492,7 +490,7 @@ public typealias ActionBlock = () -> ()
case "font":
if let fontStyle = attribute.optionalStringForKey("style") {
let styles = MFStyler.styleGetAttributedString("0", withStyle: fontStyle, genericScaling: mvmLabel == nil)
let styles = MFStyler.getAttributedString(for: "0", styleString: fontStyle, genericScaling: mvmLabel == nil)
attributedString.removeAttribute(.font, range: range)
attributedString.removeAttribute(.foregroundColor, range: range)
attributedString.addAttributes(styles.attributes(at: 0, effectiveRange: nil), range: range)
@ -533,8 +531,7 @@ public typealias ActionBlock = () -> ()
//------------------------------------------------------
public func setFontStyle(_ fontStyle: Styler.Font, _ scale: Bool = true) {
font = fontStyle.getFont(false)
textColor = .mvmBlack
fontStyle.styleLabel(self, genericScaling: false)
setScale(scale)
}

View File

@ -18,6 +18,14 @@
var name: String?
var size: CGFloat?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(_ location: Int, _ length: Int) {
super.init(location, length)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -18,6 +18,14 @@ class LabelAttributeImageModel: LabelAttributeModel {
var name: String?
var URL: String?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(_ location: Int, _ length: Int) {
super.init(location, length)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -18,10 +18,6 @@ import UIKit
get { return model as? LineModel }
}
var lineBackgroundColor: Color? {
return (lineModel?.inverted ?? false) ? lineModel?.backgroundColor_inverted : lineModel?.backgroundColor
}
//--------------------------------------------------
// MARK: - Constraints
//--------------------------------------------------
@ -50,28 +46,36 @@ import UIKit
addLine(to: view, edge: edge, useMargin: useMargin)
}
public init() {
super.init(frame: .zero)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public override init(frame: CGRect) {
super.init(frame: frame)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
model = LineModel(type: .secondary)
setStyle(.secondary)
}
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.init(model: model, delegateObject, additionalData)
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
open func setStyle(_ style: LineModel.Style) {
switch style {
case .standard:
updateLineConstraints(constant: 1)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmCoolGray3
case .thin:
updateLineConstraints(constant: 1)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .medium:
updateLineConstraints(constant: 2)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .heavy:
updateLineConstraints(constant: 4)
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
case .none:
updateLineConstraints(constant: 0)
}
lineModel?.type = style
backgroundColor = lineModel?.backgroundColor?.uiColor
updateLineConstraints(constant: lineModel?.thickness ?? 1)
}
open func shouldBeVisible() -> Bool {
@ -90,12 +94,10 @@ import UIKit
open override func setupView() {
super.setupView()
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
heightConstraint?.isActive = true
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
widthConstraint?.isActive = false
setStyle(.standard)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
@ -107,23 +109,11 @@ import UIKit
}
open override func reset() {
setStyle(.standard)
setStyle(.secondary)
}
public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
guard let type = (model as? LineModel)?.type else { return 1 }
switch type {
case .none:
return 0
case .medium:
return 2
case .heavy:
return 4
default:
return 1
}
return (model as? LineModel)?.thickness ?? 1
}
}

View File

@ -7,7 +7,7 @@
//
import UIKit
import VDSColorTokens
@objcMembers public class LineModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -30,13 +30,17 @@ import UIKit
/**
The style of the line:
- standard (1 height, silver)
- thin (1 height, black)
- secondary (1 height, silver)
- primary (1 height, black)
- standard (1 height, silver) - deprecated
- thin (1 height, black) - deprecated
- medium (2 height, black)
- heavy (4 height, black)
- none (hidden)
*/
public enum Style: String, Codable {
case secondary
case primary
case standard
case thin
case medium
@ -49,13 +53,47 @@ import UIKit
//--------------------------------------------------
public static var identifier: String = "line"
public var type: Style = .standard
public var type: Style = .secondary
public var frequency: Frequency? = .allExceptTop
//TODO: use color insted of backgroundColor. Needs server changes
// public var color: Color?
public var backgroundColor: Color?
public var backgroundColor_inverted: Color = Color(uiColor: .mvmWhite)
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if inverted {
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray20) }
return Color(uiColor: VDSColor.elementsPrimaryOndark)
}
if type == .secondary || type == .standard { return Color(uiColor: VDSColor.paletteGray85) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_backgroundColor = newValue
}
}
private var _thickness: CGFloat?
public var thickness: CGFloat {
get {
if let thickness = _thickness { return thickness }
switch type {
case .heavy:
return 4
case .medium:
return 2
case .none:
return 0
default:
return 1
}
}
set {
_thickness = newValue
}
}
public var inverted: Bool = false
// Use this to show vertical line
@ -90,6 +128,7 @@ import UIKit
case frequency
case inverted
case useVerticalLine
case thickness
}
//--------------------------------------------------
@ -111,12 +150,9 @@ import UIKit
self.inverted = inverted
}
if let backgroundColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor_inverted) {
self.backgroundColor_inverted = backgroundColor_inverted
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine)
_thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
}
public func encode(to encoder: Encoder) throws {
@ -125,8 +161,8 @@ import UIKit
try container.encode(type, forKey: .type)
try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(frequency, forKey: .frequency)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(backgroundColor_inverted, forKey: .backgroundColor_inverted)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(useVerticalLine, forKey: .useVerticalLine)
try container.encodeIfPresent(_thickness, forKey: .thickness)
}
}

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
open class LoadingSpinnerModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -32,6 +32,12 @@ open class LoadingSpinnerModel: MoleculeModelProtocol {
case diameter
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,6 +5,7 @@
// Created by Lekshmi S on 15/09/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
open class StarModel: MoleculeModelProtocol {
@ -30,6 +31,12 @@ open class StarModel: MoleculeModelProtocol {
case size
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -5,6 +5,7 @@
// Created by Lekshmi S on 21/09/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class StarsModel: MoleculeModelProtocol {
@ -34,6 +35,14 @@
case size
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with stars: [StarModel]) {
self.stars = stars
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -14,7 +14,7 @@ open class VisibleBehaviorForVideoModel: PageBehaviorModelProtocol {
public var shouldAllowMultipleInstances: Bool = true
public weak var videoModel: VideoModel?
init(with videoModel: VideoModel) {
public init(with videoModel: VideoModel) {
self.videoModel = videoModel
}
}

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class WebViewModel: MoleculeModelProtocol {
public static var identifier: String = "webview"
@ -30,6 +31,12 @@ import Foundation
case borderColor
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)

View File

@ -49,125 +49,28 @@ import UIKit
}
heightConstraint?.constant = graphObject.diameter
// iOS 12 uses the conic gradient and a mask for simplicity.
if #available(iOS 12, *) {
let gradient = CAGradientLayer()
gradient.type = .conic
gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
gradient.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
gradient.colors = graphObject.colors.map({ (color) -> CGColor in
return color.cgColor
})
gradientLayer = gradient
layer.addSublayer(gradient)
let center = CGPoint(x: gradient.bounds.midX, y: gradient.bounds.midY)
let radius = (graphObject.diameter - graphObject.lineWidth) / 2.0
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: (3 / 2 * .pi), endAngle: -(1 / 2 * .pi), clockwise: false)
let mask = CAShapeLayer()
mask.fillColor = UIColor.clear.cgColor
mask.strokeColor = UIColor.white.cgColor
mask.lineWidth = graphObject.lineWidth
mask.path = path.cgPath
gradient.mask = mask
return
}
let gradient = CAGradientLayer()
gradient.type = .conic
gradient.startPoint = CGPoint(x: 0.5, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
gradient.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
gradient.colors = graphObject.colors.map({ (color) -> CGColor in
return color.cgColor
})
gradientLayer = gradient
layer.addSublayer(gradient)
//create circle path
let radius = graphObject.diameter / 2.0
//begin point will be at the bottom, clockwise direction
let path = UIBezierPath(arcCenter: CGPoint(x: radius
, y: radius), radius: radius - graphObject.lineWidth/2.0, startAngle: CGFloat(Wheel.getPiValue(90.0)), endAngle: CGFloat(Wheel.getPiValue(90.0 + 360.0)), clockwise: true)
path.lineWidth = graphObject.lineWidth
let circleLayer = CAShapeLayer()
circleLayer.path = path.cgPath
circleLayer.lineCap = .round
circleLayer.lineWidth = graphObject.lineWidth
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.strokeColor = UIColor.black.cgColor
//create gradient layer
let gradientLayer = createGradientLayer(graphObject)
gradientLayer.mask = circleLayer
layer.addSublayer(gradientLayer)
self.gradientLayer = gradientLayer
let center = CGPoint(x: gradient.bounds.midX, y: gradient.bounds.midY)
let radius = (graphObject.diameter - graphObject.lineWidth) / 2.0
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: (3 / 2 * .pi), endAngle: -(1 / 2 * .pi), clockwise: false)
let mask = CAShapeLayer()
mask.fillColor = UIColor.clear.cgColor
mask.strokeColor = UIColor.white.cgColor
mask.lineWidth = graphObject.lineWidth
mask.path = path.cgPath
gradient.mask = mask
}
/*
create three gradient layer for circle layout.
_____________
| | top layer for smooth gradient
-------------
| | |
| | |
| | |
-------------
*/
func createGradientLayer(_ graphObject: WheelModel) -> CALayer {
let containLayer = CALayer()
containLayer.frame = CGRect(x: 0, y: 0, width: graphObject.diameter, height: graphObject.diameter)
let radius = graphObject.diameter / 2.0
//create graident layers
guard graphObject.colors.count > 1 else {
containLayer.backgroundColor = graphObject.colors.first?.cgColor
return containLayer
}
var topGradientHeight : CGFloat = 0.0
var leftColors = graphObject.colors.prefix(through: graphObject.colors.count/2)
let rightColors = graphObject.colors.suffix(from: graphObject.colors.count/2)
// make the top layer higher than line width for smooth look
topGradientHeight = min(max(graphObject.lineWidth, 1.0/(1.0+CGFloat(graphObject.colors.count))*graphObject.diameter), graphObject.diameter)
let topLayer = CAGradientLayer()
topLayer.frame = CGRect(x: 0.0, y: 0.0, width: graphObject.diameter, height: topGradientHeight)
//make the graident edge more smoothy
topLayer.startPoint = CGPoint(x: 0.25, y: 0.0)
topLayer.endPoint = CGPoint(x: 0.75, y: 0.0)
//if number of colors is even, need to display gradient layer, otherwise make top layer as solid color layer
if graphObject.colors.count % 2 == 0 {
leftColors.removeLast()
let firstColor = leftColors.last!.cgColor
let secondColor = rightColors.first!.cgColor
topLayer.colors = [firstColor, secondColor]
} else {
topLayer.backgroundColor = leftColors.last?.cgColor
}
containLayer.addSublayer(topLayer)
let leftLayer = CAGradientLayer()
leftLayer.frame = CGRect(x: 0, y: topGradientHeight, width: radius, height: graphObject.diameter - topGradientHeight)
leftLayer.startPoint = CGPoint(x: 0, y: 1)
leftLayer.endPoint = CGPoint(x: 0, y: 0)
//count of graidentLayer.colors must be bigger than 1, otherwise set backgroundColor
if leftColors.count > 1 {
leftLayer.colors = leftColors.map({ (color) -> CGColor in
return color.cgColor
})
} else {
leftLayer.backgroundColor = leftColors.first?.cgColor
}
containLayer.addSublayer(leftLayer)
let rightLayer = CAGradientLayer()
rightLayer.frame = CGRect(x: radius, y: topGradientHeight, width: radius, height: graphObject.diameter - topGradientHeight)
rightLayer.startPoint = CGPoint(x: 0, y: 0)
rightLayer.endPoint = CGPoint(x: 0, y: 1)
if rightColors.count > 1 {
rightLayer.colors = rightColors.map({ (color) -> CGColor in
return color.cgColor
})
} else {
rightLayer.backgroundColor = rightColors.first?.cgColor
}
containLayer.addSublayer(rightLayer)
return containLayer
}
//MARK: MVMCoreUIViewConstrainingProtocol
public func needsToBeConstrained() -> Bool {
return true

View File

@ -0,0 +1,59 @@
//
// UIImageRenderingMode+Extension.swift
// MVMCoreUI
//
// Created by Nadigadda, Sumanth on 24/03/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
enum RenderingModeError: Error {
case notAnRenderingMode
}
extension UIImage.RenderingMode: RawRepresentable {
init?(rawValue: String) {
switch rawValue {
case "alwaysOriginal":
self = .alwaysOriginal
case "alwaysTemplate":
self = .alwaysTemplate
case "automatic":
self = .automatic
default:
return nil
}
}
var rawValueString: String {
switch self {
case .alwaysOriginal:
return "alwaysOriginal"
case .alwaysTemplate:
return "alwaysTemplate"
case .automatic:
return "automatic"
@unknown default:
return ""
}
}
}
extension UIImage.RenderingMode: Codable {
public init(from decoder: Decoder) throws {
let typeContainer = try decoder.singleValueContainer()
let string = try typeContainer.decode(String.self)
guard let renderingMode = UIImage.RenderingMode(rawValue: string) else {
throw RenderingModeError.notAnRenderingMode
}
self = renderingMode
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValueString)
}
}

View File

@ -0,0 +1,123 @@
//
// TitleLockup.swift
// MVMCoreUI
//
// Created by Nadigadda, Sumanth on 04/05/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
@objcMembers open class TitleLockup: View {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
public let eyebrow = Label(fontStyle: .RegularBodySmall)
public let title = Label(fontStyle: .RegularBodySmall)
public let subTitle = Label(fontStyle: .RegularBodySmall)
public lazy var stack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [eyebrow, title, subTitle])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical
return stack
}()
var castModel: TitleLockupModel? {
get { return model as? TitleLockupModel }
}
//--------------------------------------------------
// MARK: - Initialization
//--------------------------------------------------
public convenience init() {
self.init(frame: .zero)
}
//--------------------------------------------------
// MARK: - MFViewProtocol
//--------------------------------------------------
open override func setupView() {
super.setupView()
addSubview(stack)
NSLayoutConstraint.constraintPinSubview(toSuperview: stack)
}
open override func updateView(_ size: CGFloat) {
super.updateView(size)
stack.updateView(size)
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func reset() {
super.reset()
stack.reset()
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? TitleLockupModel else { return }
stack.setCustomSpacing(model.defaultEyebrowTitleSpacing(), after: eyebrow)
stack.setCustomSpacing(model.defaultTitleSubTitleSpacing(), after: title)
stack.updateContainedMolecules(with: [model.eyebrow,
model.title,
model.subTitle],
delegateObject, additionalData)
}
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 65
}
//--------------------------------------------------
// MARK: - Accessibility Helpers
//--------------------------------------------------
/// Returns the labels text in one message.
func getAccessibilityMessage() -> String? {
var message = ""
if let eyebrowLabel = eyebrow.text {
message += eyebrowLabel + ", "
}
if let headlineLabel = title.text {
message += headlineLabel + ", "
}
if let bodyLabel = subTitle.text {
message += bodyLabel
}
return message.count > 0 ? message : nil
}
/// Returns an array of the appropriate accessibility elements.
func getAccessibilityElements() -> [Any]? {
var elements: [UIView] = []
if eyebrow.hasText {
elements.append(eyebrow)
}
if title.hasText {
elements.append(title)
}
if subTitle.hasText {
elements.append(subTitle)
}
return elements.count > 0 ? elements : nil
}
}

View File

@ -0,0 +1,215 @@
//
// TitleLockupModel.swift
// MVMCoreUI
//
// Created by Nadigadda, Sumanth on 04/05/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "titleLockup"
public var moleculeName: String = TitleLockupModel.identifier
public var eyebrow: LabelModel?
public var title: LabelModel
public var subTitle: LabelModel?
public var alignment: Alignment = .left {
didSet {
///Updating the text alignment for all labels
if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) {
eyebrow?.textAlignment = textAlignment
title.textAlignment = textAlignment
subTitle?.textAlignment = textAlignment
}
}
}
public var inverted: Bool = false {
didSet {
///Updating the text color
eyebrow?.textColor = titleColor
title.textColor = titleColor
subTitle?.textColor = subTitleColor
}
}
private var _backgroundColor: Color?
public var backgroundColor: Color? {
get {
return inverted ? Color(uiColor: VDSColor.backgroundPrimaryDark) : Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
public var titleColor: Color? {
return inverted ? Color(uiColor: VDSColor.elementsPrimaryOndark) : Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
public var subTitleColor: Color? {
return inverted ? Color(uiColor: VDSColor.elementsSecondaryOndark) : Color(uiColor: VDSColor.elementsSecondaryOnlight)
}
public var children: [MoleculeModelProtocol] {
[eyebrow, title, subTitle].compactMap { (molecule: MoleculeModelProtocol?) in molecule }
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(eyebrow: LabelModel? = nil, title: LabelModel, subTitle: LabelModel? = nil) throws {
self.eyebrow = eyebrow
self.title = title
self.subTitle = subTitle
updateLabelAttributes()
}
//--------------------------------------------------
// MARK: - Enum
//--------------------------------------------------
public enum Alignment: String, Codable {
case left
case center
}
//--------------------------------------------------
// MARK: - Styling
//--------------------------------------------------
/// Returns the default fontStyle for the subtitle, based on the title fontStyle.
func defaultSubtitleFontStyle() -> Styler.Font {
switch title.fontStyle {
case .RegularTitleXLarge, .RegularTitle2XLarge, .RegularFeatureXSmall:
return .RegularBodyLarge
case .RegularFeatureSmall, .RegularFeatureMedium:
return .RegularTitleLarge
default:
return .RegularBodySmall
}
}
/// Returns the default spacing between the eyebrow and title, based on the title fontStyle.
func defaultEyebrowTitleSpacing() -> CGFloat {
switch title.fontStyle {
case .RegularTitleXLarge, .RegularTitle2XLarge, .RegularFeatureXSmall, .RegularFeatureSmall:
return Padding.Three
case .RegularFeatureMedium:
return subTitle?.fontStyle == .RegularBodyLarge ? Padding.Three : Padding.Four
default:
return Padding.Two
}
}
/// Returns the default spacing between the title and subTitle, based on the title fontStyle.
func defaultTitleSubTitleSpacing() -> CGFloat {
switch title.fontStyle {
case .RegularTitleXLarge:
return Padding.Three
case .RegularTitle2XLarge, .RegularFeatureXSmall, .RegularFeatureSmall:
return Padding.Four
case .RegularFeatureMedium:
return Padding.Five
default:
return Padding.Two
}
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case eyebrow
case title
case subTitle
case inverted
case alignment
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeMolecule(codingKey: .title)
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
subTitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subTitle)
if let newAlignment = try typeContainer.decodeIfPresent(Alignment.self, forKey: .alignment) {
alignment = newAlignment
}
if let invertedStatus = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
inverted = invertedStatus
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
updateLabelAttributes()
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(eyebrow, forKey: .eyebrow)
try container.encodeModel(title, forKey: .title)
try container.encodeIfPresent(subTitle, forKey: .subTitle)
try container.encode(alignment, forKey: .alignment)
try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
}
//--------------------------------------------------
// MARK: - Model updates
//--------------------------------------------------
private func updateLabelAttributes() {
// If subtitle style is not available, will set font style based on the component
if subTitle?.fontStyle == nil {
subTitle?.fontStyle = defaultSubtitleFontStyle()
}
// If eyebrow style is not available, will set font style based on the component. Eyebrow and subtitle share the same font size
if eyebrow?.fontStyle == nil {
eyebrow?.fontStyle = subTitle?.fontStyle
}
// Updating the text color
if eyebrow?.textColor == nil {
eyebrow?.textColor = subTitleColor
}
if title.textColor == nil {
title.textColor = titleColor
}
if subTitle?.textColor == nil {
subTitle?.textColor = subTitleColor
}
// Updating the text alignment for all labels
if let textAlignment = NSTextAlignment(rawValue: alignment.rawValue) {
if eyebrow?.textAlignment == nil {
eyebrow?.textAlignment = textAlignment
}
if title.textAlignment == nil {
title.textAlignment = textAlignment
}
if subTitle?.textAlignment == nil {
subTitle?.textAlignment = textAlignment
}
}
}
}

View File

@ -23,7 +23,7 @@ public class ListThreeColumnInternationalDataDividerModel: ListItemModel, Molecu
// MARK: - Initializers
//------------------------------------------------------
public init (leftLabel: LabelModel, centerLabel: LabelModel, rightLabel: LabelModel) {
public init(leftLabel: LabelModel, centerLabel: LabelModel, rightLabel: LabelModel) {
self.leftLabel = leftLabel
self.centerLabel = centerLabel
self.rightLabel = rightLabel

View File

@ -33,7 +33,7 @@ open class HeaderView: Container {
public override func setupView() {
super.setupView()
line.setStyle(.heavy)
line.setStyle(.none)
addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
@ -43,7 +43,7 @@ open class HeaderView: Container {
// MARK: - MoleculeViewProtocol
open override func reset() {
super.reset()
line.setStyle(.heavy)
line.setStyle(.none)
molecule?.reset()
}

View File

@ -31,7 +31,7 @@ public class MoleculeHeaderView: MoleculeContainer {
public override func setupView() {
super.setupView()
line.setStyle(.heavy)
line.setStyle(.none)
addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
@ -40,7 +40,7 @@ public class MoleculeHeaderView: MoleculeContainer {
open override func reset() {
super.reset()
line.setStyle(.heavy)
line.setStyle(.none)
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {

View File

@ -22,7 +22,7 @@ import Foundation
public override func setupView() {
super.setupView()
line.setStyle(.thin)
line.setStyle(.primary)
contentView.addSubview(line)
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
@ -51,7 +51,7 @@ import Foundation
open override func reset() {
super.reset()
line.setStyle(.thin)
line.setStyle(.primary)
molecule?.reset()
}

View File

@ -14,6 +14,13 @@
public class override var identifier: String { "sectionHeader" }
public var line: LineModel?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(with moleculeModel: MoleculeModelProtocol) {
super.init(with: moleculeModel)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -42,7 +49,7 @@
bottomPadding = PaddingDefaultVerticalSpacing3
}
if line == nil {
line = LineModel(type: .thin)
line = LineModel(type: .primary)
}
}

View File

@ -7,7 +7,7 @@
//
import Foundation
import MVMCore
@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -16,7 +16,17 @@ import Foundation
public static var identifier: String = "radioButtonLabel"
public var backgroundColor: Color?
public var moleculeName: String
public var moleculeName: String = RadioButtonLabelModel.identifier
public var radioButton: RadioButtonModel
public var label: LabelModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(radioButton: RadioButtonModel, label: LabelModel) {
self.radioButton = radioButton
self.label = label
}
}

View File

@ -5,7 +5,7 @@
// Created by Scott Pfeil on 5/28/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
@objcMembers open class TabBar: UITabBar, MoleculeViewProtocol, TabBarProtocol, UITabBarDelegate {
@ -21,7 +21,6 @@
delegate = self
translatesAutoresizingMaskIntoConstraints = false
line.addLine(to: self, edge: .top, useMargin: false)
line.backgroundColor = .mvmCoolGray3
set(with: model, delegateObject, additionalData)
}
@ -34,47 +33,36 @@
self.model = model
// Set appearance
if #available(iOS 13.0, *) {
let appearance = UITabBarAppearance()
appearance.backgroundColor = model.backgroundColor?.uiColor
set(tabItemAppearance: appearance.stackedLayoutAppearance, model: model)
set(tabItemAppearance: appearance.inlineLayoutAppearance, model: model)
set(tabItemAppearance: appearance.compactInlineLayoutAppearance, model: model)
standardAppearance = appearance
} else {
// Fallback on earlier versions
backgroundColor = model.backgroundColor?.uiColor
tintColor = model.selectedColor.uiColor
unselectedItemTintColor = model.unSelectedColor.uiColor
barTintColor = model.backgroundColor?.uiColor
isTranslucent = false
}
let appearance = UITabBarAppearance()
appearance.backgroundColor = model.backgroundColor?.uiColor
set(tabItemAppearance: appearance.stackedLayoutAppearance, model: model)
set(tabItemAppearance: appearance.inlineLayoutAppearance, model: model)
set(tabItemAppearance: appearance.compactInlineLayoutAppearance, model: model)
standardAppearance = appearance
// Add buttons
var tabs: [UITabBarItem] = []
for (index, tab) in model.tabs.enumerated() {
let tabBarItem = UITabBarItem(title: tab.title, image: MVMCoreCache.shared()?.getImageFromRegisteredBundles(tab.image), tag: index)
tabBarItem.accessibilityLabel = tab.accessibilityText
if #available(iOS 13.0, *) {
} else {
tabBarItem.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabBarItem.setTitleTextAttributes([NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)], for: .normal)
}
tabs.append(tabBarItem)
}
setItems(tabs, animated: false)
selectedItem = tabs[model.selectedTab]
guard let lineModel = line.lineModel else { return }
lineModel.inverted = model.style == .dark
line.set(with: lineModel, delegateObject, additionalData)
}
/// Sets the item colors.
@available(iOS 13.0, *)
private func set(tabItemAppearance: UITabBarItemAppearance, model: TabBarModel) {
tabItemAppearance.normal.iconColor = model.unSelectedColor.uiColor
tabItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.unSelectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)]
tabItemAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.unSelectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXBold(10)]
tabItemAppearance.normal.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
tabItemAppearance.selected.iconColor = model.selectedColor.uiColor
tabItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.selectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXRegular(8)]
tabItemAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor: model.selectedColor.uiColor, NSAttributedString.Key.font: MFFonts.mfFontTXBold(10)]
tabItemAppearance.selected.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -3)
}

View File

@ -7,16 +7,55 @@
//
import Foundation
import VDSColorTokens
public class TabBarModel: MoleculeModelProtocol {
open class TabBarModel: MoleculeModelProtocol {
public static var identifier: String = "tabBar"
public var backgroundColor: Color? = Color(uiColor: .white)
public var tabs: [TabBarItemModel]
public var selectedColor = Color(uiColor: .mvmBlack)
public var unSelectedColor = Color(uiColor: .mvmCoolGray6)
open var tabs: [TabBarItemModel]
private var _backgroundColor: Color?
open var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) }
return Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
private var _selectedColor: Color?
open var selectedColor: Color {
get {
if let selectedColor = _selectedColor { return selectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_selectedColor = newValue
}
}
private var _unSelectedColor: Color?
open var unSelectedColor: Color {
get {
if let unSelectedColor = _unSelectedColor { return unSelectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsSecondaryOndark) }
return Color(uiColor: VDSColor.elementsSecondaryOnlight)
}
set {
_unSelectedColor = newValue
}
}
open var style: NavigationItemStyle? = .dark
// Must be capped to 0...(tabs.count - 1)
public var selectedTab: Int = 0
open var selectedTab: Int = 0
private enum CodingKeys: String, CodingKey {
case moleculeName
@ -25,6 +64,7 @@ public class TabBarModel: MoleculeModelProtocol {
case selectedColor
case unSelectedColor
case selectedTab
case style
}
public init(with tabs: [TabBarItemModel]) {
@ -46,24 +86,28 @@ public class TabBarModel: MoleculeModelProtocol {
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) {
selectedTab = index
}
if let navStyle = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) {
style = navStyle
}
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(tabs, forKey: .tabs)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encode(selectedColor, forKey: .selectedColor)
try container.encode(unSelectedColor, forKey: .unSelectedColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_selectedColor, forKey: .selectedColor)
try container.encodeIfPresent(_unSelectedColor, forKey: .unSelectedColor)
try container.encode(selectedTab, forKey: .selectedTab)
try container.encodeIfPresent(style, forKey: .style)
}
}
public class TabBarItemModel: Codable {
var title: String?
var image: String
var action: ActionModelProtocol
var accessibilityText: String?
open class TabBarItemModel: Codable {
open var title: String?
open var image: String
open var action: ActionModelProtocol
open var accessibilityText: String?
private enum CodingKeys: String, CodingKey {
case title
@ -86,7 +130,7 @@ public class TabBarItemModel: Codable {
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(title, forKey: .title)
try container.encode(image, forKey: .image)

View File

@ -7,6 +7,7 @@
//
import UIKit
import VDSColorTokens
@objc public protocol TabsDelegate {
func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool
@ -66,7 +67,7 @@ import UIKit
open override func setupView() {
super.setupView()
backgroundColor = .white
backgroundColor = VDSColor.backgroundPrimaryLight
addSubview(bottomLine)
setupCollectionView()
setupSelectionLine()
@ -94,7 +95,7 @@ import UIKit
bottomScrollView.delegate = self
addSubview(bottomScrollView)
bottomScrollView.addSubview(bottomContentView)
selectionLine.backgroundColor = .mvmRed
selectionLine.backgroundColor = VDSColor.paletteRed
bottomContentView.addSubview(selectionLine)
bringSubviewToFront(bottomScrollView)
}
@ -153,8 +154,7 @@ import UIKit
self.delegateObject = delegateObject
self.additionalData = additionalData
selectedIndex = tabsModel?.selectedIndex ?? 0
// TODO: Commented out until we have model support for bar color. Should also do unselected color.
//selectionLine.backgroundColor = tabsModel?.selectedColor.uiColor
selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor
reloadData()
}
}
@ -169,10 +169,10 @@ extension Tabs: UICollectionViewDataSource {
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let labelModel = tabsModel?.tabs[indexPath.row].label, let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TabCellId, for: indexPath) as? TabItemCell else {
return UICollectionViewCell()
}
cell.updateCell(labelModel: labelModel, indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel)
cell.updateCell(indexPath: indexPath, delegateObject: delegateObject, additionalData: additionalData, selected: indexPath.row == selectedIndex, tabsModel: tabsModel)
updateView(collectionView.bounds.width)
return cell
}
@ -332,13 +332,14 @@ extension Tabs {
label.updateView(size)
}
public func updateCell(labelModel: LabelModel, indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) {
public func updateCell(indexPath: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?, selected: Bool, tabsModel: TabsModel?) {
guard let tabsModel = tabsModel else { return }
label.reset()
label.set(with: labelModel, delegateObject, additionalData)
label.set(with: tabsModel.tabs[indexPath.row].label, delegateObject, additionalData)
if selected {
label.textColor = tabsModel?.selectedColor.uiColor ?? .black
label.textColor = tabsModel.selectedColor.uiColor
} else {
label.textColor = .mvmCoolGray6
label.textColor = tabsModel.unselectedColor.uiColor
}
updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel)
}

View File

@ -7,22 +7,78 @@
//
import UIKit
import VDSColorTokens
public class TabsModel: MoleculeModelProtocol {
open class TabsModel: MoleculeModelProtocol {
public static var identifier: String = "tabs"
public var backgroundColor: Color?
public var tabs: [TabItemModel]
public var selectedColor = Color(uiColor: .black)
open var tabs: [TabItemModel]
open var style: NavigationItemStyle?
private var _backgroundColor: Color?
open var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) }
return Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
private var _selectedColor: Color?
open var selectedColor: Color {
get {
if let selectedColor = _selectedColor { return selectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_selectedColor = newValue
}
}
private var _unselectedColor: Color?
open var unselectedColor: Color {
get {
if let unselectedColor = _unselectedColor { return unselectedColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsSecondaryOndark) }
return Color(uiColor: VDSColor.elementsSecondaryOnlight)
}
set {
_unselectedColor = newValue
}
}
private var _selectedBarColor: Color?
open var selectedBarColor: Color {
get {
if let selectedBarColor = _selectedBarColor { return selectedBarColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.paletteRed)
}
set {
_selectedBarColor = newValue
}
}
// Must be capped to 0...(tabs.count - 1)
public var selectedIndex: Int = 0
open var selectedIndex: Int = 0
private enum CodingKeys: String, CodingKey {
case moleculeName
case tabs
case backgroundColor
case selectedColor
case unselectedColor
case selectedBarColor
case selectedIndex
case moleculeName
case style
}
public init(with tabs: [TabItemModel]) {
@ -33,31 +89,35 @@ public class TabsModel: MoleculeModelProtocol {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) {
selectedColor = color
}
_selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor)
_unselectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .unselectedColor)
_selectedBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedBarColor)
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style)
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
selectedIndex = index
}
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(tabs, forKey: .tabs)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encode(selectedColor, forKey: .selectedColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_selectedColor, forKey: .selectedColor)
try container.encodeIfPresent(_unselectedColor, forKey: .unselectedColor)
try container.encodeIfPresent(_selectedBarColor, forKey: .selectedBarColor)
try container.encode(selectedIndex, forKey: .selectedIndex)
try container.encodeIfPresent(style, forKey: .style)
}
}
public class TabItemModel: Codable {
public var label: LabelModel
public var action: ActionModelProtocol?
open class TabItemModel: Codable {
open var label: LabelModel
open var action: ActionModelProtocol?
init(label: LabelModel) {
public init(label: LabelModel) {
self.label = label
}
@ -66,7 +126,7 @@ public class TabItemModel: Codable {
case action
}
func setDefaults() {
open func setDefaults() {
if label.textAlignment == nil {
label.textAlignment = .center
}
@ -85,7 +145,7 @@ public class TabItemModel: Codable {
setDefaults()
}
public func encode(to encoder: Encoder) throws {
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModel(label, forKey: .label)
try container.encodeModelIfPresent(action, forKey: .action)

View File

@ -42,6 +42,15 @@ class AccordionListItemModel: MoleculeListItemModel {
hideArrow = true
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with moleculeModel: MoleculeModelProtocol, molecules:[ListItemModelProtocol & MoleculeModelProtocol]) {
self.molecules = molecules
super.init(with: moleculeModel)
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------

View File

@ -14,4 +14,14 @@ public class ActionDetailWithImageModel: MoleculeModelProtocol {
public var backgroundColor: Color?
public var headlineBodyButton: HeadlineBodyButtonModel
public var image: ImageViewModel
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headlineBodyButton: HeadlineBodyButtonModel, image: ImageViewModel) {
self.headlineBodyButton = headlineBodyButton
self.image = image
}
}

View File

@ -7,6 +7,7 @@
//
import UIKit
import MVMCore
public class CornerLabelsModel: ParentMoleculeModelProtocol {
public static var identifier: String = "cornerLabels"
@ -20,7 +21,7 @@ public class CornerLabelsModel: ParentMoleculeModelProtocol {
[molecule, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel].compactMap { $0 }
}
init(with molecule: MoleculeModelProtocol?) {
public init(with molecule: MoleculeModelProtocol?) {
self.molecule = molecule
}

View File

@ -7,6 +7,7 @@
//
import Foundation
import MVMCore
public class LabelToggleModel: MoleculeModelProtocol {
public static var identifier: String = "labelToggle"
@ -15,7 +16,7 @@ public class LabelToggleModel: MoleculeModelProtocol {
public var label: LabelModel
public var toggle: ToggleModel
init(_ label: LabelModel, _ toggle: ToggleModel) {
public init(_ label: LabelModel, _ toggle: ToggleModel) {
self.label = label
self.toggle = toggle
}

View File

@ -5,6 +5,8 @@
// Created by Scott Pfeil on 5/18/20.
//
import UIKit
public class NavigationImageButtonModel: NavigationButtonModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
@ -17,6 +19,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
public var image: String
public var action: ActionModelProtocol
public var accessibilityText: String?
public var imageRenderingMode: UIImage.RenderingMode = .automatic
//--------------------------------------------------
// MARK: - Initializer
@ -37,6 +40,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
case accessibilityIdentifier
case moleculeName
case accessibilityText
case imageRenderingMode
}
//--------------------------------------------------
@ -49,6 +53,9 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
image = try typeContainer.decode(String.self, forKey: .image)
action = try typeContainer.decodeModel(codingKey: .action)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
if let mode = try typeContainer.decodeIfPresent(UIImage.RenderingMode.self, forKey: .imageRenderingMode) {
imageRenderingMode = mode
}
}
open func encode(to encoder: Encoder) throws {
@ -58,6 +65,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModel(action, forKey: .action)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(imageRenderingMode, forKey: .imageRenderingMode)
}
//--------------------------------------------------
@ -66,7 +74,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
/// Convenience function that creates a BarButtonItem for the model.
public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem {
let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image)
let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image)?.withRenderingMode(imageRenderingMode)
let buttonItem = ImageBarButtonItem.create(with: uiImage, model: self, delegateObject: delegateObject, additionalData: additionalData)
buttonItem.accessibilityIdentifier = accessibilityIdentifier ?? image
if let accessibilityString = accessibilityText {

View File

@ -6,6 +6,12 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import VDSColorTokens
public enum NavigationItemStyle: String, Codable {
case light
case dark
}
open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
//--------------------------------------------------
@ -14,12 +20,39 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
open class var identifier: String { "navigationBar" }
private let defaultHidesSystemBackButton = true
open var title: String?
open var hidden: Bool
open var backgroundColor: Color?
open var tintColor: Color
open var line: LineModel?
open var hidden = false
open var line: LineModel? = LineModel(type: .secondary)
open var hidesSystemBackButton = true
open var style: NavigationItemStyle?
private var _backgroundColor: Color?
open var backgroundColor: Color? {
get {
if let backgroundColor = _backgroundColor { return backgroundColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.backgroundPrimaryDark) }
return Color(uiColor: VDSColor.backgroundPrimaryLight)
}
set {
_backgroundColor = newValue
}
}
private var _tintColor: Color?
open var tintColor: Color {
get {
if let tintColor = _tintColor { return tintColor }
if let style = style,
style == .dark { return Color(uiColor: VDSColor.elementsPrimaryOndark) }
return Color(uiColor: VDSColor.elementsPrimaryOnlight)
}
set {
_tintColor = newValue
}
}
/// If true, we add the button in the backButton property. If false we do not add the button. If nil, we add the button if the controller is not the bottom of the stack
open var alwaysShowBackButton: Bool?
@ -28,17 +61,13 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
open var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var titleView: MoleculeModelProtocol?
open var titleOffset: UIOffset? = UIOffset(horizontal: -CGFloat.greatestFiniteMagnitude, vertical: 0)
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init() {
hidden = false
backgroundColor = Color(uiColor: .mvmWhite)
tintColor = Color(uiColor: .mvmBlack)
line = LineModel(type: .standard)
}
public init() {}
//--------------------------------------------------
// MARK: - Keys
@ -57,6 +86,8 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
case additionalLeftButtons
case additionalRightButtons
case titleView
case style
case titleOffset
}
//--------------------------------------------------
@ -66,16 +97,27 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .mvmWhite)
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .mvmBlack)
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .standard)
hidesSystemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidesSystemBackButton) ?? true
if let hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) {
self.hidden = hidden
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
_tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor)
if let line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) {
self.line = line
}
if let hidesSystemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidesSystemBackButton) {
self.hidesSystemBackButton = hidesSystemBackButton
}
alwaysShowBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowBackButton)
backButton = try typeContainer.decodeModelIfPresent(codingKey: .backButton)
additionalLeftButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalLeftButtons)
additionalRightButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalRightButtons)
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style)
if let titleOffset = try typeContainer.decodeIfPresent(UIOffset.self, forKey: .titleOffset) {
self.titleOffset = titleOffset
}
line?.inverted = style == .dark
}
open func encode(to encoder: Encoder) throws {
@ -83,8 +125,8 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(title, forKey: .title)
try container.encode(hidden, forKey: .hidden)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(tintColor, forKey: .tintColor)
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(_tintColor, forKey: .tintColor)
try container.encodeIfPresent(line, forKey: .line)
try container.encode(hidesSystemBackButton, forKey: .hidesSystemBackButton)
try container.encodeIfPresent(alwaysShowBackButton, forKey: .alwaysShowBackButton)
@ -92,6 +134,8 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
try container.encodeModelsIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons)
try container.encodeModelsIfPresent(additionalRightButtons, forKey: .additionalRightButtons)
try container.encodeModelIfPresent(titleView, forKey: .titleView)
try container.encodeIfPresent(style, forKey: .style)
try container.encodeIfPresent(titleOffset, forKey: .titleOffset)
}
}

View File

@ -22,7 +22,7 @@ public class BGImageHeadlineBodyButtonModel: ContainerModel, MoleculeModelProtoc
// MARK: - Initializer
//--------------------------------------------------
init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
public init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
self.headlineBody = headlineBody
self.image = image
super.init()

View File

@ -54,27 +54,27 @@ open class HeadlineBody: View {
}
public func styleLandingPageHeader() {
headlineLabel.setFontStyle(.Title2XLarge)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = Padding.Two
headlineLabel.setFontStyle(.RegularTitle2XLarge)
messageLabel.setFontStyle(.RegularTitleMedium)
spaceBetweenLabelsConstant = Padding.Four
}
public func stylePageHeader() {
headlineLabel.setFontStyle(.BoldTitleLarge)
headlineLabel.setFontStyle(.RegularTitleLarge)
messageLabel.setFontStyle(.RegularBodyLarge)
spaceBetweenLabelsConstant = Padding.Two
}
public func styleListItem() {
headlineLabel.setFontStyle(.RegularTitleSmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = Padding.One
}
public func styleListItem() {
headlineLabel.setFontStyle(.BoldBodySmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = 0
}
public func styleListItemDivider() {
headlineLabel.setFontStyle(.BoldTitleMedium)
headlineLabel.setFontStyle(.BoldTitleSmall)
messageLabel.setFontStyle(.RegularBodySmall)
spaceBetweenLabelsConstant = 0
spaceBetweenLabelsConstant = Padding.Two
}
//--------------------------------------------------

View File

@ -5,7 +5,7 @@
// Created by Scott Pfeil on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
public class HeadlineBodyButtonModel: MoleculeModelProtocol {
//--------------------------------------------------
@ -20,6 +20,16 @@ public class HeadlineBodyButtonModel: MoleculeModelProtocol {
public var button: ButtonModel
public var buttonHeadlinePadding: CGFloat
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(headlineBody: HeadlineBodyModel, button: ButtonModel, buttonHeadlinePadding: CGFloat) {
self.headlineBody = headlineBody
self.button = button
self.buttonHeadlinePadding = buttonHeadlinePadding
}
//--------------------------------------------------
// MARK: - Method
//--------------------------------------------------

View File

@ -22,7 +22,7 @@ public class HeadlineBodyCaretLinkImageModel: ContainerModel, MoleculeModelProto
// MARK: - Initializer
//--------------------------------------------------
init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
public init(headlineBody: HeadlineBodyModel, image: ImageViewModel) {
self.headlineBody = headlineBody
self.image = image
super.init()

View File

@ -20,6 +20,15 @@ import Foundation
case list
case numberColor
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(numberColor: Color, molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
self.numberColor = numberColor
super.init(molecules: molecules, axis: axis, spacing: spacing)
}
// Numbered list model comes in the from of list = [MoleculeModelProtocol]
public required init(from decoder: Decoder) throws {

View File

@ -22,7 +22,17 @@ import Foundation
case bulletChar
case bulletColor
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(bulletChar: String, bulletColor: Color, molecules: [StackItemModelProtocol & MoleculeModelProtocol], axis: NSLayoutConstraint.Axis? = nil, spacing: CGFloat? = nil) {
self.bulletChar = bulletChar
self.bulletColor = bulletColor
super.init(molecules: molecules, axis: axis, spacing: spacing)
}
// Numbered list model comes in the from of list = [MoleculeModelProtocol]
public required init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)

View File

@ -20,4 +20,5 @@ public protocol NavigationItemModelProtocol {
var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
var titleView: MoleculeModelProtocol? { get set }
var titleOffset: UIOffset? { get }
}

View File

@ -16,6 +16,14 @@
public var closeAction: ActionModelProtocol?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(pageType: String, screenHeading: String?, molecules: [ListItemModelProtocol & MoleculeModelProtocol]) {
super.init(pageType: pageType, screenHeading: screenHeading, molecules: molecules)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -5,7 +5,7 @@
// Created by Scott Pfeil on 10/8/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import MVMCore
@objcMembers public class ModalSectionListTemplateModel: SectionListTemplateModel {
//--------------------------------------------------
@ -15,6 +15,14 @@
public override class var identifier: String { "modalSectionList" }
public var closeAction: ActionModelProtocol?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(with sections: [SectionModel], pageType: String, molecules: [ListItemModelProtocol & MoleculeModelProtocol], screenHeading: String?) {
super.init(with: sections, pageType: pageType, molecules: molecules, screenHeading: screenHeading)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -15,6 +15,14 @@
public override class var identifier: String { "modalStack" }
public var closeAction: ActionModelProtocol?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public override init(pageType: String, moleculeStack: StackModel) {
super.init(pageType: pageType, moleculeStack: moleculeStack)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -24,7 +32,7 @@
}
//--------------------------------------------------
// MARK: - Init
// MARK: - Initializer
//--------------------------------------------------
required public init(from decoder: Decoder) throws {

View File

@ -19,6 +19,14 @@ public protocol SectionListHeaderFooterModel { }
public var footer: (SectionListHeaderFooterModel & MoleculeModelProtocol)?
public var rows: [ListItemModelProtocol & MoleculeModelProtocol]
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with rows: [ListItemModelProtocol & MoleculeModelProtocol]) {
self.rows = rows
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -65,6 +73,15 @@ public protocol SectionListHeaderFooterModel { }
}
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with sections: [SectionModel], pageType: String, molecules: [ListItemModelProtocol & MoleculeModelProtocol], screenHeading: String? = nil) {
self.sections = sections
super.init(pageType: pageType, screenHeading: screenHeading, molecules: molecules)
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------

View File

@ -19,7 +19,7 @@ import UIKit
public let containerHelper = ContainerHelper()
// For the accessory view convenience.
private var caretView: CaretView?
private var caretView: UIImageView?
private var caretViewWidthSizeObject: MFSizeObject?
private var caretViewHeightSizeObject: MFSizeObject?
@ -42,13 +42,13 @@ import UIKit
switch style {
case .standard?:
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.standard)
bottomSeparatorView?.setStyle(.secondary)
case .shortDivider?:
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.thin)
bottomSeparatorView?.setStyle(.none)
case .tallDivider?:
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.thin)
bottomSeparatorView?.setStyle(.none)
case .sectionFooter?:
topSeparatorView?.setStyle(.none)
bottomSeparatorView?.setStyle(.none)
@ -185,20 +185,22 @@ import UIKit
@objc public func addCaretViewAccessory() {
guard accessoryView == nil else { return }
let peakingImageView = UIImageView(image: MVMCoreUIUtility.imageNamed("peakingRightArrow")?.withRenderingMode(.alwaysTemplate))
let caret = CaretView(lineWidth: 1)
caret.translatesAutoresizingMaskIntoConstraints = true
caret.isAccessibilityElement = true
caret.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
caret.accessibilityTraits = .button
caret.size = .small(.vertical)
if let size = caret.size?.dimensions() {
caret.frame = CGRect(origin: .zero, size: size)
caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9)
caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16)
}
caretView = caret
accessoryView = caret
peakingImageView.translatesAutoresizingMaskIntoConstraints = true
peakingImageView.alpha = 0
peakingImageView.tintColor = .black
peakingImageView.isAccessibilityElement = true
peakingImageView.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")
peakingImageView.accessibilityTraits = .button
let accessorySize = CGRect(origin: .zero, size: CGSize(width: 13.3, height: 13.3))
peakingImageView.frame = accessorySize
caretViewWidthSizeObject = MFSizeObject(standardSize: accessorySize.width, standardiPadPortraitSize: 16.6)
caretViewHeightSizeObject = MFSizeObject(standardSize: accessorySize.height, standardiPadPortraitSize: 16.6)
caretView = peakingImageView
accessoryView = peakingImageView
}
/// NOTE: Should only be called when displayed or about to be displayed.
@ -244,8 +246,8 @@ import UIKit
topSeparatorView?.set(with: model, delegateObject, additionalData)
bottomSeparatorView?.set(with: model, delegateObject, additionalData)
} else {
topSeparatorView?.setStyle(.standard)
bottomSeparatorView?.setStyle(.standard)
topSeparatorView?.setStyle(.secondary)
bottomSeparatorView?.setStyle(.secondary)
}
setSeparatorFrequency(model?.frequency ?? .allExceptTop, indexPath: indexPath)
}

View File

@ -43,9 +43,6 @@ import UIKit
public var selectedField: UIView?
// Stores the previous tab bar index.
public var tabBarIndex: Int?
/// Checks if the screen width has changed
open func screenSizeChanged() -> Bool {
!MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1)
@ -244,12 +241,6 @@ import UIKit
view.backgroundColor = backgroundColor.uiColor
}
// Update splitview properties
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
updateTabBar()
}
// Notify the manager of new data
manager?.newDataReceived?(in: self)
}
@ -267,34 +258,6 @@ import UIKit
return model?.navigationBar
}
//--------------------------------------------------
// MARK: - TabBar
//--------------------------------------------------
open func updateTabBar() {
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self else { return }
MVMCoreUISplitViewController.main()?.tabBar?.delegateObject = delegateObjectIVar
if let index = (model as? TabPageModelProtocol)?.tabBarIndex {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = loadObject?.requestParameters?.actionMap?["tabBarIndex"] as? Int {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = self.tabBarIndex {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = MVMCoreUISplitViewController.main()?.tabBar?.currentTabIndex() {
// Store current tab index for cases like back button.
self.tabBarIndex = index
}
if let hidden = (model as? TabPageModelProtocol)?.tabBarHidden {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
} else if let hidden = loadObject?.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
} else {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(true)
}
}
//--------------------------------------------------
// MARK: - View Lifecycle
//--------------------------------------------------
@ -349,12 +312,6 @@ import UIKit
}
open func pageShown() {
// Update split view properties if this is the current detail controller.
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
updateTabBar()
}
// Track.
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)

View File

@ -75,7 +75,7 @@ public class AddRemoveMoleculesBehavior: PageCustomActionHandlerBehavior, PageMo
self.delegate = delegateObject
}
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) {
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {
guard let list = delegate?.moleculeListDelegate else { return }
for case let model as (MoleculeModelProtocol & ListItemModelProtocol & AddMolecules) in rootMolecules {
if let moleculesToAdd = model.getRecursiveMoleculesToAdd(),

View File

@ -19,7 +19,7 @@ public protocol PageBehaviorProtocol: ModelHandlerProtocol {
public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject)
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?)
}
public protocol PageVisibilityBehavior: PageBehaviorProtocol {

View File

@ -186,7 +186,7 @@ extension UIColor {
//--------------------------------------------------
/// HEX: #F6F6F6
public static let mvmCoolGray1 = UIColor.assetColor(named: "coolGray1")
@objc public static let mvmCoolGray1 = UIColor.assetColor(named: "coolGray1")
/// HEX: #D8DADA
public static let mvmCoolGray3 = UIColor.assetColor(named: "coolGray3")

View File

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

View File

@ -1,201 +0,0 @@
//
// NavigationController.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/24/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol {
public var separatorView: Line?
public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)?
/// Getter for the main navigation controller
public static func navigationController() -> Self? {
return MVMCoreActionUtility.initializerClassCheck(MVMCoreUISession.sharedGlobal()?.navigationController, classToVerify: self) as? Self
}
/// Provides MVM styling to the navigation bar. Returns a reference to the line.
public static func style(_ navigationBar: UINavigationBar) -> Line {
navigationBar.backgroundColor = .white
navigationBar.shadowImage = UIImage()
navigationBar.isOpaque = true
navigationBar.tintColor = .black
navigationBar.titleTextAttributes = [NSAttributedString.Key.font: MFStyler.fontBoldBodySmall(false)];
return Line(pinTo: navigationBar, edge: .bottom, useMargin: false)
}
/// Sets up the application with a navigation controller
public static func setupNavigationController() -> Self? {
let navigationController = self.init()
navigationController.separatorView = style(navigationController.navigationBar)
MVMCoreUISession.sharedGlobal()?.navigationController = navigationController
MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController
MVMCoreNavigationHandler.shared()?.navigationController = navigationController
MVMCoreNavigationHandler.shared()?.addDelegate(navigationController)
return navigationController
}
/// Sets up the application with a navigation controller as the main container.
public static func setupNavigationControllerAsMainController() -> Self? {
guard let navigationController = setupNavigationController() else { return nil }
MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController)
return navigationController
}
/// Convenience function for setting the navigation item.
public static func setNavigationItem(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) {
viewController.navigationItem.title = navigationItemModel.title
viewController.navigationItem.accessibilityLabel = navigationItemModel.title
viewController.navigationItem.hidesBackButton = navigationItemModel.hidesSystemBackButton
viewController.navigationItem.leftItemsSupplementBackButton = !navigationItemModel.hidesSystemBackButton
setNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
setNavigationTitleView(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
}
/// Convenience function for setting the navigation buttons.
public static func setNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) {
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
var leftItems: [UIBarButtonItem] = []
if navigationItemModel.hidesSystemBackButton,
navigationItemModel.alwaysShowBackButton != false {
if let backButtonModel = navigationItemModel.backButton,
MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 0 > 1 || navigationItemModel.alwaysShowBackButton ?? false {
leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
}
if let leftItemModels = navigationItemModel.additionalLeftButtons {
for item in leftItemModels {
leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
}
}
}
viewController.navigationItem.leftBarButtonItems = leftItems.count > 0 ? leftItems : nil
var rightItems: [UIBarButtonItem] = []
if let rightItemModels = navigationItemModel.additionalRightButtons {
for item in rightItemModels {
rightItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
}
}
viewController.navigationItem.rightBarButtonItems = rightItems.count > 0 ? rightItems : nil
}
/// Convenience function for setting the navigation bar ui, except for the buttons.
public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) {
navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true)
navigationController.navigationBar.barTintColor = navigationItemModel.backgroundColor?.uiColor ?? .white
let tint = navigationItemModel.tintColor.uiColor
navigationController.navigationBar.tintColor = tint
// Have the navigation title match the tint color
navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor)
// Update line.
if let navigationController = navigationController as? NavigationController {
navigationController.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none
}
}
/// Convenience function for setting the navigation titleView.
public static func setNavigationTitleView(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) {
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
if let titleViewModel = navigationItemModel?.titleView, let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) {
viewController.navigationItem.titleView = molecule
}
}
/// Convenience function to return the navigation model of the lowest controller traversing managers if applicable.
public func getNavigationModel(from viewController: UIViewController) -> NavigationItemModelProtocol? {
return (viewController as? PageProtocol)?.pageModel?.navigationBar
}
/// Verifies the controller is the currently displayed controller.
public func isDisplayed(viewController: UIViewController) -> Bool {
guard let topViewController = topViewController,
viewController == MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else {
return false
}
return true
}
}
extension NavigationController: MVMCoreViewManagerProtocol {
public func getCurrentViewController() -> UIViewController? {
guard let topViewController = topViewController else { return nil }
return MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController)
}
public func containsPage(withPageType pageType: String?) -> Bool {
for controller in viewControllers {
if let manager = controller as? MVMCoreViewManagerProtocol,
manager.containsPage(withPageType: pageType) {
return true
} else if let controller = controller as? MVMCoreViewControllerProtocol,
controller.pageType == pageType {
return true
}
}
return false
}
public func newDataReceived(in viewController: UIViewController) {
if isDisplayed(viewController: viewController),
let topViewController = topViewController,
let model = getNavigationModel(from: viewController) {
Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: topViewController)
Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: topViewController)
}
manager?.newDataReceived?(in: viewController)
}
public func willDisplay(_ viewController: UIViewController) {
if let topViewController = topViewController,
let model = getNavigationModel(from: viewController) {
Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: topViewController)
}
manager?.willDisplay?(viewController)
}
public func displayedViewController(_ viewController: UIViewController) {
if isDisplayed(viewController: viewController),
let topViewController = topViewController,
let model = getNavigationModel(from: viewController) {
Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: topViewController)
}
manager?.displayedViewController?(viewController)
}
}
extension NavigationController: MVMCorePresentationDelegateProtocol {
public func navigationController(_ navigationController: UINavigationController, prepareDisplayFor viewController: UIViewController) {
guard self == navigationController,
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController),
let model = getNavigationModel(from: newViewController) else { return }
Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: viewController)
}
public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) {
guard self == navigationController,
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
}
manager?.willDisplay?(newViewController)
}
public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) {
guard self == navigationController,
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
if let model = getNavigationModel(from: newViewController) {
Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: viewController)
}
manager?.displayedViewController?(newViewController)
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
controller.viewControllerReady?(inManager: self)
}
}
}

View File

@ -0,0 +1,137 @@
//
// NavigationController.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/24/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol {
public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)?
/// Getter for the main navigation controller
public static func navigationController() -> Self? {
return MVMCoreActionUtility.initializerClassCheck(MVMCoreUISession.sharedGlobal()?.navigationController, classToVerify: self) as? Self
}
/// Sets up the application with a navigation controller
public static func setupNavigationController() -> Self? {
let navigationController = self.init()
MVMCoreUISession.sharedGlobal()?.navigationController = navigationController
MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController
MVMCoreNavigationHandler.shared()?.navigationController = navigationController
MVMCoreNavigationHandler.shared()?.addDelegate(navigationController)
navigationController.setNavigationBarUI(with: NavigationItemModel())
return navigationController
}
/// Sets up the application with a navigation controller as the main container.
public static func setupNavigationControllerAsMainController() -> Self? {
guard let navigationController = setupNavigationController() else { return nil }
MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController)
return navigationController
}
/// Convenience function to return the navigation model of the lowest controller traversing managers if applicable.
public func getNavigationModel(from viewController: UIViewController) -> NavigationItemModelProtocol? {
return (viewController as? PageProtocol)?.pageModel?.navigationBar
}
/// Verifies the controller is the currently displayed controller.
public func isDisplayed(viewController: UIViewController) -> Bool {
guard let topViewController = topViewController,
viewController == MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else {
return false
}
return true
}
}
extension NavigationController: MVMCoreViewManagerProtocol {
public func getCurrentViewController() -> UIViewController? {
guard let topViewController = topViewController else { return nil }
return MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController)
}
public func containsPage(withPageType pageType: String?) -> Bool {
for controller in viewControllers {
if let manager = controller as? MVMCoreViewManagerProtocol,
manager.containsPage(withPageType: pageType) {
return true
} else if let controller = controller as? MVMCoreViewControllerProtocol,
controller.pageType == pageType {
return true
}
}
return false
}
public func newDataReceived(in viewController: UIViewController) {
if isDisplayed(viewController: viewController),
let topViewController = topViewController,
let model = getNavigationModel(from: viewController) {
setNavigationItem(with: model, for: topViewController)
setNavigationBarUI(with: model)
navigationBar.setNeedsLayout()
navigationBar.layoutIfNeeded()
}
manager?.newDataReceived?(in: viewController)
}
public func willDisplay(_ viewController: UIViewController) {
if let topViewController = topViewController,
isDisplayed(viewController: viewController),
let model = getNavigationModel(from: viewController) {
setNavigationItem(with: model, for: topViewController)
setNavigationBarUI(with: model)
navigationBar.setNeedsLayout()
navigationBar.layoutIfNeeded()
}
manager?.willDisplay?(viewController)
}
public func displayedViewController(_ viewController: UIViewController) {
manager?.displayedViewController?(viewController)
}
}
extension NavigationController: MVMCorePresentationDelegateProtocol {
public func navigationController(_ navigationController: UINavigationController, prepareDisplayFor viewController: UIViewController) {
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
}
guard self == navigationController,
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController),
let model = getNavigationModel(from: newViewController) else { return }
setNavigationItem(with: model, for: viewController)
setNavigationBarUI(with: model)
}
public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) {
guard self == navigationController,
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
manager?.willDisplay?(newViewController)
}
public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) {
guard self == navigationController,
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
manager?.displayedViewController?(newViewController)
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
controller.viewControllerReady?(inManager: self)
}
}
}
extension UIColor {
func image(_ size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
return UIGraphicsImageRenderer(size: size).image { rendererContext in
self.setFill()
rendererContext.fill(CGRect(origin: .zero, size: size))
}
}
}

View File

@ -0,0 +1,88 @@
//
// UINavigationController+Extension.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/14/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import Foundation
public extension UINavigationController {
/// Convenience function for setting the navigation item.
func setNavigationItem(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
viewController.navigationItem.title = model.title
viewController.navigationItem.accessibilityLabel = model.title
viewController.navigationItem.hidesBackButton = model.hidesSystemBackButton
viewController.navigationItem.leftItemsSupplementBackButton = !model.hidesSystemBackButton
setNavigationButtons(with: model, for: viewController)
setNavigationTitleView(with: model, for: viewController)
}
/// Convenience function for setting the navigation buttons.
func setNavigationButtons(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
var leftItems: [UIBarButtonItem] = []
if model.hidesSystemBackButton,
model.alwaysShowBackButton != false {
if let backButtonModel = model.backButton,
MVMCoreNavigationHandler.shared()?.getViewControllers(for: self)?.count ?? 0 > 1 || model.alwaysShowBackButton ?? false {
leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
}
if let leftItemModels = model.additionalLeftButtons {
for item in leftItemModels {
leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
}
}
}
viewController.navigationItem.leftBarButtonItems = leftItems.count > 0 ? leftItems : nil
var rightItems: [UIBarButtonItem] = []
if let rightItemModels = model.additionalRightButtons {
for item in rightItemModels {
rightItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
}
}
viewController.navigationItem.rightBarButtonItems = rightItems.count > 0 ? rightItems : nil
}
/// Convenience function for setting the navigation titleView.
func setNavigationTitleView(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
if let titleViewModel = model.titleView,
let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) {
viewController.navigationItem.titleView = molecule
}
}
/// Returns a ShadowImage based on the line property of NavigationItemModelProtocol
func getNavigationBarShadowImage(for navigationItemModel: NavigationItemModelProtocol) -> UIImage? {
guard let thickness = navigationItemModel.line?.thickness,
let backgroundColor = navigationItemModel.line?.backgroundColor else { return nil }
return backgroundColor.uiColor.image(CGSize(width: thickness, height: thickness))
}
/// Convenience function for setting the navigation bar ui
func setNavigationBarUI(with model: NavigationItemModelProtocol) {
let navigationBar = navigationBar
let font = MFStyler.fontBoldBodyLarge(false)
let backgroundColor = model.backgroundColor?.uiColor
let tint = model.tintColor.uiColor
navigationBar.tintColor = tint
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.titleTextAttributes = [NSAttributedString.Key.font: font,
NSAttributedString.Key.foregroundColor: tint];
appearance.backgroundColor = backgroundColor
appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor)
appearance.titlePositionAdjustment = model.titleOffset ?? .zero
appearance.shadowColor = model.line?.backgroundColor?.uiColor ?? .clear
appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate)
navigationBar.standardAppearance = appearance
navigationBar.scrollEdgeAppearance = appearance
setNavigationBarHidden(model.hidden, animated: true)
}
}

View File

@ -7,23 +7,77 @@
//
import Foundation
import UIKit
// Navigation bar update functions
public extension MVMCoreUISplitViewController {
/// Updates the state for various controls (navigation, tab, progress) for the controller.
func updateState(with viewController: UIViewController) {
guard let navigationController = navigationController,
navigationController.isDisplayed(viewController: viewController) else { return }
updateNavigationBarFor(viewController: viewController)
updateProgressBar(for: viewController)
updateTabBar(for: viewController)
}
// MARK: - Progress Bar
/// Updates the progress bar based on the page json for the view controller.
func updateProgressBar(for viewController: UIViewController) {
guard let viewController = viewController as? MVMCoreViewControllerProtocol else { return }
var progress: Float = 0.0
if let progressString = viewController.loadObject??.pageJSON?.optionalStringForKey(KeyProgressPercent),
let floatValue = Float(progressString) {
progress = floatValue/100
}
setBottomProgressBarProgress(progress)
}
// MARK: - Tab Bar
/// Updates the tab bar based on the page json for the view controller.
func updateTabBar(for viewController: UIViewController) {
let mvmViewController = viewController as? MVMCoreViewControllerProtocol
tabBar?.delegateObject = mvmViewController?.delegateObject?() as? MVMCoreUIDelegateObject
let navigationIndex = (MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 1) - 1
// Set the highlighted index. In terms of priority, Page > Action > Previous.
if let index = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarIndex {
tabBar?.highlightTab(at: index)
} else if let index = mvmViewController?.loadObject??.requestParameters?.actionMap?["tabBarIndex"] as? Int {
tabBar?.highlightTab(at: index)
} else if navigationIndex < tabBarIndices.count {
let index = (tabBarIndices[navigationIndex] as! NSNumber).intValue
tabBar?.highlightTab(at: index)
}
// Store current tab index, so we can switch back when going back in hierarchy.
if tabBarIndices.count > 0 {
tabBarIndices.removeObjects(in: NSRange(location: navigationIndex, length: tabBarIndices.count - navigationIndex))
}
if let currentIndex = tabBar?.currentTabIndex() {
tabBarIndices.add(NSNumber(integerLiteral: currentIndex))
}
// Show/Hide. In terms of priority, Page > Action > Always Show.
if let hidden = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarHidden {
updateTabBarShowing(!hidden)
} else if let hidden = mvmViewController?.loadObject??.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
updateTabBarShowing(!hidden)
} else {
updateTabBarShowing(true)
}
}
// MARK: - Navigation Bar
/// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol.
static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
guard let splitView = MVMCoreUISplitViewController.main(),
navigationController == splitView.navigationController,
viewController == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() else {
func setNavigationBar(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
guard navigationController == self.navigationController,
viewController == getCurrentDetailViewController() else {
/// Not the split view navigation controller, skip split functions.
return
}
splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel)
}
/// Sets the navigation item for the view controller based on the model and splitview controller
private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
setLeftPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
setRightPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
@ -94,6 +148,11 @@ public extension MVMCoreUISplitViewController {
rightItems.append(panelButton)
}
// Add any buttons added by the splitview.
if let additionalRightButtons = additionalRightButtons(for: viewController) {
rightItems.append(contentsOf: additionalRightButtons)
}
// Add other model buttons
if let rightItemModels = navigationItemModel?.additionalRightButtons {
for item in rightItemModels {
@ -101,11 +160,6 @@ public extension MVMCoreUISplitViewController {
}
}
// Add any buttons added by the splitview.
if let additionalRightButtons = additionalRightButtons(for: viewController) {
rightItems.append(contentsOf: additionalRightButtons)
}
topViewController.navigationItem.setRightBarButtonItems(rightItems.count > 0 ? rightItems : nil, animated: !DisableAnimations.boolValue)
}
@ -121,7 +175,31 @@ public extension MVMCoreUISplitViewController {
guard let navigationController = navigationController,
navigationController.isDisplayed(viewController: viewController),
let model = navigationController.getNavigationModel(from: viewController) else { return }
set(for: viewController, navigationController: navigationController, navigationItemModel: model)
setNavigationBar(for: viewController, navigationController: navigationController, navigationItemModel: model)
guard !(topAlertView?.overridingStatusBar() ?? false) else { return }
setStatusBarForCurrentViewController()
}
// MARK: - Status Bar
/// Returns the bar style for the background color. Light if on a dark background, otherwise default.
func getStatusBarStyle(for backgroundColor: UIColor?) -> UIStatusBarStyle {
var greyScale: CGFloat = 0
if backgroundColor?.getWhite(&greyScale, alpha: nil) == true,
greyScale < 0.5 { return .lightContent }
return .default
}
/// Updates the status bar background color and style.
@objc func setStatusBarForCurrentViewController() {
let viewController = getCurrentViewController() as? MVMCoreUIDetailViewProtocol
let backgroundColor = viewController?.defaultStatusBarBackgroundColor?() ??
navigationController?.navigationBar.standardAppearance.backgroundColor ??
statusBarView?.backgroundColor
let style = viewController?.defaultStatusBarStyle?() ??
getStatusBarStyle(for: backgroundColor)
setStatusBarBackgroundColor(backgroundColor, style: style)
}
}
@ -134,12 +212,12 @@ extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol {
navigationController?.containsPage(withPageType: pageType) ?? false
}
public func displayedViewController(_ viewController: UIViewController) {
public func willDisplay(_ viewController: UIViewController) {
setupPanels()
updateNavigationBarFor(viewController: viewController)
updateState(with: viewController)
}
public func newDataReceived(in viewController: UIViewController) {
updateNavigationBarFor(viewController: viewController)
updateState(with: viewController)
}
}

View File

@ -44,6 +44,9 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
// Reference to the top alert view
@property (nullable, weak, nonatomic) MVMCoreUITopAlertView *topAlertView;
// Reference to the status bar view
@property (nullable, weak, nonatomic) UIView *statusBarView;
// References to the current navigation item settings.
@property (nonatomic, readonly) BOOL leftPanelIsAccessible;
@property (nonatomic, readonly) BOOL rightPanelIsAccessible;
@ -52,6 +55,9 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
/// Reference to the tabbar.
@property (nullable, weak, nonatomic) UIView <TabBarProtocol>*tabBar;
/// Tab bar index history.
@property (nonnull, strong, nonatomic) NSMutableArray <NSNumber *>*tabBarIndices;
// Convenience getter
+ (nullable instancetype)mainSplitViewController;
@ -122,10 +128,6 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
+ (CGFloat)getApplicationViewWidth;
+ (CGFloat)getApplicationViewMaxSize;
// return subviewcontrollers' prefer status bar style
- (UIStatusBarStyle)getDefaultStatusBarStyle;
- (nullable UIColor *)getDefaultStatusBarBackgroundColor;
/// Returns true if a panel is showing.
- (BOOL)isAPanelShowing;
@ -166,4 +168,15 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
/// Updates if the tab bar is showing or not.
- (void)updateTabBarShowing:(BOOL)showing;
#pragma mark - Status Bar
/// Updates the status bar with the given style and background color
- (void)setStatusBarBackgroundColor:(nullable UIColor *)backgroundColor style:(UIStatusBarStyle)style;
/// Shows the view under the status bar.
- (void)expandStatusBarView;
/// Hides the view under the status bar.
- (void)collapseStatusBarView;
@end

View File

@ -63,6 +63,10 @@ typedef NS_OPTIONS(NSInteger, MFExtendedDrawer) {
@property (weak, nonatomic, readwrite) UIViewController *navigationItemViewController;
@property (strong, nonatomic) NSNumber *transitionWidth;
@property (nonatomic) UIStatusBarStyle statusBarStyle;
@property (strong, nonatomic) NSLayoutConstraint *statusBarHeightConstraint;
@property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint;
// Dismisses any panel
- (void)dismissPanels:(id)sender;
@ -89,13 +93,20 @@ CGFloat const PanelAnimationDuration = 0.2;
}
- (nullable instancetype)initWithLeftPanel:(nullable UIViewController <MVMCoreUIPanelProtocol> *)leftPanel rightPanel:(nullable UIViewController <MVMCoreUIPanelProtocol> *)rightPanel {
if (self = [super init]) {
if (self = [self init]) {
self.globalLeftPanel = leftPanel;
self.globalRightPanel = rightPanel;
}
return self;
}
- (nullable instancetype)init {
if (self = [super init]) {
self.tabBarIndices = [NSMutableArray array];
}
return self;
}
#pragma mark - Main Subclassables
- (MFNumberOfDrawers)numberOfDrawersShouldShow:(NSNumber *)forWidth {
@ -841,6 +852,38 @@ CGFloat const PanelAnimationDuration = 0.2;
}];
}
#pragma mark - Status Bar
- (void)setStatusBarBackgroundColor:(UIColor *)backgroundColor style:(UIStatusBarStyle)style {
self.statusBarView.backgroundColor = backgroundColor;
self.statusBarStyle = style;
// Triggers preferredStatusBarStyle
[self.parentViewController setNeedsStatusBarAppearanceUpdate];
}
- (UIStatusBarStyle)preferredStatusBarStyle {
return self.statusBarStyle;
}
- (void)expandStatusBarView {
__weak typeof(self) weakSelf = self;
[MVMCoreDispatchUtility performBlockOnMainThread:^{
weakSelf.statusBarBottomConstraint.active = YES;
weakSelf.statusBarHeightConstraint.active = NO;
[weakSelf.view layoutIfNeeded];
}];
}
- (void)collapseStatusBarView {
__weak typeof(self) weakSelf = self;
[MVMCoreDispatchUtility performBlockOnMainThread:^{
weakSelf.statusBarBottomConstraint.active = NO;
weakSelf.statusBarHeightConstraint.active = YES;
[weakSelf.view layoutIfNeeded];
}];
}
#pragma mark - View Cyle
- (void)loadView {
@ -849,6 +892,17 @@ CGFloat const PanelAnimationDuration = 0.2;
view.translatesAutoresizingMaskIntoConstraints = NO;
self.view = view;
// Status bar
UIView *statusBarView = [MVMCoreUICommonViewsUtility commonView];
statusBarView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:statusBarView];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[statusBarView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView)]];
id topGuide = view.safeAreaLayoutGuide;
self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
self.statusBarBottomConstraint.active = YES;
self.statusBarHeightConstraint = [statusBarView.heightAnchor constraintEqualToConstant:0];
self.statusBarView = statusBarView;
// Top Alert
MVMCoreUITopAlertView *topAlertView = nil;
if ([[CoreUIObject sharedInstance].globalTopAlertDelegate respondsToSelector:@selector(getTopAlertView)]) {
@ -894,9 +948,9 @@ CGFloat const PanelAnimationDuration = 0.2;
self.bottomProgressBarHeightConstraint = bottomProgressHeight;
if (topAlertView) {
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[topAlertView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(topAlertView, mainView, progressView)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[topAlertView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,topAlertView, mainView, progressView)]];
} else {
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(mainView, progressView)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,mainView, progressView)]];
}
// Add tabbar if we have it.
@ -924,7 +978,6 @@ CGFloat const PanelAnimationDuration = 0.2;
- (void)viewDidLoad {
[super viewDidLoad];
[self.topAlertView pinATopViewController:self];
// Creates the back button
self.backButton = [[UIBarButtonItem alloc] initWithImage:[self imageForBackButton] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonPressed:)];
@ -1008,36 +1061,6 @@ CGFloat const PanelAnimationDuration = 0.2;
}
}
- (UIStatusBarStyle)preferredStatusBarStyle {
if (self.topAlertView.topAlertObject) {
return self.topAlertView.statusBarStyle;
} else {
UIStatusBarStyle style = [self getDefaultStatusBarStyle];
[self.topAlertView resetDefaultBackgroundColor:[self getDefaultStatusBarBackgroundColor] basedOnStatusBarStyle:style];
return style;
}
}
- (UIStatusBarStyle)getDefaultStatusBarStyle {
UIViewController *viewController = [self getCurrentDetailViewController];
if ([viewController conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)]
&& [viewController respondsToSelector:@selector(defaultStatusBarStyle)]
&& [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarStyle]) {
return [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarStyle];
}
return UIStatusBarStyleDefault;
}
- (UIColor *)getDefaultStatusBarBackgroundColor {
UIViewController *viewController = [self getCurrentDetailViewController];
if ([viewController conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)]
&& [viewController respondsToSelector:@selector(defaultStatusBarBackgroundColor)]
&& [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarBackgroundColor]) {
return [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarBackgroundColor];
}
return nil;
}
- (BOOL)isAPanelShowing {
return fabs(self.mainViewLeading.constant) > 1;
}

View File

@ -75,7 +75,7 @@ open class Container: View, ContainerProtocol {
self.view = view
}
convenience init(andContain view: UIView) {
public convenience init(andContain view: UIView) {
self.init()
addAndContain(view)
}

View File

@ -20,7 +20,11 @@ public class ClearFormFieldEffectModel: FormFieldEffectProtocol {
public var activatedRuleIds: [String]?
public var rules: [RulesProtocol]
init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
self.fieldKey = fieldKey
self.activatedRuleIds = activatedRuleIds
self.rules = rules

View File

@ -18,8 +18,12 @@ public class DisableFormFieldEffectModel: FormFieldEffectProtocol {
public var fieldKey: String = ""
public var activatedRuleIds: [String]?
public var rules: [RulesProtocol]
init(_ fieldKey: String, _ activatedRuleIds: [String], _ rules: [RulesProtocol]) {
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ fieldKey: String, _ activatedRuleIds: [String], _ rules: [RulesProtocol]) {
self.fieldKey = fieldKey
self.activatedRuleIds = activatedRuleIds
self.rules = rules

View File

@ -19,7 +19,11 @@ public class DynamicRuleFormFieldEffectModel: FormFieldEffectProtocol {
public var activatedRuleIds: [String]?
public var rules: [RulesProtocol]
init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
self.fieldKey = fieldKey
self.activatedRuleIds = activatedRuleIds
self.rules = rules

View File

@ -21,7 +21,11 @@ public class EnableFormFieldEffectModel: FormFieldEffectProtocol {
public var activatedRuleIds: [String]?
public var rules: [RulesProtocol]
init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ fieldKey: String, activatedRuleIds: [String], rules: [RulesProtocol]) {
self.fieldKey = fieldKey
self.activatedRuleIds = activatedRuleIds
self.rules = rules

View File

@ -18,8 +18,12 @@ public class HideFormFieldEffectModel: FormFieldEffectProtocol {
public var fieldKey: String = ""
public var activatedRuleIds: [String]?
public var rules: [RulesProtocol]
init(_ fieldKey: String, _ activatedRuleIds: [String], _ rules: [RulesProtocol]) {
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ fieldKey: String, _ activatedRuleIds: [String], _ rules: [RulesProtocol]) {
self.fieldKey = fieldKey
self.activatedRuleIds = activatedRuleIds
self.rules = rules

View File

@ -19,6 +19,14 @@ public class RuleAllValueChangedModel: RulesProtocol {
public var errorMessage: [String: String]?
public var fields: [String]
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(with fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Validation
//--------------------------------------------------

View File

@ -19,6 +19,14 @@ public class RuleAnyRequiredModel: RuleAnyModelProtocol {
public var fields: [String]
public var errorMessage: [String: String]?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------

View File

@ -19,6 +19,14 @@ public class RuleAnyValueChangedModel: RuleAnyModelProtocol {
public var errorMessage: [String: String]?
public var fields: [String]
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Validation
//--------------------------------------------------

View File

@ -20,6 +20,14 @@ public class RuleEqualsIgnoreCaseModel: RuleCompareModelProtocol {
public var fields: [String]
public var errorMessage: [String: String]?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Validation
//--------------------------------------------------

View File

@ -19,6 +19,14 @@ public class RuleEqualsModel: RuleCompareModelProtocol {
public var fields: [String]
public var errorMessage: [String: String]?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Validation
//--------------------------------------------------

View File

@ -18,6 +18,15 @@ public class RuleRegexModel: RulesProtocol {
public var regex: String
public var errorMessage: [String: String]?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String], regex: String) {
self.fields = fields
self.regex = regex
}
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -20,6 +20,14 @@ public class RuleRequiredModel: RulesProtocol {
public var errorMessage: [String: String]?
public var fields: [String]
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Validation
//--------------------------------------------------

View File

@ -19,7 +19,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
/// Used to layout the ui.
public lazy var stackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [tabs, line, subNavigationController.view])
let stackView = UIStackView(arrangedSubviews: [tabs, subNavigationController.view])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.isAccessibilityElement = false
stackView.axis = .vertical
@ -33,10 +33,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
return tabs
}()
public lazy var line: Line = {
return Line(model: LineModel(type: .standard), delegateObjectIVar, nil)
}()
public lazy var subNavigationController: UINavigationController = {
let subNavigationController = SubNavManagerNavigationController(rootViewController: viewController)
subNavigationController.view.translatesAutoresizingMaskIntoConstraints = false
@ -78,7 +74,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
}
hideNavigationBarLine(for: viewController)
}
required public init?(coder: NSCoder) {
@ -111,16 +106,32 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
}
}
open override func pageShown() {
// Currently not calling super until we can decouple page shown logics for managers.
hideNavigationBarLine(true)
}
open override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Notify showing view we will disappear.
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.managerWillDisappear?(self)
}
/// Hides the navigation bar for the page.
open func hideNavigationBarLine(for viewController: UIViewController) {
(viewController as? PageProtocol)?.pageModel?.navigationBar?.line?.type = .none
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
hideNavigationBarLine(true)
}
/// Hides/Shows the navigation bar for the page.
open func hideNavigationBarLine(_ isHidden: Bool) {
guard self == navigationController?.topViewController else { return }
var color = UIColor.clear
if !isHidden,
let backgroundColor = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line?.backgroundColor?.uiColor {
color = backgroundColor
}
navigationController?.navigationBar.standardAppearance.shadowColor = color
navigationController?.navigationBar.scrollEdgeAppearance?.shadowColor = color
}
open override func updateViews() {
@ -213,12 +224,12 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
index != tabs.selectedIndex else { return }
viewController = controller
pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType
hideNavigationBarLine(for: controller)
if let viewController = getCurrentViewController() {
manager?.willDisplay?(viewController)
}
tabs.selectIndex(index, animated: true)
self.index = nil
hideNavigationBarLine(true)
}
public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) {
@ -279,6 +290,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
// MARK: - MVMCoreViewManagerViewControllerProtocol
open override func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
super.viewControllerReady(inManager: manager)
// Pass on down
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.viewControllerReady?(inManager: self)
}
@ -297,15 +309,13 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
}
open func newDataReceived(in viewController: UIViewController) {
if viewController == self.viewController {
hideNavigationBarLine(for: viewController)
}
manager?.newDataReceived?(in: viewController)
hideNavigationBarLine(true)
}
public func willDisplay(_ viewController: UIViewController) {
hideNavigationBarLine(for: viewController)
manager?.willDisplay?(viewController)
hideNavigationBarLine(true)
}
public func displayedViewController(_ viewController: UIViewController) {

View File

@ -204,6 +204,7 @@ open class CoreUIModelMapping: ModelMapping {
// MARK:- LockUps
ModelRegistry.register(handler: LockUpsPlanNames.self, for: LockUpsPlanNamesModel.self)
ModelRegistry.register(handler: LockupsPlanSMLXL.self, for: LockupsPlanSMLXLModel.self)
ModelRegistry.register(handler: TitleLockup.self, for: TitleLockupModel.self)
// MARK: - Top Notifications
ModelRegistry.register(handler: NotificationView.self, for: NotificationModel.self)

View File

@ -125,8 +125,6 @@
- (void)openURLInSafariWebView:(nonnull NSURL *)url {
SFSafariViewController *safariViewController = [[SFSafariViewController alloc] initWithURL:url];
safariViewController.preferredBarTintColor = [UIColor whiteColor];
safariViewController.preferredControlTintColor = [UIColor blackColor];
[[MVMCoreNavigationHandler sharedNavigationHandler] presentViewController:safariViewController animated:YES];
}

View File

@ -217,7 +217,6 @@ B3 -> Legal
+ (nullable UIFont *)fontForHeadlineSmall:(BOOL)genericScaling;
+ (nullable UIFont *)fontForHeadlineSmall2;
+ (nullable UIFont *)fontForHeadlineSmall2:(BOOL)genericScaling;
+ (nullable UIFont *)fontForHeadlineSmall2ForWidth:(CGFloat)size;
+ (nullable UIFont *)fontB1ForWidth:(CGFloat)size;
+ (nullable UIFont *)fontForBodyWithSize:(CGFloat)size genericScaling:(BOOL)genericScaling;
+ (nullable UIFont *)fontB2ForWidth:(CGFloat)size;
@ -287,15 +286,8 @@ B3 -> Legal
+ (void)styleLabelRegularMicro:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling;
+ (void)styleLabelRegularMicro:(nonnull UILabel *)label;
/// Will style the label with mva 3.0 fonts based on the string.
+ (BOOL)styleMVA3Label:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling;
#pragma mark - 2.0 styles
/// Will style the label based on the string. Accepted values, including mva3.0 fonts and 2.0 fonts H1, H2, H3, H32, B1, B2, B3, B20
+ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style;
+ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling;
+ (void)styleLabelH1:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling;
+ (void)styleLabelH1:(nonnull UILabel *)label;
@ -377,11 +369,6 @@ B3 -> Legal
+ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string;
+ (nonnull NSAttributedString *)styleGetRegularMicroAttributedString:(nullable NSString *)string genericScaling:(BOOL)genericScaling;
/// Will style the string based on the string. Accepted values, H1, H2, H3, H32, B1, B2, B3, B20
+ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style;
+ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling;
+ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string font:(nonnull UIFont *)font color:(nonnull UIColor *)color;
+ (nonnull NSAttributedString *)styleGetH1AttributedString:(nullable NSString *)string;
+ (nonnull NSAttributedString *)styleGetH2AttributedString:(nullable NSString *)string;

View File

@ -113,27 +113,11 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
#pragma mark - 3.0 fonts
+ (nonnull UIFont *)getMVA3FontSize:(CGFloat)size bold:(BOOL)isBold {
if (isBold) {
if (size >= 15) {
return [MFFonts mfFontDSBold:size];
} else {
return [MFFonts mfFontTXBold:size];
}
} else {
if (size >= 15) {
return [MFFonts mfFontDSRegular:size];
} else {
return [MFFonts mfFontTXRegular:size];
}
}
return [self getFontForSize:size isBold:isBold];
}
+ (nonnull UIFont *)fontTitle2XLarge:(BOOL)genericScaling {
CGFloat size = 36;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"Title2XLarge" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontTitle2XLarge {
@ -141,22 +125,15 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontTitleXLarge:(BOOL)genericScaling {
CGFloat size = 32;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"TitleXLarge" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontTitleXLarge{
+ (nonnull UIFont *)fontTitleXLarge {
return [self fontTitleXLarge:YES];
}
+ (nonnull UIFont *)fontBoldTitleLarge:(BOOL)genericScaling {
CGFloat size = 24;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"BoldTitleLarge" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontBoldTitleLarge {
@ -164,11 +141,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontRegularTitleLarge:(BOOL)genericScaling {
CGFloat size = 24;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:NO];
return [self getFontForStyleString:@"RegularTitleLarge" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontRegularTitleLarge {
@ -176,11 +149,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontBoldTitleMedium:(BOOL)genericScaling {
CGFloat size = 20;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"BoldTitleMedium" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontBoldTitleMedium {
@ -188,11 +157,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontRegularTitleMedium:(BOOL)genericScaling {
CGFloat size = 20;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:NO];
return [self getFontForStyleString:@"RegularTitleMedium" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontRegularTitleMedium {
@ -200,11 +165,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontBoldBodyLarge:(BOOL)genericScaling {
CGFloat size = 16;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"BoldBodyLarge" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontBoldBodyLarge {
@ -212,11 +173,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontRegularBodyLarge:(BOOL)genericScaling {
CGFloat size = 16;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:NO];
return [self getFontForStyleString:@"RegularBodyLarge" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontRegularBodyLarge {
@ -224,11 +181,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontBoldBodySmall:(BOOL)genericScaling {
CGFloat size = 13;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"BoldBodySmall" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontBoldBodySmall {
@ -236,11 +189,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontRegularBodySmall:(BOOL)genericScaling {
CGFloat size = 13;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:NO];
return [self getFontForStyleString:@"RegularBodySmall" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontRegularBodySmall {
@ -248,11 +197,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontBoldMicro:(BOOL)genericScaling {
CGFloat size = 11;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:YES];
return [self getFontForStyleString:@"BoldMicro" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontBoldMicro {
@ -260,11 +205,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nonnull UIFont *)fontRegularMicro:(BOOL)genericScaling {
CGFloat size = 11;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [self getMVA3FontSize:size bold:NO];
return [self getFontForStyleString:@"RegularMicro" genericScaling:genericScaling];
}
+ (nonnull UIFont *)fontRegularMicro {
@ -275,11 +216,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
#pragma mark - 2.0 fonts
+ (nullable UIFont *)fontH1:(BOOL)genericScaling {
CGFloat size = 40;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont75Bd:size];
return [self getFontForStyleString:@"H1" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontH1 {
@ -287,11 +224,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontH2:(BOOL)genericScaling {
CGFloat size = 25;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont75Bd:size];
return [self getFontForStyleString:@"H2" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontH2 {
@ -299,11 +232,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontH3:(BOOL)genericScaling {
CGFloat size = 18;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont75Bd:size];
return [self getFontForStyleString:@"H3" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontH3 {
@ -311,11 +240,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontH32:(BOOL)genericScaling {
CGFloat size = 32;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont75Bd:size];
return [self getFontForStyleString:@"H32" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontH32 {
@ -323,11 +248,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontB1:(BOOL)genericScaling {
CGFloat size = 13;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont75Bd:size];
return [self getFontForStyleString:@"B1" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontB1 {
@ -335,11 +256,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontB2:(BOOL)genericScaling {
CGFloat size = 13;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont55Rg:size];
return [self getFontForStyleString:@"B2" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontB2 {
@ -347,11 +264,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontB3:(BOOL)genericScaling {
CGFloat size = 11;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont55Rg:size];
return [self getFontForStyleString:@"B3" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontB3 {
@ -359,11 +272,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontB20:(BOOL)genericScaling {
CGFloat size = 20;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont55Rg:size];
return [self getFontForStyleString:@"B20" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontB20 {
@ -412,16 +321,8 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
return [MFFonts mfFont75Bd:size];
}
+ (nullable UIFont *)fontForHeadlineSmall2ForWidth:(CGFloat)size {
CGFloat pointSize = 16;
pointSize = [[MFStyler sizeObjectGenericForCurrentDevice:pointSize] getValueBasedOnSize:size];
return [MFFonts mfFont75Bd:pointSize];
}
+ (nullable UIFont *)fontB1ForWidth:(CGFloat)size {
CGFloat pointSize = 13;
pointSize = [[MFStyler sizeObjectGenericForCurrentDevice:pointSize] getValueBasedOnSize:size];
return [MFFonts mfFont75Bd:pointSize];
return [self getFontForStyleString:@"B1" scaleValue:size];
}
+ (nullable UIFont *)fontForBodyWithSize:(CGFloat)size genericScaling:(BOOL)genericScaling {
@ -432,9 +333,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontB2ForWidth:(CGFloat)size {
CGFloat pointSize = 13;
pointSize = [[MFStyler sizeObjectGenericForCurrentDevice:pointSize] getValueBasedOnSize:size];
return [MFFonts mfFont55Rg:pointSize];
return [self getFontForStyleString:@"B2" scaleValue:size];
}
+ (nullable UIFont *)fontForBodyWithSize:(CGFloat)size forWidth:(CGFloat)width {
@ -467,47 +366,27 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontForPrimaryButton:(BOOL)genericScaling {
CGFloat size = 13;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFontTXBold:size];
return [self getFontForStyleString:@"BoldBodyLarge" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontForPrimaryButtonForWidth:(CGFloat)size {
CGFloat pointSize = 13;
pointSize = [[MFStyler sizeObjectGenericForCurrentDevice:pointSize] getValueBasedOnSize:size];
return [MFFonts mfFontTXBold:pointSize];
return [self getFontForStyleString:@"BoldBodyLarge" scaleValue:size];
}
+ (nullable UIFont *)fontForSmallButton:(BOOL)genericScaling {
CGFloat size = 11;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFontTXBold:size];
return [self getFontForStyleString:@"BoldBodySmall" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontForSmallButtonForWidth:(CGFloat)size {
CGFloat pointSize = 11;
pointSize = [[MFStyler sizeObjectGenericForCurrentDevice:pointSize] getValueBasedOnSize:size];
return [MFFonts mfFontTXBold:pointSize];
return [self getFontForStyleString:@"BoldBodySmall" scaleValue:size];
}
+ (nullable UIFont *)fontForTextField:(BOOL)genericScaling {
CGFloat size = 16;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont55Rg:size];
return [self getFontForStyleString:@"RegularBodyLarge" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontForTextFieldUnderLabel:(BOOL)genericScaling {
CGFloat size = 12;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont55Rg:size];
return [self getFontForStyleString:@"RegularBodySmall" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontForUnreadMessageOnSupport:(BOOL)genericScaling {
@ -554,11 +433,7 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
}
+ (nullable UIFont *)fontForFeedCardTitle:(BOOL)genericScaling {
CGFloat size = 16;
if (genericScaling) {
size = [self sizeFontGenericForCurrentDevice:size];
}
return [MFFonts mfFont75Bd:size];
return [self getFontForStyleString:@"BoldTitleXLarge" genericScaling:genericScaling];
}
+ (nullable UIFont *)fontForLargeLoyaltyHeaderTitle:(BOOL)genericScaling {
@ -785,77 +660,8 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
[self styleLabelRegularMicro:label genericScaling:YES];
}
+ (BOOL)styleMVA3Label:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling {
if ([style isEqualToString:@"Title2XLarge"]) {
[self styleLabelTitle2XLarge:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"TitleXLarge"]) {
[self styleLabelTitleXLarge:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"BoldTitleLarge"]) {
[self styleLabelBoldTitleLarge:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"RegularTitleLarge"]) {
[self styleLabelRegularTitleLarge:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"BoldTitleMedium"]) {
[self styleLabelBoldTitleMedium:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"RegularTitleMedium"]) {
[self styleLabelRegularTitleMedium:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"BoldBodyLarge"]) {
[self styleLabelBoldBodyLarge:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"RegularBodyLarge"]) {
[self styleLabelRegularBodyLarge:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"BoldBodySmall"]) {
[self styleLabelBoldBodySmall:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"RegularBodySmall"]) {
[self styleLabelRegularBodySmall:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"BoldMicro"]) {
[self styleLabelBoldMicro:label genericScaling:genericScaling];
return YES;
} else if ([style isEqualToString:@"RegularMicro"]) {
[self styleLabelRegularMicro:label genericScaling:genericScaling];
return YES;
} else {
return NO;
}
}
#pragma mark - 2.0 Styles
+ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling {
if ([self styleMVA3Label:label withStyle:style genericScaling:genericScaling]) {
//try mva 3.0 font first
} else if ([style isEqualToString:@"H1"]) {
[self styleLabelH1:label genericScaling:genericScaling];
} else if ([style isEqualToString:@"H2"]) {
[self styleLabelH2:label genericScaling:genericScaling];
} else if ([style isEqualToString:@"H3"]) {
[self styleLabelH3:label genericScaling:genericScaling];
} else if ([style isEqualToString:@"H32"]) {
[self styleLabelH32:label genericScaling:genericScaling];
} else if ([style isEqualToString:@"B1"]) {
[self styleLabelB1:label genericScaling:genericScaling];
} else if ([style isEqualToString:@"B3"]) {
[self styleLabelB3:label genericScaling:genericScaling];
} else if ([style isEqualToString:@"B20"]) {
[self styleLabelB20:label genericScaling:genericScaling];
} else {
[self styleLabelB2:label genericScaling:genericScaling];
}
}
+ (void)styleLabel:(nonnull UILabel *)label withStyle:(nullable NSString *)style {
[self styleLabel:label withStyle:style genericScaling:YES];
}
+ (void)styleLabelH1:(nonnull UILabel *)label genericScaling:(BOOL)genericScaling {
label.font = [MFStyler fontH1:genericScaling];
label.textColor = [UIColor blackColor];
@ -975,30 +781,6 @@ CGFloat const LabelWithInternalButtonLineSpace = 2;
#pragma mark - Attributed Strings
+ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style {
return [self styleGetAttributedString:string withStyle:style genericScaling:YES];
}
+ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string withStyle:(nullable NSString *)style genericScaling:(BOOL)genericScaling {
if ([style isEqualToString:@"H1"]) {
return [self styleGetH1AttributedString:string genericScaling:genericScaling];
} else if ([style isEqualToString:@"H2"]) {
return [self styleGetH2AttributedString:string genericScaling:genericScaling];
} else if ([style isEqualToString:@"H3"]) {
return [self styleGetH3AttributedString:string genericScaling:genericScaling];
} else if ([style isEqualToString:@"H32"]) {
return [self styleGetH32AttributedString:string genericScaling:genericScaling];
} else if ([style isEqualToString:@"B1"]) {
return [self styleGetB1AttributedString:string genericScaling:genericScaling];
} else if ([style isEqualToString:@"B3"]) {
return [self styleGetB3AttributedString:string genericScaling:genericScaling];
} else if ([style isEqualToString:@"B20"]) {
return [self styleGetB20AttributedString:string genericScaling:genericScaling];
} else {
return [self styleGetB2AttributedString:string genericScaling:genericScaling];
}
}
+ (nonnull NSAttributedString *)styleGetAttributedString:(nullable NSString *)string font:(nonnull UIFont *)font color:(nonnull UIColor *)color {
NSAttributedString *attributedString = nil;
if (![string isEqual:[NSNull null]] && string.length > 0) {

View File

@ -7,69 +7,103 @@
//
import Foundation
import UIKit
open class Styler {
// MARK:- Font Enum
public enum Font: String, Codable {
case Title2XLarge
case TitleXLarge
case BoldTitleLarge
case RegularFeatureXLarge
case BoldFeatureXLarge
case RegularFeatureLarge
case BoldFeatureLarge
case RegularFeatureMedium
case BoldFeatureMedium
case RegularFeatureSmall
case BoldFeatureSmall
case RegularFeatureXSmall
case BoldFeatureXSmall
case RegularTitle2XLarge
case BoldTitle2XLarge
case RegularTitleXLarge
case BoldTitleXLarge
case RegularTitleLarge
case BoldTitleMedium
case BoldTitleLarge
case RegularTitleMedium
case BoldBodyLarge
case BoldTitleMedium
case RegularTitleSmall
case BoldTitleSmall
case RegularBodyLarge
case BoldBodySmall
case BoldBodyLarge
case RegularBodyMedium
case BoldBodyMedium
case RegularBodySmall
case BoldMicro
case BoldBodySmall
case RegularMicro
case BoldMicro
// Legacy Fonts
case H1
case H32
case H2
case B20
case H3
case B1
case B2
case B3
case Title2XLarge // Maps to RegularTitle2XLarge
case TitleXLarge // Maps to RegularTitleXLarge
case H1 // Maps to RegularTitle2XLarge
case H32 // Maps to RegularTitleXLarge
case H2 // Maps to RegularTitleLarge
case B20 // Maps to RegularBodyLarge
case H3 // Maps to BoldTitleMedium
case B1 // Maps to BoldBodySmall
case B2 // Maps to RegularBodySmall
case B3 // Maps to RegularMicro
/// Returns the font size of the current enum case.
public func pointSize() -> CGFloat {
switch self {
case .H1:
case .RegularFeatureXLarge,
.BoldFeatureXLarge:
return 96
case .RegularFeatureLarge,
.BoldFeatureLarge:
return 80
case .RegularFeatureMedium,
.BoldFeatureMedium:
return 64
case .RegularFeatureSmall,
.BoldFeatureSmall:
return 48
case .RegularFeatureXSmall,
.BoldFeatureXSmall,
.RegularTitle2XLarge,
.BoldTitle2XLarge,
.Title2XLarge,
.H1:
return 40
case .Title2XLarge:
return 36
case .TitleXLarge, .H32:
case .RegularTitleXLarge,
.BoldTitleXLarge,
.TitleXLarge,
.H32:
return 32
case .H2:
return 25
case .BoldTitleLarge,
.RegularTitleLarge:
.RegularTitleLarge,
.H2:
return 24
case .BoldTitleMedium,
.RegularTitleMedium, .B20:
.RegularTitleMedium,
.H3:
return 20
case .H3:
return 18
case .BoldBodyLarge,
.RegularBodyLarge:
case .RegularTitleSmall,
.BoldTitleSmall,
.BoldBodyLarge,
.RegularBodyLarge,
.B20:
return 16
case .RegularBodyMedium,
.BoldBodyMedium:
return 14
case .BoldBodySmall, .B1,
.RegularBodySmall, .B2:
return 13
return 12
case .BoldMicro,
.RegularMicro, .B3:
return 11
@ -90,85 +124,38 @@ open class Styler {
public func isBold() -> Bool {
switch self {
case .RegularTitleLarge,
.RegularTitleMedium, .B20,
.RegularBodyLarge,
.RegularBodySmall, .B2,
.RegularMicro, .B3:
return false
case .H1,
.Title2XLarge,
.TitleXLarge, .H32,
.H2,
.BoldTitleLarge,
.BoldTitleMedium,
.H3,
.BoldBodyLarge,
.BoldBodySmall, .B1,
.BoldMicro:
return true
}
}
/// Determines if the current enum is a legacy or modern font.
public func isLegacyFont() -> Bool {
switch self {
case .Title2XLarge,
.TitleXLarge,
.RegularTitleLarge,
.RegularTitleMedium,
.RegularBodyLarge,
.RegularBodySmall,
.RegularMicro,
case .BoldFeatureXLarge,
.BoldFeatureLarge,
.BoldFeatureMedium,
.BoldFeatureSmall,
.BoldFeatureXSmall,
.BoldTitle2XLarge,
.BoldTitleXLarge,
.BoldTitleLarge,
.BoldTitleMedium,
.BoldTitleSmall,
.BoldBodyLarge,
.BoldBodyMedium,
.BoldBodySmall,
.BoldMicro:
return false
case .H1,
.H32,
.H2,
.H3,
.B1,
.B2,
.B3,
.B20:
.BoldMicro:
return true
default:
return false
}
}
/// Returns the font based on the declared enum case.
public func getFont(_ genericScaling: Bool = true) -> UIFont {
let size = genericScaling ? sizeFontGeneric(forCurrentDevice: pointSize()) : pointSize()
if isLegacyFont() {
switch self {
case .B2, .B3, .B20:
return MFFonts.mfFont55Rg(size)
default:
return MFFonts.mfFont75Bd(size)
}
} else {
if isBold() {
return size >= 15 ? MFFonts.mfFontDSBold(size) : MFFonts.mfFontTXBold(size)
} else {
return size >= 15 ? MFFonts.mfFontDSRegular(size) : MFFonts.mfFontTXRegular(size)
}
}
return MFStyler.getFontFor(size: size, isBold: isBold())
}
/// Styles the provided label to the declared enum Font case.
public func styleLabel(_ label: UILabel, textColor: UIColor = .mvmBlack, genericScaling: Bool = true) {
public func styleLabel(_ label: UILabel, genericScaling: Bool = true) {
label.font = getFont(genericScaling)
label.textColor = textColor
label.textColor = color()
}
}
@ -178,20 +165,33 @@ open class Styler {
case primary
case secondary
}
///MVA 3.0 - Button sizes are standard(default size), small, Tiny. Tiny button has been depricated as of Rebranding 3.0.
public enum Size: String, Codable {
case standard
case small
case tiny
func getHeight() -> CGFloat {
switch self {
case .standard:
return 42
return 44
case .small:
return 32
case .tiny:
return 20
}
}
func minimumWidth() -> CGFloat {
switch self {
case .standard:
return 76
case .small:
return 0
case .tiny:
return 49
}
}
}
}
@ -254,3 +254,38 @@ open class Styler {
}
}
}
@objc public extension MFStyler {
/// Creates the appropriate VZW font for a given size and weight.
@objc static func getFontFor(size: CGFloat, isBold: Bool) -> UIFont {
if isBold {
return size >= 13 ? MFFonts.mfFontDSBold(size) : MFFonts.mfFontTXBold(size)
} else {
return size >= 13 ? MFFonts.mfFontDSRegular(size) : MFFonts.mfFontTXRegular(size)
}
}
/// Creates the appropriate VZW font for a VDS style.
@objc static func getFontFor(styleString: String, genericScaling: Bool = true) -> UIFont? {
return Styler.Font(rawValue: styleString)?.getFont(genericScaling)
}
/// Creates the appropriate VZW font for a VDS style, scaling based on the scaleValue threshold passed in.
@objc static func getFontFor(styleString: String, scaleValue: CGFloat) -> UIFont? {
guard let font = Styler.Font(rawValue: styleString),
let size = Styler.Font(rawValue: styleString)?.pointSize(),
let newSize = Styler.sizeObjectGeneric(forCurrentDevice: size)?.getValueBased(onSize: scaleValue) else { return nil }
return getFontFor(size: newSize, isBold: font.isBold())
}
/// Styles the label accordingly to Styler.Font
@objc static func style(label: UILabel, styleString: String, genericScaling: Bool = true) {
Styler.Font(rawValue: styleString)?.styleLabel(label, genericScaling: genericScaling)
}
/// Returns an attributed string with the passed in VDS Style.
@objc static func getAttributedString(for string: String, styleString: String, genericScaling: Bool = true) -> NSAttributedString {
let font = Styler.Font(rawValue: styleString)!
return styleGetAttributedString(string, font: font.getFont(genericScaling), color: font.color())
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

View File

@ -1,23 +1,23 @@
{
"images" : [
{
"filename" : "nav_back.png",
"idiom" : "universal",
"filename" : "Back.png",
"scale" : "1x"
},
{
"filename" : "nav_back@2x.png",
"idiom" : "universal",
"filename" : "Back-1.png",
"scale" : "2x"
},
{
"filename" : "nav_back@3x.png",
"idiom" : "universal",
"filename" : "Back-2.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

View File

@ -13,16 +13,19 @@
@optional
// Show based on the object
/// Show based on the object
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
// Hides
/// Removes the notification
- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
// Collapses the notification if it has a short top message. Otherwise removes notification.
/// Collapses the notification if it has a short top message. Otherwise removes notification.
- (void)collapseNotification;
/// Updates the existing top alert with the new object
- (void)updateTopAlertWith:(nullable MVMCoreTopAlertObject *)topAlertObject;
/// Returns if the top alert is currently utilizing the status bar.
- (BOOL)overridingStatusBar;
@end

Some files were not shown because too many files have changed in this diff Show More