Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui.git into feature/ACT-192-Year-In-Review
This commit is contained in:
commit
d5783fb072
@ -126,7 +126,6 @@
|
||||
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 */; };
|
||||
22B678F929E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22B678F829E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift */; };
|
||||
@ -153,6 +152,7 @@
|
||||
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 */; };
|
||||
4B002ACA2BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+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 */; };
|
||||
@ -174,8 +174,6 @@
|
||||
5870636F2ACF238E00CA18D5 /* ReadableDecodingErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */; };
|
||||
58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */; };
|
||||
608211282AC6B57E00C3FC39 /* MVMCoreUILoggingHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */; };
|
||||
7199C8162A4F3A64001568B7 /* AccessibilityHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */; };
|
||||
71BE969E2AD96BE6000B5DB7 /* RotorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */; };
|
||||
8D070BB0241B56530099AC56 /* ListRightVariableTotalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */; };
|
||||
8D070BB2241B56AD0099AC56 /* ListRightVariableTotalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */; };
|
||||
8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */; };
|
||||
@ -302,7 +300,6 @@
|
||||
AFA4932229E5EF2E001A9663 /* NotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */; };
|
||||
AFA4933F29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */; };
|
||||
AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.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 */; };
|
||||
B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; };
|
||||
B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; };
|
||||
@ -575,9 +572,15 @@
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB891E822253FA8500022516 /* Label.swift */; };
|
||||
EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */; };
|
||||
EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */; };
|
||||
EA1758482BC97ED800A5C0D9 /* BadgeIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */; };
|
||||
EA17584A2BC97EF100A5C0D9 /* BadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */; };
|
||||
EA17584C2BC9894800A5C0D9 /* ButtonIconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */; };
|
||||
EA17584E2BC9895A00A5C0D9 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */; };
|
||||
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
|
||||
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
|
||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
||||
EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642902BCDA97300D81DC4 /* TileContainer.swift */; };
|
||||
EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */; };
|
||||
EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B942B504A43000139B4 /* ButtonGroup.swift */; };
|
||||
EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; };
|
||||
EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; };
|
||||
@ -589,7 +592,6 @@
|
||||
EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; };
|
||||
EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; };
|
||||
EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; };
|
||||
EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; };
|
||||
EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; };
|
||||
EA985C872981AB0F00F2FF2E /* VDS-Tilelet+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C862981AB0F00F2FF2E /* VDS-Tilelet+Codable.swift */; };
|
||||
EA985C892981AB7100F2FF2E /* VDS-TextStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C882981AB7100F2FF2E /* VDS-TextStyle.swift */; };
|
||||
@ -604,6 +606,7 @@
|
||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
|
||||
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
|
||||
EACCF38C2ABB346700E0F104 /* VDS-Interpreters.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */; };
|
||||
EAD715AA2BBC8FAF00DEDA6A /* VDSTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */; };
|
||||
FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -756,6 +759,7 @@
|
||||
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>"; };
|
||||
4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateDropdownEntryFieldModel+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>"; };
|
||||
@ -775,10 +779,10 @@
|
||||
5822720A2B1FC55F00F75BAE /* RotorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = "<group>"; };
|
||||
5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PollingBehaviorModel.swift; sourceTree = "<group>"; };
|
||||
5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadableDecodingErrors.swift; sourceTree = "<group>"; };
|
||||
5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui.xcconfig; sourceTree = "<group>"; };
|
||||
5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui_dev.xcconfig; sourceTree = "<group>"; };
|
||||
58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = "<group>"; };
|
||||
608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = "<group>"; };
|
||||
7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityHandler.swift; sourceTree = "<group>"; };
|
||||
71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = "<group>"; };
|
||||
8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = "<group>"; };
|
||||
8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = "<group>"; };
|
||||
8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
@ -1179,9 +1183,15 @@
|
||||
DBC4391A224421A0001AB423 /* CaretLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretLink.swift; sourceTree = "<group>"; };
|
||||
EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearableModelProtocol.swift; sourceTree = "<group>"; };
|
||||
EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeIndicator.swift; sourceTree = "<group>"; };
|
||||
EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeIndicatorModel.swift; sourceTree = "<group>"; };
|
||||
EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconModel.swift; sourceTree = "<group>"; };
|
||||
EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = "<group>"; };
|
||||
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
|
||||
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
|
||||
EA6642902BCDA97300D81DC4 /* TileContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainer.swift; sourceTree = "<group>"; };
|
||||
EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainerModel.swift; sourceTree = "<group>"; };
|
||||
EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = "<group>"; };
|
||||
EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = "<group>"; };
|
||||
EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = "<group>"; };
|
||||
@ -1208,6 +1218,7 @@
|
||||
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
|
||||
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
|
||||
EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VDS-Interpreters.swift"; sourceTree = "<group>"; };
|
||||
EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTokens.xcframework; path = ../SharedFrameworks/VDSTokens.xcframework; sourceTree = "<group>"; };
|
||||
FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -1217,10 +1228,8 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */,
|
||||
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */,
|
||||
EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */,
|
||||
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */,
|
||||
EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */,
|
||||
EAD715AA2BBC8FAF00DEDA6A /* VDSTokens.xcframework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1344,6 +1353,7 @@
|
||||
children = (
|
||||
0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */,
|
||||
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */,
|
||||
4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */,
|
||||
);
|
||||
path = "Date Dropdown";
|
||||
sourceTree = "<group>";
|
||||
@ -2081,6 +2091,7 @@
|
||||
D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */,
|
||||
EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */,
|
||||
EA985C5F2970A3F000F2FF2E /* VDS.framework */,
|
||||
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */,
|
||||
@ -2268,6 +2279,12 @@
|
||||
AA07EA922510A451009A2AE3 /* Star.swift */,
|
||||
B4CC8FBE29DF34730005D28B /* BadgeModel.swift */,
|
||||
B4CC8FBC29DF34680005D28B /* Badge.swift */,
|
||||
EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */,
|
||||
EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */,
|
||||
EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */,
|
||||
EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */,
|
||||
EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */,
|
||||
EA6642902BCDA97300D81DC4 /* TileContainer.swift */,
|
||||
EA985C3F2970939A00F2FF2E /* TileletModel.swift */,
|
||||
EA985C3D2970938F00F2FF2E /* Tilelet.swift */,
|
||||
EA7D81612B2B6E7F00D29F9E /* IconModel.swift */,
|
||||
@ -2351,6 +2368,8 @@
|
||||
D29DF31421ECECA7003B2FB9 /* SupportingFiles */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */,
|
||||
5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */,
|
||||
D29DF32721EE8736003B2FB9 /* Strings */,
|
||||
D29DF26621E6A9E4003B2FB9 /* ThirdParty */,
|
||||
D29DF31521ECECC0003B2FB9 /* Fonts */,
|
||||
@ -2684,6 +2703,7 @@
|
||||
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */,
|
||||
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */,
|
||||
D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */,
|
||||
EA17584A2BC97EF100A5C0D9 /* BadgeIndicatorModel.swift in Sources */,
|
||||
AA56A20F243C5EE900303286 /* ListTwoColumnSubsectionDividerModel.swift in Sources */,
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */,
|
||||
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
|
||||
@ -2908,6 +2928,7 @@
|
||||
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
|
||||
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
|
||||
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */,
|
||||
EA17584E2BC9895A00A5C0D9 /* ButtonIcon.swift in Sources */,
|
||||
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */,
|
||||
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
|
||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
|
||||
@ -2935,6 +2956,7 @@
|
||||
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */,
|
||||
8DE5BECD2456F7A200772E76 /* ListTwoColumnDropdownSelectorsModel.swift in Sources */,
|
||||
AA7F47732541AD560015A2C1 /* ListStarRatingModel.swift in Sources */,
|
||||
EA17584C2BC9894800A5C0D9 /* ButtonIconModel.swift in Sources */,
|
||||
AA7F47762541AD6A0015A2C1 /* ListStarRating.swift in Sources */,
|
||||
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
|
||||
AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */,
|
||||
@ -2989,6 +3011,7 @@
|
||||
D264FAAC2441009400D98315 /* RadioBoxCollectionViewCell.swift in Sources */,
|
||||
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */,
|
||||
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */,
|
||||
EA1758482BC97ED800A5C0D9 /* BadgeIndicator.swift in Sources */,
|
||||
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */,
|
||||
0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */,
|
||||
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
|
||||
@ -3053,6 +3076,7 @@
|
||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
|
||||
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
|
||||
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */,
|
||||
EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */,
|
||||
AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */,
|
||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
|
||||
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
|
||||
@ -3086,6 +3110,7 @@
|
||||
8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */,
|
||||
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */,
|
||||
0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */,
|
||||
4B002ACA2BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift in Sources */,
|
||||
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */,
|
||||
01F2C20427C81F9700DC3D36 /* SubNavInteractor.swift.swift in Sources */,
|
||||
D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */,
|
||||
@ -3179,6 +3204,7 @@
|
||||
D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */,
|
||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
||||
EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */,
|
||||
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
|
||||
27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */,
|
||||
EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */,
|
||||
@ -3236,6 +3262,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D29DF0D221E404D4003B2FB9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
@ -3294,7 +3321,7 @@
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@ -3303,6 +3330,7 @@
|
||||
};
|
||||
D29DF0D321E404D4003B2FB9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
import MVMCore
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
|
||||
open class Link: VDS.TextLink, VDSMoleculeViewProtocol {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
import MVMCore
|
||||
import Combine
|
||||
@ -36,7 +36,7 @@ open class PillButton: VDS.Button, MVMCoreUIViewConstrainingProtocol, MFButtonPr
|
||||
text = viewModel.title
|
||||
isEnabled = viewModel.enabled
|
||||
size = viewModel.size
|
||||
use = viewModel.style ?? .primary
|
||||
use = viewModel.style
|
||||
surface = viewModel.inverted ? .dark : .light
|
||||
if let accessibilityText = viewModel.accessibilityText {
|
||||
accessibilityLabel = accessibilityText
|
||||
|
||||
@ -16,12 +16,6 @@ import UIKit
|
||||
|
||||
public weak var datePicker: UIDatePicker?
|
||||
|
||||
private var calendar: Calendar = {
|
||||
var calendar: Calendar = .current
|
||||
calendar.timeZone = NSTimeZone.system
|
||||
return calendar
|
||||
}()
|
||||
|
||||
public var dateFormat: String? {
|
||||
get { dateDropdownModel?.dateFormat }
|
||||
set {
|
||||
@ -97,7 +91,7 @@ import UIKit
|
||||
|
||||
dateDropdownModel?.date = date
|
||||
|
||||
if calendar.isDate(date, inSameDayAs: Date()) {
|
||||
if let isToday = dateDropdownModel?.isSelectedToday(), isToday {
|
||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||
} else {
|
||||
text = dateDropdownModel?.dateFormatter.string(from: date)
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
//
|
||||
// DateDropdownEntryFieldModel+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Xi Zhang on 4/23/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension DateDropdownEntryFieldModel {
|
||||
|
||||
public func isSelectedToday() -> Bool {
|
||||
|
||||
guard let date = date else {
|
||||
return false
|
||||
}
|
||||
|
||||
return calendar.isDate(date, inSameDayAs: Date())
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,12 @@
|
||||
public var minDate: Date?
|
||||
public var maxDate: Date?
|
||||
|
||||
var calendar: Calendar = {
|
||||
var calendar: Calendar = .current
|
||||
calendar.timeZone = NSTimeZone.system
|
||||
return calendar
|
||||
}()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -7,8 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSFormControlsTokens
|
||||
import VDSTokens
|
||||
|
||||
@objcMembers open class RadioButton: Control, MFButtonProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
70
MVMCoreUI/Atomic/Atoms/Views/BadgeIndicator.swift
Normal file
70
MVMCoreUI/Atomic/Atoms/Views/BadgeIndicator.swift
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// BadgeIndicator.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 4/12/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
open class BadgeIndicator: VDS.BadgeIndicator, VDSMoleculeViewProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public var viewModel: BadgeIndicatorModel!
|
||||
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
public var additionalData: [AnyHashable : Any]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
public func viewModelDidUpdate() {
|
||||
surface = viewModel.surface
|
||||
number = viewModel.number
|
||||
fillColor = viewModel.fillColor
|
||||
borderColorLight = viewModel.borderColorLight?.uiColor
|
||||
borderColorDark = viewModel.borderColorDark?.uiColor
|
||||
kind = viewModel.kind
|
||||
maximumDigits = viewModel.maximumDigits
|
||||
size = viewModel.size
|
||||
leadingCharacter = viewModel.leadingCharacter
|
||||
trailingText = viewModel.trailingText
|
||||
dotSize = viewModel.dotSize
|
||||
verticalPadding = viewModel.verticalPadding
|
||||
horizontalPadding = viewModel.horizontalPadding
|
||||
hideDot = viewModel.hideDot
|
||||
hideBorder = viewModel.hideBorder
|
||||
width = viewModel.width
|
||||
height = viewModel.height
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
|
||||
if let viewModel {
|
||||
if let accessibilityText = viewModel.accessibilityText {
|
||||
self.accessibilityLabel = accessibilityText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//to deal with how it's parent constrains this control
|
||||
extension BadgeIndicator: MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
public func needsToBeConstrained() -> Bool { true }
|
||||
|
||||
public func horizontalAlignment() -> UIStackView.Alignment { .leading }
|
||||
}
|
||||
111
MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift
Normal file
111
MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift
Normal file
@ -0,0 +1,111 @@
|
||||
//
|
||||
// BadgeIndicatorModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 4/12/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
|
||||
open class BadgeIndicatorModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String { "badgeIndicator" }
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - VDS Properties
|
||||
//--------------------------------------------------
|
||||
public var surface: Surface { inverted ? .dark : .light }
|
||||
public var inverted: Bool = false
|
||||
public var number: Int?
|
||||
public var accessibilityText: String?
|
||||
public var fillColor = BadgeIndicator.FillColor.red
|
||||
public var borderColorLight: Color?
|
||||
public var borderColorDark: Color?
|
||||
public var kind = BadgeIndicator.Kind.simple
|
||||
public var maximumDigits = BadgeIndicator.MaximumDigits.two
|
||||
public var size = BadgeIndicator.Size.xxlarge
|
||||
public var leadingCharacter: String?
|
||||
public var trailingText: String?
|
||||
public var dotSize: CGFloat?
|
||||
public var verticalPadding: CGFloat?
|
||||
public var horizontalPadding: CGFloat?
|
||||
public var hideDot: Bool = false
|
||||
public var hideBorder: Bool = false
|
||||
public var width: CGFloat?
|
||||
public var height: CGFloat?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case inverted
|
||||
case accessibilityText
|
||||
case number
|
||||
case fillColor
|
||||
case borderColorLight
|
||||
case borderColorDark
|
||||
case kind
|
||||
case maximumDigits
|
||||
case size
|
||||
case leadingCharacter
|
||||
case trailingText
|
||||
case dotSize
|
||||
case verticalPadding
|
||||
case horizontalPadding
|
||||
case hideDot
|
||||
case hideBorder
|
||||
case width
|
||||
case height
|
||||
}
|
||||
|
||||
required public convenience init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.init()
|
||||
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
|
||||
accessibilityText = try container.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
number = try container.decodeIfPresent(Int.self, forKey: .number)
|
||||
fillColor = try container.decodeIfPresent(BadgeIndicator.FillColor.self, forKey: .fillColor) ?? .red
|
||||
borderColorLight = try container.decodeIfPresent(Color.self, forKey: .borderColorLight)
|
||||
borderColorDark = try container.decodeIfPresent(Color.self, forKey: .borderColorDark)
|
||||
kind = try container.decodeIfPresent(BadgeIndicator.Kind.self, forKey: .kind) ?? .simple
|
||||
maximumDigits = try container.decodeIfPresent(BadgeIndicator.MaximumDigits.self, forKey: .maximumDigits) ?? .two
|
||||
size = try container.decodeIfPresent(BadgeIndicator.Size.self, forKey: .size) ?? .xxlarge
|
||||
leadingCharacter = try container.decodeIfPresent(String.self, forKey: .leadingCharacter)
|
||||
trailingText = try container.decodeIfPresent(String.self, forKey: .trailingText)
|
||||
dotSize = try container.decodeIfPresent(CGFloat.self, forKey: .dotSize)
|
||||
verticalPadding = try container.decodeIfPresent(CGFloat.self, forKey: .verticalPadding)
|
||||
horizontalPadding = try container.decodeIfPresent(CGFloat.self, forKey: .horizontalPadding)
|
||||
hideDot = try container.decodeIfPresent(Bool.self, forKey: .hideDot) ?? false
|
||||
hideBorder = try container.decodeIfPresent(Bool.self, forKey: .hideBorder) ?? false
|
||||
width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
|
||||
height = try container.decodeIfPresent(CGFloat.self, forKey: .height)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(number, forKey: .number)
|
||||
try container.encodeIfPresent(fillColor, forKey: .fillColor)
|
||||
try container.encodeIfPresent(borderColorLight, forKey: .borderColorLight)
|
||||
try container.encodeIfPresent(borderColorDark, forKey: .borderColorDark)
|
||||
try container.encodeIfPresent(kind, forKey: .kind)
|
||||
try container.encodeIfPresent(maximumDigits, forKey: .maximumDigits)
|
||||
try container.encodeIfPresent(size, forKey: .size)
|
||||
try container.encodeIfPresent(leadingCharacter, forKey: .leadingCharacter)
|
||||
try container.encodeIfPresent(trailingText, forKey: .trailingText)
|
||||
try container.encodeIfPresent(dotSize, forKey: .dotSize)
|
||||
try container.encodeIfPresent(verticalPadding, forKey: .verticalPadding)
|
||||
try container.encodeIfPresent(hideDot, forKey: .hideDot)
|
||||
try container.encodeIfPresent(hideBorder, forKey: .hideBorder)
|
||||
try container.encodeIfPresent(width, forKey: .width)
|
||||
try container.encodeIfPresent(height, forKey: .height)
|
||||
}
|
||||
}
|
||||
80
MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift
Normal file
80
MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift
Normal file
@ -0,0 +1,80 @@
|
||||
//
|
||||
// ButtonIcon.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 4/12/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
open class ButtonIcon: VDS.ButtonIcon, VDSMoleculeViewProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public var viewModel: ButtonIconModel!
|
||||
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
public var additionalData: [AnyHashable : Any]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
public func viewModelDidUpdate() {
|
||||
surface = viewModel.surface
|
||||
|
||||
onClick = { [weak self] control in
|
||||
guard let self, let viewModel = self.viewModel else { return }
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: viewModel.action,
|
||||
sourceModel: viewModel,
|
||||
additionalData: self.additionalData,
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
|
||||
badgeIndicatorModel = viewModel.badgeIndicatorModel
|
||||
kind = viewModel.kind
|
||||
surfaceType = viewModel.surfaceType
|
||||
iconName = viewModel.iconName
|
||||
selectedIconName = viewModel.selectedIconName
|
||||
size = viewModel.size
|
||||
customSize = viewModel.customSize
|
||||
floating = viewModel.floating
|
||||
fitToIcon = viewModel.fitToIcon
|
||||
hideBorder = viewModel.hideBorder
|
||||
showBadgeIndicator = viewModel.showBadgeIndicator
|
||||
selectable = viewModel.selectable
|
||||
iconOffset = viewModel.iconOffset
|
||||
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
|
||||
if let viewModel {
|
||||
if let accessibilityText = viewModel.accessibilityText {
|
||||
//since this is a container control and the
|
||||
//icon & badgeIndicator (gets from it's own model) are traversed separatly
|
||||
icon.accessibilityLabel = accessibilityText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//to deal with how it's parent constrains this control
|
||||
extension ButtonIcon: MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
public func needsToBeConstrained() -> Bool { true }
|
||||
|
||||
public func horizontalAlignment() -> UIStackView.Alignment { .leading }
|
||||
}
|
||||
|
||||
142
MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift
Normal file
142
MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift
Normal file
@ -0,0 +1,142 @@
|
||||
//
|
||||
// ButtonIconModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 4/12/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
open class ButtonIconModel: ButtonModelProtocol, MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "buttonIcon"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - VDS Properties
|
||||
//--------------------------------------------------
|
||||
public var surface: Surface { inverted ? .dark : .light }
|
||||
public var inverted: Bool = false
|
||||
public var accessibilityText: String?
|
||||
|
||||
public var action: ActionModelProtocol
|
||||
|
||||
public var kind = ButtonIcon.Kind.ghost
|
||||
public var surfaceType = ButtonIcon.SurfaceType.colorFill
|
||||
public var iconName: Icon.Name = .info
|
||||
public var selectedIconName: Icon.Name?
|
||||
public var size = ButtonIcon.Size.large
|
||||
public var customSize : Int?
|
||||
public var floating: Bool = false
|
||||
public var fitToIcon: Bool = false
|
||||
public var hideBorder: Bool = true
|
||||
public var showBadgeIndicator: Bool = false
|
||||
public var selectable: Bool = false
|
||||
public var iconOffset: CGPoint = .zero
|
||||
|
||||
public var badgeIndicatorModel: VDS.ButtonIcon.BadgeIndicatorModel? {
|
||||
guard let model = badgeIndicator else { return nil }
|
||||
return .init(kind: model.kind,
|
||||
fillColor: model.fillColor,
|
||||
expandDirection: expandDirection,
|
||||
size: model.size,
|
||||
maximumDigits: model.maximumDigits,
|
||||
width: model.width,
|
||||
height: model.height,
|
||||
number: model.number,
|
||||
leadingCharacter: model.leadingCharacter,
|
||||
trailingText: model.trailingText,
|
||||
dotSize: model.dotSize,
|
||||
verticalPadding: model.verticalPadding,
|
||||
horizontalPadding: model.horizontalPadding,
|
||||
hideDot: model.hideDot,
|
||||
hideBorder: model.hideBorder)
|
||||
}
|
||||
|
||||
private var badgeIndicator: BadgeIndicatorModel?
|
||||
private var expandDirection = ButtonIcon.BadgeIndicatorModel.ExpandDirection.right
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
public init(with iconName: VDS.Icon.Name, action: ActionModelProtocol) {
|
||||
self.iconName = iconName
|
||||
self.action = action
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case inverted
|
||||
case accessibilityText
|
||||
case action
|
||||
case badgeIndicator
|
||||
case expandDirection
|
||||
case kind
|
||||
case surfaceType
|
||||
case iconName
|
||||
case selectedIconName
|
||||
case size
|
||||
case customSize
|
||||
case floating
|
||||
case fitToIcon
|
||||
case hideBorder
|
||||
case showBadgeIndicator
|
||||
case selectable
|
||||
case iconOffset
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
action = try container.decodeModel(codingKey: .action)
|
||||
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
|
||||
accessibilityText = try container.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
badgeIndicator = try container.decodeIfPresent(BadgeIndicatorModel.self, forKey: .badgeIndicator)
|
||||
expandDirection = try container.decodeIfPresent(ButtonIcon.BadgeIndicatorModel.ExpandDirection.self, forKey: .expandDirection) ?? .right
|
||||
kind = try container.decodeIfPresent(ButtonIcon.Kind.self, forKey: .kind) ?? .ghost
|
||||
surfaceType = try container.decodeIfPresent(ButtonIcon.SurfaceType.self, forKey: .kind) ?? .colorFill
|
||||
iconName = try container.decode(Icon.Name.self, forKey: .iconName)
|
||||
selectedIconName = try container.decodeIfPresent(Icon.Name.self, forKey: .selectedIconName)
|
||||
size = try container.decodeIfPresent(ButtonIcon.Size.self, forKey: .size) ?? .large
|
||||
customSize = try container.decodeIfPresent(Int.self, forKey: .customSize)
|
||||
floating = try container.decodeIfPresent(Bool.self, forKey: .floating) ?? false
|
||||
fitToIcon = try container.decodeIfPresent(Bool.self, forKey: .fitToIcon) ?? false
|
||||
hideBorder = try container.decodeIfPresent(Bool.self, forKey: .hideBorder) ?? false
|
||||
showBadgeIndicator = try container.decodeIfPresent(Bool.self, forKey: .showBadgeIndicator) ?? false
|
||||
selectable = try container.decodeIfPresent(Bool.self, forKey: .selectable) ?? false
|
||||
iconOffset = try container.decodeIfPresent(CGPoint.self, forKey: .iconOffset) ?? .zero
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(badgeIndicator, forKey: .badgeIndicator)
|
||||
try container.encodeIfPresent(expandDirection, forKey: .expandDirection)
|
||||
try container.encodeIfPresent(kind, forKey: .kind)
|
||||
try container.encodeIfPresent(surfaceType, forKey: .kind)
|
||||
try container.encode(iconName, forKey: .iconName)
|
||||
try container.encodeIfPresent(selectedIconName, forKey: .selectedIconName)
|
||||
try container.encodeIfPresent(size, forKey: .size)
|
||||
try container.encodeIfPresent(customSize, forKey: .customSize)
|
||||
try container.encodeIfPresent(floating, forKey: .floating)
|
||||
try container.encodeIfPresent(fitToIcon, forKey: .fitToIcon)
|
||||
try container.encodeIfPresent(hideBorder, forKey: .hideBorder)
|
||||
try container.encodeIfPresent(showBadgeIndicator, forKey: .showBadgeIndicator)
|
||||
try container.encodeIfPresent(selectable, forKey: .selectable)
|
||||
try container.encodeIfPresent(iconOffset, forKey: .iconOffset)
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
// Created by Kevin Christiano on 1/30/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
open class CarouselIndicator: Control, CarouselPageControlProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -64,9 +64,8 @@
|
||||
bottomLabelConstraint.isActive = true
|
||||
|
||||
alignCheckbox(.center)
|
||||
isAccessibilityElement = true
|
||||
accessibilityHint = checkbox.accessibilityHint
|
||||
accessibilityTraits = checkbox.accessibilityTraits
|
||||
isAccessibilityElement = false
|
||||
accessibilityElements = [checkbox, label]
|
||||
observation = observe(\.checkbox.isSelected, options: [.new]) { [weak self] _, _ in
|
||||
self?.updateAccessibilityLabel()
|
||||
}
|
||||
@ -139,6 +138,8 @@
|
||||
|
||||
open func updateAccessibilityLabel() {
|
||||
checkbox.updateAccessibilityLabel()
|
||||
accessibilityLabel = [checkbox.accessibilityLabel, label.text].compactMap { $0 }.joined(separator: ",")
|
||||
if let text = label.text {
|
||||
checkbox.accessibilityLabel?.append(", \(text)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
open class IconModel: MoleculeModelProtocol {
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
|
||||
public class LineModel: MoleculeModelProtocol, Invertable {
|
||||
|
||||
139
MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift
Normal file
139
MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift
Normal file
@ -0,0 +1,139 @@
|
||||
//
|
||||
// TileContainer.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 4/15/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
import Combine
|
||||
|
||||
open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var model: MoleculeModelProtocol?
|
||||
|
||||
public var viewModel: TileContainerModel!
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
public var additionalData: [AnyHashable: Any]?
|
||||
|
||||
public var molecule: MoleculeViewProtocol? {
|
||||
willSet {
|
||||
if newValue == nil {
|
||||
molecule?.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
public convenience required init() {
|
||||
self.init(frame: .zero)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public
|
||||
//--------------------------------------------------
|
||||
public func viewModelDidUpdate() {
|
||||
|
||||
if let moleculeModel = viewModel.molecule {
|
||||
if let molecule,
|
||||
moleculeModel.moleculeName == molecule.model?.moleculeName {
|
||||
molecule.set(with: moleculeModel, delegateObject, additionalData)
|
||||
} else if let moleculeView = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
molecule = moleculeView
|
||||
addContentView(moleculeView)
|
||||
}
|
||||
}
|
||||
|
||||
// set backgroundImage
|
||||
if let imageName = viewModel.backgroundImage {
|
||||
loadImage(imageName)
|
||||
}
|
||||
|
||||
//set action
|
||||
if let action = viewModel.action {
|
||||
//add the subscriber
|
||||
onClick = { [weak self] control in
|
||||
guard let self, let viewModel = self.viewModel else { return }
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: action,
|
||||
sourceModel: viewModel,
|
||||
additionalData: self.additionalData,
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
//set the rest of the properties
|
||||
surface = viewModel.surface
|
||||
imageFallbackColor = viewModel.imageFallbackColor
|
||||
width = viewModel.width
|
||||
height = viewModel.height
|
||||
showBorder = viewModel.showBorder
|
||||
showDropShadow = viewModel.showDropShadow
|
||||
padding = viewModel.padding
|
||||
color = viewModel.color
|
||||
aspectRatio = viewModel.aspectRatio
|
||||
backgroundEffect = viewModel.backgroundEffect
|
||||
}
|
||||
|
||||
private func loadImage(_ imageName: String? = nil) {
|
||||
guard let imageName else {
|
||||
if backgroundImage != nil {
|
||||
backgroundImage = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.backgroundImage = image
|
||||
})}
|
||||
MVMCoreCache.shared()?.getImage(imageName, useWidth: false, widthForS7: 0, useHeight: false, heightForS7: 0, format: nil, localFallbackImageName: nil, allowServerQueryParameters: false, localBundle: nil, completionHandler: finishedLoadingBlock)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
//--------------------------------------------------
|
||||
open func updateView(_ size: CGFloat) {}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
//since this is a class func, we can't reference it directly
|
||||
public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
100
|
||||
}
|
||||
|
||||
/// Allows the molecule to set its name for reuse. Default could be moleculeName. Mainly used for list or collections.
|
||||
public static func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
// This will aggregate names of molecules to make an id.
|
||||
guard let containerModel = model as? TileContainerModel,
|
||||
let molecule = containerModel.molecule,
|
||||
let moleculeClass = ModelRegistry.getMoleculeClass(molecule),
|
||||
let moleculeName = moleculeClass.nameForReuse(with: molecule, delegateObject)
|
||||
else { return "\(model.moleculeName)<>" }
|
||||
|
||||
return "\(model.moleculeName)<\(moleculeName)>"
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any collection size changes
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else { return }
|
||||
self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TileContainer: MVMCoreUIViewConstrainingProtocol {
|
||||
public func horizontalAlignment() -> UIStackView.Alignment { .leading }
|
||||
}
|
||||
117
MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift
Normal file
117
MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift
Normal file
@ -0,0 +1,117 @@
|
||||
//
|
||||
// TileContainerModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 4/15/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
open class TileContainerModel: TileContainerBaseModel<TileContainer.Padding, TileContainer>, ParentMoleculeModelProtocol, MoleculeModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "tileContainer"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
|
||||
public var molecule: MoleculeModelProtocol?
|
||||
public var children: [any MoleculeModelProtocol] {
|
||||
guard let molecule else { return [] }
|
||||
return [molecule]
|
||||
}
|
||||
|
||||
public func replaceChildMolecule(with molecule: MoleculeModelProtocol) throws -> Bool {
|
||||
return try replaceChildMolecule(at: &self.molecule, with: molecule)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case molecule
|
||||
}
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
molecule = try container.decodeModelIfPresent(codingKey: .molecule)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeModelIfPresent(molecule, forKey: .molecule)
|
||||
try super.encode(to: encoder)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open class TileContainerBaseModel<PaddingType: DefaultValuing & Codable, TileContainerType:TileContainerBase<PaddingType>> : Codable{
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public var inverted: Bool = false
|
||||
public var backgroundImage: String?
|
||||
public var action: ActionModelProtocol?
|
||||
public var imageFallbackColor: Surface = .light
|
||||
public var width: CGFloat?
|
||||
public var height: CGFloat?
|
||||
public var showBorder: Bool = false
|
||||
public var showDropShadow: Bool = false
|
||||
public var padding = PaddingType.defaultValue
|
||||
public var color: TileContainerType.BackgroundColor = .black
|
||||
public var aspectRatio: TileContainerType.AspectRatio = .ratio1x1
|
||||
public var backgroundEffect: TileContainerType.BackgroundEffect = .none
|
||||
public var surface: Surface { inverted ? .dark : .light }
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case inverted
|
||||
case backgroundImage
|
||||
case action
|
||||
case imageFallbackColor
|
||||
case width
|
||||
case height
|
||||
case showBorder
|
||||
case showDropShadow
|
||||
case padding
|
||||
case color
|
||||
case aspectRatio
|
||||
case backgroundEffect
|
||||
}
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
|
||||
backgroundImage = try container.decodeIfPresent(String.self, forKey: .backgroundImage)
|
||||
action = try container.decodeModelIfPresent(codingKey: .action)
|
||||
imageFallbackColor = try container.decodeIfPresent(VDS.Surface.self, forKey: .imageFallbackColor) ?? .light
|
||||
width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
|
||||
height = try container.decodeIfPresent(CGFloat.self, forKey: .height)
|
||||
showBorder = try container.decodeIfPresent(Bool.self, forKey: .showBorder) ?? false
|
||||
showDropShadow = try container.decodeIfPresent(Bool.self, forKey: .showDropShadow) ?? false
|
||||
padding = try container.decodeIfPresent(PaddingType.self, forKey: .padding) ?? PaddingType.defaultValue
|
||||
color = try container.decodeIfPresent(TileContainerType.BackgroundColor.self, forKey: .color) ?? .black
|
||||
aspectRatio = try container.decodeIfPresent(TileContainerType.AspectRatio.self, forKey: .aspectRatio) ?? .ratio1x1
|
||||
backgroundEffect = try container.decodeIfPresent(TileContainerType.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none
|
||||
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(backgroundImage, forKey: .backgroundImage)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try container.encodeIfPresent(imageFallbackColor, forKey: .imageFallbackColor)
|
||||
try container.encodeIfPresent(width, forKey: .width)
|
||||
try container.encodeIfPresent(height, forKey: .height)
|
||||
try container.encodeIfPresent(showBorder, forKey: .showBorder)
|
||||
try container.encodeIfPresent(showDropShadow, forKey: .showDropShadow)
|
||||
try container.encodeIfPresent(padding, forKey: .padding)
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio)
|
||||
try container.encodeIfPresent(backgroundEffect, forKey: .backgroundEffect)
|
||||
}
|
||||
}
|
||||
@ -39,10 +39,7 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{
|
||||
// MARK: - Public
|
||||
//--------------------------------------------------
|
||||
public func viewModelDidUpdate() {
|
||||
color = viewModel.color
|
||||
padding = viewModel.padding
|
||||
aspectRatio = viewModel.aspectRatio
|
||||
width = viewModel.width
|
||||
//tilelet specific properties
|
||||
if let value = viewModel.textWidth {
|
||||
textWidth = .value(value)
|
||||
} else if let percentage = viewModel.textPercentage {
|
||||
@ -64,6 +61,51 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
// TileContainer properties
|
||||
// set backgroundImage
|
||||
if let imageName = viewModel.backgroundImage {
|
||||
loadImage(imageName)
|
||||
}
|
||||
|
||||
//set action
|
||||
if let action = viewModel.action {
|
||||
//add the subscriber
|
||||
onClick = { [weak self] control in
|
||||
guard let self, let viewModel = self.viewModel else { return }
|
||||
MVMCoreUIActionHandler.performActionUnstructured(with: action,
|
||||
sourceModel: viewModel,
|
||||
additionalData: self.additionalData,
|
||||
delegateObject: self.delegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
//set the rest of the properties
|
||||
surface = viewModel.surface
|
||||
imageFallbackColor = viewModel.imageFallbackColor
|
||||
width = viewModel.width
|
||||
height = viewModel.height
|
||||
showBorder = viewModel.showBorder
|
||||
showDropShadow = viewModel.showDropShadow
|
||||
padding = viewModel.padding
|
||||
color = viewModel.color
|
||||
aspectRatio = viewModel.aspectRatio
|
||||
backgroundEffect = viewModel.backgroundEffect
|
||||
}
|
||||
|
||||
private func loadImage(_ imageName: String? = nil) {
|
||||
guard let imageName else {
|
||||
if backgroundImage != nil {
|
||||
backgroundImage = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.backgroundImage = image
|
||||
})}
|
||||
MVMCoreCache.shared()?.getImage(imageName, useWidth: false, widthForS7: 0, useHeight: false, heightForS7: 0, format: nil, localFallbackImageName: nil, allowServerQueryParameters: false, localBundle: nil, completionHandler: finishedLoadingBlock)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
open class TileletModel: MoleculeModelProtocol {
|
||||
open class TileletModel: TileContainerBaseModel<Tilelet.Padding, Tilelet>, MoleculeModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
@ -17,52 +17,37 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tilelet"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var color: Tilelet.BackgroundColor
|
||||
public var padding: Tilelet.Padding
|
||||
public var aspectRatio: Tilelet.AspectRatio
|
||||
|
||||
public var badge: Tilelet.BadgeModel?
|
||||
public var title: LabelModel?
|
||||
public var subTitle: LabelModel?
|
||||
public var descriptiveIcon: Tilelet.DescriptiveIcon?
|
||||
public var directionalIcon: Tilelet.DirectionalIcon?
|
||||
public var width: CGFloat?
|
||||
public var textWidth: CGFloat?
|
||||
public var textPercentage: CGFloat?
|
||||
public var action: ActionModelProtocol?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case color
|
||||
case padding
|
||||
case aspectRatio
|
||||
case badge
|
||||
case title
|
||||
case subTitle
|
||||
case descriptiveIcon
|
||||
case directionalIcon
|
||||
case width
|
||||
case textWidth
|
||||
case textPercentage
|
||||
case action
|
||||
}
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
self.backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
self.color = try container.decodeIfPresent(Tilelet.BackgroundColor.self, forKey: .color) ?? Tilelet.BackgroundColor.black
|
||||
self.padding = try container.decodeIfPresent(Tilelet.Padding.self, forKey: .padding) ?? Tilelet.Padding.small
|
||||
self.aspectRatio = try container.decodeIfPresent(Tilelet.AspectRatio.self, forKey: .aspectRatio) ?? Tilelet.AspectRatio.none
|
||||
self.badge = try container.decodeIfPresent(Tilelet.BadgeModel.self, forKey: .badge)
|
||||
self.title = try container.decodeIfPresent(LabelModel.self, forKey: .title)
|
||||
self.subTitle = try container.decodeIfPresent(LabelModel.self, forKey: .subTitle)
|
||||
self.descriptiveIcon = try container.decodeIfPresent(Tilelet.DescriptiveIcon.self, forKey: .descriptiveIcon)
|
||||
self.directionalIcon = try container.decodeIfPresent(Tilelet.DirectionalIcon.self, forKey: .directionalIcon)
|
||||
self.width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
|
||||
self.textWidth = try container.decodeIfPresent(CGFloat.self, forKey: .textWidth)
|
||||
self.textPercentage = try container.decodeIfPresent(CGFloat.self, forKey: .textPercentage)
|
||||
action = try container.decodeModelIfPresent(codingKey: .action)
|
||||
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
badge = try container.decodeIfPresent(Tilelet.BadgeModel.self, forKey: .badge)
|
||||
title = try container.decodeIfPresent(LabelModel.self, forKey: .title)
|
||||
subTitle = try container.decodeIfPresent(LabelModel.self, forKey: .subTitle)
|
||||
descriptiveIcon = try container.decodeIfPresent(Tilelet.DescriptiveIcon.self, forKey: .descriptiveIcon)
|
||||
directionalIcon = try container.decodeIfPresent(Tilelet.DirectionalIcon.self, forKey: .directionalIcon)
|
||||
textWidth = try container.decodeIfPresent(CGFloat.self, forKey: .textWidth)
|
||||
textPercentage = try container.decodeIfPresent(CGFloat.self, forKey: .textPercentage)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public func titleModel(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Tilelet.TitleModel? {
|
||||
@ -99,22 +84,17 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
return .init(text: subTitle.text, textAttributes: attrs)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
try container.encodeIfPresent(padding, forKey: .padding)
|
||||
try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio)
|
||||
try container.encodeIfPresent(badge, forKey: .badge)
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeIfPresent(subTitle, forKey: .subTitle)
|
||||
try container.encodeIfPresent(descriptiveIcon, forKey: .descriptiveIcon)
|
||||
try container.encodeIfPresent(directionalIcon, forKey: .directionalIcon)
|
||||
try container.encodeIfPresent(width, forKey: .width)
|
||||
try container.encodeIfPresent(textWidth, forKey: .textWidth)
|
||||
try container.encodeIfPresent(textPercentage, forKey: .textPercentage)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try super.encode(to: encoder)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import MVMCore
|
||||
|
||||
open class TooltipModel: MoleculeModelProtocol {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codable Extensions
|
||||
@ -16,6 +16,14 @@ import VDSColorTokens
|
||||
|
||||
extension VDS.Surface: Codable {}
|
||||
extension VDS.Badge.FillColor: Codable {}
|
||||
extension VDS.BadgeIndicator.FillColor: Codable {}
|
||||
extension VDS.BadgeIndicator.Kind: Codable {}
|
||||
extension VDS.BadgeIndicator.MaximumDigits: Codable {}
|
||||
extension VDS.BadgeIndicator.Size: Codable {}
|
||||
extension VDS.ButtonIcon.Kind: Codable {}
|
||||
extension VDS.ButtonIcon.Size: Codable {}
|
||||
extension VDS.ButtonIcon.BadgeIndicatorModel.ExpandDirection: Codable {}
|
||||
extension VDS.ButtonIcon.SurfaceType: Codable {}
|
||||
extension VDS.ButtonGroup.Alignment: Codable {}
|
||||
extension VDS.Icon.Name: Codable {}
|
||||
extension VDS.Icon.Size: Codable {}
|
||||
@ -92,6 +100,53 @@ extension VDS.TileContainerBase.BackgroundColor: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
extension VDS.TileContainerBase.BackgroundEffect: Codable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case type
|
||||
case firstColor
|
||||
case secondColor
|
||||
}
|
||||
|
||||
enum BackgroundEffectType: String, Codable {
|
||||
case transparency
|
||||
case none
|
||||
case gradient
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let type = try container.decode(BackgroundEffectType.self, forKey: .type)
|
||||
|
||||
switch type {
|
||||
case .transparency:
|
||||
self = .transparency
|
||||
case .none:
|
||||
self = .none
|
||||
case .gradient:
|
||||
let firstColor = try container.decode(String.self, forKey: .firstColor)
|
||||
let secondColor = try container.decode(String.self, forKey: .secondColor)
|
||||
self = .gradient(firstColor, secondColor)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
switch self {
|
||||
case .transparency:
|
||||
try container.encode(BackgroundEffectType.transparency.rawValue, forKey: .type)
|
||||
case .none:
|
||||
try container.encode(BackgroundEffectType.none.rawValue, forKey: .type)
|
||||
case .gradient(let firstColor, let secondColor):
|
||||
try container.encode(BackgroundEffectType.gradient.rawValue, forKey: .type)
|
||||
try container.encode(firstColor, forKey: .firstColor)
|
||||
try container.encode(secondColor, forKey: .secondColor)
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension VDS.TileContainer.Padding: Codable {
|
||||
enum PaddingError: Error {
|
||||
case valueNotFound(type: String)
|
||||
@ -112,8 +167,8 @@ extension VDS.TileContainer.Padding: Codable {
|
||||
do {
|
||||
let type = try container.decode(String.self)
|
||||
switch type {
|
||||
case "padding2X":
|
||||
self = .padding2X
|
||||
case "padding3X":
|
||||
self = .padding3X
|
||||
case "padding4X":
|
||||
self = .padding4X
|
||||
case "padding6X":
|
||||
|
||||
@ -74,7 +74,7 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMo
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
buttons = try typeContainer.decode(TwoButtonViewModel.self, forKey: .buttons)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, Parent
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
caretLink = try typeContainer.decode(CaretLinkModel.self, forKey: .caretLink)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMolec
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
link = try typeContainer.decode(LinkModel.self, forKey: .link)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, Paren
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
titleLockup = try typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
titleLockup = try helper.deprecatedCreate(from: decoder) ?? typeContainer.decodeMolecule(codingKey: .titleLockup)
|
||||
button = try typeContainer.decode(ButtonModel.self, forKey: .button)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
|
||||
public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
// Created by Scott Pfeil on 5/28/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
@objcMembers open class TabBar: UITabBar, MoleculeViewProtocol, TabBarProtocol, UITabBarDelegate {
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
open class TabBarModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tabBar"
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
|
||||
@objc public protocol TabsDelegate {
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
import VDS
|
||||
open class TabsModel: MoleculeModelProtocol {
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
public enum NavigationItemStyle: String, Codable {
|
||||
case light
|
||||
|
||||
@ -10,6 +10,7 @@ import Foundation
|
||||
import Combine
|
||||
import Dispatch
|
||||
import MVMCore
|
||||
import VDSTokens
|
||||
|
||||
@objcMembers open class CollapsableNotification: View {
|
||||
//--------------------------------------------------
|
||||
@ -50,7 +51,7 @@ import MVMCore
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
verticalStack.reset()
|
||||
backgroundColor = .mvmGreen()
|
||||
backgroundColor = bottomView.backgroundColor
|
||||
}
|
||||
|
||||
open func subscribeForNotifications() {
|
||||
@ -98,6 +99,8 @@ import MVMCore
|
||||
guard let model = model as? CollapsableNotificationModel else { return }
|
||||
topView.set(with: model, delegateObject, additionalData)
|
||||
bottomView.set(with: model, delegateObject, additionalData)
|
||||
topView.label.textColorConfiguration = bottomView.titleLabel.textColorConfiguration
|
||||
topView.label.surface = bottomView.surface
|
||||
|
||||
// Update top view default noop to expand.
|
||||
if let topAction = model.topAction,
|
||||
@ -110,6 +113,7 @@ import MVMCore
|
||||
}
|
||||
}
|
||||
initialState()
|
||||
backgroundColor = bottomView.backgroundColor
|
||||
}
|
||||
|
||||
open func performBlockOperation(with block: @escaping (MVMCoreBlockOperation) -> Void) {
|
||||
@ -214,7 +218,7 @@ import MVMCore
|
||||
|
||||
extension CollapsableNotification: StatusBarUI {
|
||||
public func getStatusBarUI() -> (color: UIColor, style: UIStatusBarStyle) {
|
||||
let color = backgroundColor ?? UIColor.mvmGreen
|
||||
let color = backgroundColor ?? VDSColor.feedbackInformationBackgroundOnlight
|
||||
var greyScale: CGFloat = 0
|
||||
topView.label.textColor.getWhite(&greyScale, alpha: nil)
|
||||
return (color, greyScale > 0.5 ? .lightContent : .default)
|
||||
@ -226,7 +230,7 @@ extension CollapsableNotification: AccessibilityProtocol {
|
||||
if !topView.isHidden {
|
||||
return topView
|
||||
} else {
|
||||
return bottomView.headline
|
||||
return bottomView.titleLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,21 +26,13 @@ open class CollapsableNotificationModel: NotificationMoleculeModel {
|
||||
self.collapseTime = collapseTime
|
||||
}
|
||||
super.init(with: headline, style: style, backgroundColor: backgroundColor, body: body, button: button, closeButton: closeButton)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
open override func setDefaults() {
|
||||
super.setDefaults()
|
||||
open func setDefaults() {
|
||||
if topLabel.numberOfLines == nil {
|
||||
topLabel.numberOfLines = 1
|
||||
}
|
||||
if topLabel.textColor == nil {
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
topLabel.textColor = Color(uiColor: .mvmBlack)
|
||||
default:
|
||||
topLabel.textColor = Color(uiColor: .mvmWhite)
|
||||
}
|
||||
}
|
||||
if topLabel.textAlignment == nil {
|
||||
topLabel.textAlignment = .center
|
||||
}
|
||||
@ -69,6 +61,7 @@ open class CollapsableNotificationModel: NotificationMoleculeModel {
|
||||
self.initiallyCollapsed = initiallyCollapsed
|
||||
}
|
||||
try super.init(from: decoder)
|
||||
setDefaults()
|
||||
}
|
||||
|
||||
open override func encode(to encoder: Encoder) throws {
|
||||
|
||||
@ -52,7 +52,7 @@ import Foundation
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
label.setFontStyle(.BoldBodySmall)
|
||||
label.textColor = .white
|
||||
label.textColor = .black
|
||||
label.textAlignment = .center
|
||||
}
|
||||
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
// Created by Scott Pfeil on 9/15/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
import VDS
|
||||
|
||||
|
||||
open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
|
||||
open class NotificationMoleculeModel: MoleculeModelProtocol {
|
||||
|
||||
/**
|
||||
The style of the notification:
|
||||
@ -21,91 +21,48 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
|
||||
case error
|
||||
case warning
|
||||
case information
|
||||
|
||||
var toVDSStyle: VDS.Notification.Style {
|
||||
switch self {
|
||||
case .success:
|
||||
.success
|
||||
case .error:
|
||||
.error
|
||||
case .warning:
|
||||
.warning
|
||||
case .information:
|
||||
.info
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var id: String = UUID().uuidString
|
||||
public class var identifier: String { "notification" }
|
||||
public var accessibilityIdentifier: String?
|
||||
public var backgroundColor: Color?
|
||||
public var headline: LabelModel
|
||||
public var body: LabelModel?
|
||||
public var button: ButtonModel?
|
||||
public var secondaryButton: ButtonModel?
|
||||
public var closeButton: NotificationXButtonModel?
|
||||
public var style: NotificationMoleculeModel.Style = .success
|
||||
public var style: Style = .success
|
||||
public var inverted: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(with headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, closeButton: NotificationXButtonModel? = nil) {
|
||||
public init(with headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, secondaryButton: ButtonModel? = nil, closeButton: NotificationXButtonModel? = nil) {
|
||||
self.headline = headline
|
||||
self.style = style
|
||||
self.backgroundColor = backgroundColor
|
||||
self.body = body
|
||||
self.button = button
|
||||
self.secondaryButton = secondaryButton
|
||||
self.closeButton = closeButton
|
||||
super.init()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Default
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func setDefaults() {
|
||||
useHorizontalMargins = true
|
||||
useVerticalMargins = true
|
||||
topPadding = PaddingTwo
|
||||
bottomPadding = PaddingTwo
|
||||
|
||||
if backgroundColor == nil {
|
||||
switch style {
|
||||
case .error:
|
||||
backgroundColor = Color(uiColor: .mvmOrange)
|
||||
case .warning:
|
||||
backgroundColor = Color(uiColor: .mvmYellow)
|
||||
case .information:
|
||||
backgroundColor = Color(uiColor: .mvmBlue)
|
||||
default:
|
||||
backgroundColor = Color(uiColor: .mvmGreen)
|
||||
}
|
||||
}
|
||||
if headline.textColor == nil {
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
headline.textColor = Color(uiColor: .mvmBlack)
|
||||
default:
|
||||
headline.textColor = Color(uiColor: .mvmWhite)
|
||||
}
|
||||
}
|
||||
if body?.textColor == nil {
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
body?.textColor = Color(uiColor: .mvmBlack)
|
||||
default:
|
||||
body?.textColor = Color(uiColor: .mvmWhite)
|
||||
}
|
||||
}
|
||||
|
||||
button?.size = .small
|
||||
button?.style = .secondary
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
button?.inverted = false
|
||||
default:
|
||||
button?.inverted = true
|
||||
}
|
||||
|
||||
if closeButton?.color == nil {
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
closeButton?.color = Color(uiColor: .mvmBlack)
|
||||
default:
|
||||
closeButton?.color = Color(uiColor: .mvmWhite)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -119,7 +76,9 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
|
||||
case headline
|
||||
case body
|
||||
case button
|
||||
case secondaryButton
|
||||
case closeButton
|
||||
case inverted
|
||||
case style
|
||||
}
|
||||
|
||||
@ -129,27 +88,34 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
|
||||
|
||||
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)
|
||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||
button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button)
|
||||
secondaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .secondaryButton)
|
||||
closeButton = try typeContainer.decodeIfPresent(NotificationXButtonModel.self, forKey: .closeButton)
|
||||
inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
|
||||
if let style = try typeContainer.decodeIfPresent(NotificationMoleculeModel.Style.self, forKey: .style) {
|
||||
self.style = style
|
||||
}
|
||||
super.init()
|
||||
}
|
||||
|
||||
open override 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.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encode(headline, forKey: .headline)
|
||||
try container.encodeIfPresent(body, forKey: .body)
|
||||
try container.encodeIfPresent(button, forKey: .button)
|
||||
try container.encodeIfPresent(secondaryButton, forKey: .secondaryButton)
|
||||
try container.encodeIfPresent(closeButton, forKey: .closeButton)
|
||||
try container.encodeIfPresent(inverted, forKey: .inverted)
|
||||
try container.encode(style, forKey: .style)
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationMoleculeModel {
|
||||
public var surface: Surface {
|
||||
inverted ? .dark : .light
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,90 +7,101 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class NotificationMoleculeView: Container {
|
||||
import VDS
|
||||
@objcMembers open class NotificationMoleculeView: VDS.Notification, VDSMoleculeViewProtocol {
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
open var viewModel: NotificationMoleculeModel!
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
public var additionalData: [AnyHashable: Any]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - VDSMoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
|
||||
open func viewModelDidUpdate() {
|
||||
surface = viewModel.surface
|
||||
title = viewModel.headline.text
|
||||
subTitle = viewModel.body?.text
|
||||
|
||||
if let button = viewModel.button {
|
||||
primaryButtonModel = .init(text: button.title, onClick: {[weak self] _ in
|
||||
guard let self else { return }
|
||||
self.executeAction(model: button, delegateObject: self.delegateObject, additionalData: self.additionalData)
|
||||
})
|
||||
}
|
||||
|
||||
if let secondaryButton = viewModel.secondaryButton {
|
||||
secondaryButtonModel = .init(text: secondaryButton.title, onClick: {[weak self] _ in
|
||||
guard let self else { return }
|
||||
self.executeAction(model: secondaryButton, delegateObject: self.delegateObject, additionalData: self.additionalData)
|
||||
})
|
||||
}
|
||||
|
||||
if let accessibilityIdentifier = viewModel.accessibilityIdentifier {
|
||||
self.accessibilityIdentifier = accessibilityIdentifier
|
||||
}
|
||||
|
||||
if let closeButton = viewModel.closeButton {
|
||||
onCloseClick = { [weak self] _ in
|
||||
guard let self else { return }
|
||||
self.executeAction(model: closeButton, delegateObject: self.delegateObject, additionalData: self.additionalData) }
|
||||
}
|
||||
|
||||
hideCloseButton = viewModel.closeButton == nil
|
||||
style = viewModel.style.toVDSStyle
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
|
||||
public let headline = Label(fontStyle: .BoldBodySmall)
|
||||
public let body = Label(fontStyle: .RegularBodySmall)
|
||||
public let button = PillButton()
|
||||
public let closeButton = NotificationXButton()
|
||||
public var labelStack: Stack<StackModel>!
|
||||
public var horizontalStack: Stack<StackModel>!
|
||||
|
||||
// Legacy constant
|
||||
private static let viewHeight: CGFloat = 96.0
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Life Cycle
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func setupView() {
|
||||
super.setupView()
|
||||
reset()
|
||||
|
||||
// Buttons should have highest priority, then headline, then body
|
||||
headline.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 500), for: .horizontal)
|
||||
headline.setContentHuggingPriority(.required, for: .vertical)
|
||||
body.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 500), for: .horizontal)
|
||||
body.setContentHuggingPriority(.required, for: .vertical)
|
||||
headline.setContentCompressionResistancePriority(UILayoutPriority(rawValue: body.contentCompressionResistancePriority(for: .vertical).rawValue + 40), for: .vertical)
|
||||
headline.lineBreakMode = .byTruncatingTail
|
||||
body.lineBreakMode = .byTruncatingTail
|
||||
button.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
|
||||
|
||||
labelStack = Stack<StackModel>.createStack(with: [headline, body], spacing: 0)
|
||||
horizontalStack = Stack<StackModel>.createStack(with: [(view: labelStack, model: StackItemModel()),(view: button, model: StackItemModel(horizontalAlignment: .fill)),(view: closeButton, model: StackItemModel(horizontalAlignment: .fill))], axis: .horizontal)
|
||||
addAndContain(horizontalStack)
|
||||
labelStack.restack()
|
||||
horizontalStack.restack()
|
||||
|
||||
heightAnchor.constraint(equalToConstant: Self.viewHeight).isActive = true
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
backgroundColor = .mvmGreen()
|
||||
headline.textColor = .white
|
||||
body.textColor = .white
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
Self.amendAccesibilityLabel(for: titleLabel)
|
||||
Self.amendAccesibilityLabel(for: subTitleLabel)
|
||||
Self.amendAccesibilityLabel(for: primaryButton)
|
||||
Self.amendAccesibilityLabel(for: secondaryButton)
|
||||
Self.amendAccesibilityLabel(for: closeButton)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? NotificationMoleculeModel else { return }
|
||||
labelStack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, nil)
|
||||
horizontalStack.updateContainedMolecules(with: [labelStack.stackModel, model.button, model.closeButton], delegateObject, nil)
|
||||
updateAccessibility()
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
public func updateView(_ size: CGFloat) { }
|
||||
|
||||
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return viewHeight
|
||||
}
|
||||
|
||||
open func updateAccessibility() {
|
||||
NotificationMoleculeView.amendAccesibilityLabel(for: headline)
|
||||
NotificationMoleculeView.amendAccesibilityLabel(for: body)
|
||||
NotificationMoleculeView.amendAccesibilityLabel(for: button)
|
||||
NotificationMoleculeView.amendAccesibilityLabel(for: closeButton)
|
||||
}
|
||||
|
||||
|
||||
/// Formats the accessibilityLabel so voice over users know it's in the notification.
|
||||
static public func amendAccesibilityLabel(for view: UIView) {
|
||||
guard let amendment = MVMCoreUIUtility.hardcodedString(withKey: "top_alert_notification"),
|
||||
let accessibilityLabel = view.accessibilityLabel,
|
||||
!accessibilityLabel.hasPrefix(amendment) else { return }
|
||||
view.accessibilityLabel = "\(amendment) - \(accessibilityLabel)"
|
||||
public class func amendAccesibilityLabel(for view: UIView?) {
|
||||
guard let view,
|
||||
let amendment = MVMCoreUIUtility.hardcodedString(withKey: "top_alert_notification")
|
||||
else { return }
|
||||
view.amendAccesibilityLabel(with: amendment)
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationMoleculeView: AccessibilityProtocol {
|
||||
public func getAccessibilityLayoutChangedArgument() -> Any? {
|
||||
return headline
|
||||
return titleLabel
|
||||
}
|
||||
}
|
||||
|
||||
extension UIView {
|
||||
/// Formats the accessibilityLabel so voice over users know it's in the notification.
|
||||
public func amendAccesibilityLabel(with amendment: String) {
|
||||
guard let accessibilityLabel, !accessibilityLabel.hasPrefix(amendment) else { return }
|
||||
self.accessibilityLabel = "\(amendment) - \(accessibilityLabel)"
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ import MVMCore
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? NotificationXButtonModel else { return }
|
||||
tintColor = model.color?.uiColor ?? .white
|
||||
|
||||
// TODO: Temporary, consider action for dismissing top alert
|
||||
if model.action.actionType == ActionNoopModel.identifier {
|
||||
|
||||
@ -15,25 +15,21 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var color: Color?
|
||||
public var action: ActionModelProtocol = ActionNoopModel()
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case color
|
||||
case action
|
||||
}
|
||||
|
||||
public init(color: Color? = nil, action: ActionModelProtocol = ActionNoopModel()) {
|
||||
self.color = color
|
||||
public init(action: ActionModelProtocol = ActionNoopModel()) {
|
||||
self.action = action
|
||||
}
|
||||
|
||||
public required init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
color = try typeContainer.decodeIfPresent(Color.self, forKey: .color)
|
||||
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
|
||||
self.action = action
|
||||
}
|
||||
@ -43,7 +39,6 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,8 @@ public protocol MoleculeDelegateProtocol: AnyObject {
|
||||
/// Notifies the delegate that the molecule layout update. Should be called when the layout may change due to an async method. Mainly used for list or collections.
|
||||
func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) //optional
|
||||
|
||||
func replaceMoleculeData(_ moleculeModels: [MoleculeModelProtocol])
|
||||
/// Attempts to replace the molecules provided. Returns the ones that replaced successfully.
|
||||
func replaceMoleculeData(_ moleculeModels: [MoleculeModelProtocol], completionHandler: (([MoleculeModelProtocol])->Void)?)
|
||||
}
|
||||
|
||||
extension MoleculeDelegateProtocol {
|
||||
|
||||
@ -66,6 +66,14 @@ extension MoleculeViewProtocol {
|
||||
set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
}
|
||||
|
||||
public func executeAction<T: ButtonModelProtocol & MoleculeModelProtocol>(model: T, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
Task(priority: .userInitiated) {
|
||||
try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: model.action,
|
||||
additionalData: MVMCoreUIActionHandler.add(sourceModel: model, to: additionalData),
|
||||
delegateObject: delegateObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience Functions
|
||||
|
||||
@ -21,7 +21,11 @@ public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtoc
|
||||
}
|
||||
|
||||
extension VDSMoleculeViewProtocol {
|
||||
|
||||
public var model: MoleculeModelProtocol {
|
||||
get { viewModel }
|
||||
set { }
|
||||
}
|
||||
|
||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
self.model = model
|
||||
guard let castedModel = model as? ViewModel else { return }
|
||||
|
||||
@ -511,7 +511,7 @@ import MVMCore
|
||||
// Needed otherwise when subclassed, the extension gets called.
|
||||
open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
|
||||
|
||||
public func replaceMoleculeData(_ moleculeModels: [MoleculeModelProtocol]) {
|
||||
public func replaceMoleculeData(_ moleculeModels: [MoleculeModelProtocol], completionHandler: (([MoleculeModelProtocol])->Void)? = nil) {
|
||||
pageUpdateQueue.addOperation {
|
||||
let replacedModels:[MoleculeModelProtocol] = moleculeModels.compactMap { model in
|
||||
guard self.attemptToReplace(with: model) else {
|
||||
@ -524,6 +524,7 @@ import MVMCore
|
||||
self.updateUI(for: replacedModels)
|
||||
}
|
||||
}
|
||||
completionHandler?(replacedModels)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,8 +21,6 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior {
|
||||
private var observingForResponses: NSObjectProtocol?
|
||||
private var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
public var transcendsPageUpdates: Bool { true }
|
||||
|
||||
public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) {
|
||||
moleculeIds = (model as! ReplaceableMoleculeBehaviorModel).moleculeIds
|
||||
let shouldListenForListUpdates = delegateObject?.moleculeListDelegate != nil
|
||||
@ -62,7 +60,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior {
|
||||
}
|
||||
}
|
||||
if moleculeModels.count > 0 {
|
||||
delegateObject?.moleculeDelegate?.replaceMoleculeData(moleculeModels)
|
||||
delegateObject?.moleculeDelegate?.replaceMoleculeData(moleculeModels, completionHandler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +93,15 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if modules.count > 0 {
|
||||
delegateObject?.moleculeDelegate?.replaceMoleculeData(modules)
|
||||
guard modules.count > 0 else { return }
|
||||
#if LOGGING
|
||||
let requestParams = (notification.userInfo?["MVMCoreLoadObject"] as? MVMCoreLoadObject)?.requestParameters
|
||||
MVMCoreLoggingHandler.shared()?.handleDebugMessage("Replacing \(modules.map { $0.id }) from \(requestParams?.url?.absoluteString ?? "unknown"), e2eId: \(requestParams?.identifier ?? "unknown")")
|
||||
#endif
|
||||
delegateObject?.moleculeDelegate?.replaceMoleculeData(modules) { replacedModels in
|
||||
let modules = replacedModels.compactMap { modulesLoaded.dictionaryForKey($0.id) }
|
||||
guard let viewController = self.delegateObject?.moleculeDelegate as? MVMCoreViewControllerProtocol else { return }
|
||||
modules.forEach { MVMCoreUILoggingHandler.shared()?.defaultLogPageUpdate(forController: viewController, from: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -56,6 +56,18 @@ extension UIColor {
|
||||
"upGold2": (.vzupGold2, "#F4CA53"),
|
||||
"upGold3": (.vzupGold3, "#CC9B2D")]
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Helper
|
||||
//--------------------------------------------------
|
||||
public var rgbComponents: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
|
||||
var red: CGFloat = 0
|
||||
var green: CGFloat = 0
|
||||
var blue: CGFloat = 0
|
||||
var alpha: CGFloat = 0
|
||||
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
|
||||
return (red, green, blue, alpha)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Brand
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -34,6 +34,7 @@ import Combine
|
||||
public static func setupNavigationControllerAsMainController() -> Self? {
|
||||
guard let navigationController = setupNavigationController() else { return nil }
|
||||
MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController)
|
||||
MVMCoreObject.sharedInstance()?.viewControllerManager = navigationController
|
||||
return navigationController
|
||||
}
|
||||
|
||||
@ -136,6 +137,31 @@ extension NavigationController: MVMCoreViewManagerProtocol {
|
||||
public func displayedViewController(_ viewController: UIViewController) {
|
||||
manager?.displayedViewController?(viewController)
|
||||
}
|
||||
|
||||
private func go(to index: Int) async {
|
||||
guard index != viewControllers.count - 1 else { return }
|
||||
await NavigationHandler.shared().set(viewControllers: Array(viewControllers[0...index]), navigationController: self)
|
||||
}
|
||||
|
||||
public func navigate(toViewControllerOfPageType pageType: String, controllerType: AnyClass?) async -> UIViewController? {
|
||||
for (index, controller) in viewControllers.enumerated() {
|
||||
if let manager = controller as? MVMCoreViewManagerProtocol,
|
||||
let viewController = await manager.navigate(toViewControllerOfPageType: pageType, controllerType: controllerType) {
|
||||
await go(to: index)
|
||||
return viewController
|
||||
} else if let controller = controller as? MVMCoreViewControllerProtocol & UIViewController,
|
||||
controller.pageType == pageType {
|
||||
guard let controllerType = controllerType else {
|
||||
await go(to: index)
|
||||
return controller
|
||||
}
|
||||
guard (type(of: controller) == controllerType) else { continue }
|
||||
await go(to: index)
|
||||
return controller
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
extension UIColor {
|
||||
|
||||
@ -102,7 +102,7 @@ public extension UINavigationController {
|
||||
navigationBar.standardAppearance = appearance
|
||||
navigationBar.scrollEdgeAppearance = appearance
|
||||
|
||||
setNavigationBarHidden(model.hidden, animated: true)
|
||||
setNavigationBarHidden(model.hidden, animated: false)
|
||||
}
|
||||
|
||||
@objc @MainActor
|
||||
|
||||
@ -269,6 +269,10 @@ extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol {
|
||||
public func newDataReceived(in viewController: UIViewController) {
|
||||
updateState(with: viewController)
|
||||
}
|
||||
|
||||
public func navigate(toViewControllerOfPageType pageType: String, controllerType: AnyClass?) async -> UIViewController? {
|
||||
return await navigationController?.navigate(toViewControllerOfPageType: pageType, controllerType: controllerType)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public extension MVMCoreUISplitViewController {
|
||||
|
||||
@ -95,6 +95,7 @@ CGFloat const PanelAnimationDuration = 0.2;
|
||||
if (topAlertView) {
|
||||
[splitViewController subscribeForNotifications];
|
||||
}
|
||||
[MVMCoreObject sharedInstance].viewControllerManager = splitViewController;
|
||||
return splitViewController;
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import MVMCore
|
||||
import VDSColorTokens
|
||||
import VDSTokens
|
||||
|
||||
open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, TabsDelegate, MVMCorePresentationDelegateProtocol, SubNavSwipeNavigationProtocol {
|
||||
/// The number of tabs count or less that will turn on the fillContainer
|
||||
@ -362,6 +362,35 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
manager?.displayedViewController?(viewController)
|
||||
}
|
||||
|
||||
private func go(to index: Int) async {
|
||||
// Load controller from the cache
|
||||
guard index != self.index,
|
||||
let controller = viewControllers[index] else { return }
|
||||
needToTrackTabSelect = true
|
||||
self.index = index
|
||||
await NavigationHandler.shared().replace(viewController: controller, navigationController:subNavigationController, delegateObject:delegateObject(), tryToReplace: false, animated: true)
|
||||
}
|
||||
|
||||
public func navigate(toViewControllerOfPageType pageType: String, controllerType: AnyClass?) async -> UIViewController? {
|
||||
for (index, controller) in viewControllers.enumerated() {
|
||||
if let manager = controller as? MVMCoreViewManagerProtocol,
|
||||
let viewController = await manager.navigate(toViewControllerOfPageType: pageType, controllerType: controllerType) {
|
||||
await go(to: index)
|
||||
return viewController
|
||||
} else if let controller = controller as? MVMCoreViewControllerProtocol & UIViewController,
|
||||
controller.pageType == pageType {
|
||||
guard let controllerType = controllerType else {
|
||||
await go(to: index)
|
||||
return controller
|
||||
}
|
||||
guard (type(of: controller) == controllerType) else { continue }
|
||||
await go(to: index)
|
||||
return controller
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUISwipeNavigationProtocol
|
||||
|
||||
public func swipeLeft() {
|
||||
|
||||
@ -73,8 +73,11 @@ open class CoreUIModelMapping: ModelMapping {
|
||||
ModelRegistry.register(handler: LoadingSpinner.self, for: LoadingSpinnerModel.self)
|
||||
ModelRegistry.register(handler: Video.self, for: VideoModel.self)
|
||||
ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self)
|
||||
ModelRegistry.register(handler: TileContainer.self, for: TileContainerModel.self)
|
||||
ModelRegistry.register(handler: Badge.self, for: BadgeModel.self)
|
||||
ModelRegistry.register(handler: BadgeIndicator.self, for: BadgeIndicatorModel.self)
|
||||
ModelRegistry.register(handler: Icon.self, for: IconModel.self)
|
||||
ModelRegistry.register(handler: ButtonIcon.self, for: ButtonIconModel.self)
|
||||
ModelRegistry.register(handler: Tooltip.self, for: TooltipModel.self)
|
||||
|
||||
// MARK:- Horizontal Combination Molecules
|
||||
|
||||
@ -13,4 +13,7 @@
|
||||
|
||||
// Action Logging
|
||||
@objc open func defaultLogAction(forController controller: MVMCoreViewControllerProtocol?, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { }
|
||||
|
||||
// Module Update Logging
|
||||
@objc open func defaultLogPageUpdate(forController controller: MVMCoreViewControllerProtocol, from module: [AnyHashable: Any]) { }
|
||||
}
|
||||
|
||||
13
MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig
Normal file
13
MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// mvmcore_ui.xcconfig
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kyle Hedden on 4/23/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
// Refer back to the workspace settings if they exist.
|
||||
#include? "../../../workspaceSettings.xcconfig"
|
||||
16
MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig
Normal file
16
MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// mvmcore_ui_dev.xcconfig
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kyle Hedden on 4/23/24.
|
||||
// Copyright © 2024 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) LOGGING
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) LOGGING=1
|
||||
|
||||
// Refer back to the workspace settings if they exist.
|
||||
#include? "../../../workspaceSettings.xcconfig"
|
||||
@ -73,6 +73,7 @@ public extension MVMCoreUIUtility {
|
||||
|
||||
@objc
|
||||
public extension MVMCoreUIUtility {
|
||||
/// Returns the current visible viewcontroller.
|
||||
@objc @MainActor
|
||||
static func getVisibleViewController() -> UIViewController? {
|
||||
var viewController = NavigationHandler.shared().getViewControllerToPresentOn()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user