From 314f2e91cb5d1d1f4cbda418be510761679c8e4c Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 25 Mar 2024 13:29:36 -0400 Subject: [PATCH 01/49] Manager updates for navigating to controller. --- .../NavigationController.swift | 26 +++++++++++++++++ ...MCoreUISplitViewController+Extension.swift | 4 +++ .../MVMCoreUISplitViewController.m | 1 + .../SubNav/SubNavManagerController.swift | 29 +++++++++++++++++++ .../Utility/MVMCoreUIUtility+Extension.swift | 1 + 5 files changed, 61 insertions(+) diff --git a/MVMCoreUI/Containers/NavigationController/NavigationController.swift b/MVMCoreUI/Containers/NavigationController/NavigationController.swift index 57f4b5a5..d8d56244 100644 --- a/MVMCoreUI/Containers/NavigationController/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController/NavigationController.swift @@ -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 { diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index c0420055..549d53a8 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -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 { diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index 79c81b8d..453c7d56 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -95,6 +95,7 @@ CGFloat const PanelAnimationDuration = 0.2; if (topAlertView) { [splitViewController subscribeForNotifications]; } + [MVMCoreObject sharedInstance].viewControllerManager = splitViewController; return splitViewController; } diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 741fb830..ed1a7ca1 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -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() { diff --git a/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift b/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift index 2f755491..ea91f62b 100644 --- a/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift +++ b/MVMCoreUI/Utility/MVMCoreUIUtility+Extension.swift @@ -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() From 36eaaf97df2511c317fffea12fdd413c45a45f9f Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Mar 2024 13:36:28 -0400 Subject: [PATCH 02/49] Digital PCT265 story MVAPCT-48 - Remove animating of navigation bar shown --- .../NavigationController/UINavigationController+Extension.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index 44aa9207..5a3d9a1a 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -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 From 494a7296583f43207f3b212f0b793efe888892e1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 2 Apr 2024 15:02:39 -0500 Subject: [PATCH 03/49] update to point to the new VDSTokens framework Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 30 ++++++++++++------- .../Atomic/Atoms/Buttons/ButtonModel.swift | 2 +- .../Atomic/Atoms/Buttons/Link/Link.swift | 2 +- .../Atomic/Atoms/Buttons/PillButton.swift | 2 +- .../Atomic/Atoms/Selectors/RadioButton.swift | 3 +- .../CarouselIndicator/CarouselIndicator.swift | 2 +- .../CarouselIndicatorModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/IconModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 2 +- .../Atomic/Atoms/Views/TooltipModel.swift | 2 +- .../Atomic/Extensions/VDS-Enums+Codable.swift | 2 +- .../LockUps/TitleLockupModel.swift | 2 +- .../HorizontalCombinationViews/TabBar.swift | 2 +- .../TabBarModel.swift | 2 +- .../HorizontalCombinationViews/Tabs.swift | 2 +- .../TabsModel.swift | 2 +- .../NavigationBar/NavigationItemModel.swift | 2 +- .../SubNav/SubNavManagerController.swift | 2 +- 18 files changed, 37 insertions(+), 28 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 038ecb6c..2e45f290 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -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 */; }; @@ -174,8 +173,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 +299,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 */; }; @@ -589,7 +585,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,9 +599,25 @@ 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 */; }; + EAD715AB2BBC8FAF00DEDA6A /* VDSTokens.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + EAD715AC2BBC8FAF00DEDA6A /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + EAD715AB2BBC8FAF00DEDA6A /* VDSTokens.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; 0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggleModel.swift; sourceTree = ""; }; @@ -777,8 +788,6 @@ 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadableDecodingErrors.swift; sourceTree = ""; }; 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = ""; }; 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; - 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityHandler.swift; sourceTree = ""; }; - 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = ""; }; 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = ""; }; 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = ""; }; 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = ""; }; @@ -1208,6 +1217,7 @@ EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = ""; }; EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = ""; }; EACCF38B2ABB346700E0F104 /* VDS-Interpreters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VDS-Interpreters.swift"; sourceTree = ""; }; + EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTokens.xcframework; path = ../SharedFrameworks/VDSTokens.xcframework; sourceTree = ""; }; FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1217,10 +1227,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; }; @@ -2081,6 +2089,7 @@ D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = { isa = PBXGroup; children = ( + EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */, EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */, EA985C5F2970A3F000F2FF2E /* VDS.framework */, 187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */, @@ -2590,6 +2599,7 @@ D29DF0C821E404D4003B2FB9 /* Sources */, D29DF0C921E404D4003B2FB9 /* Frameworks */, D29DF0CA21E404D4003B2FB9 /* Resources */, + EAD715AC2BBC8FAF00DEDA6A /* Embed Frameworks */, ); buildRules = ( ); diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index e9fd6509..dec3480c 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDSTokens import VDS import MVMCore diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift index 9aea7b17..f9261d97 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/Link/Link.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDSTokens import VDS open class Link: VDS.TextLink, VDSMoleculeViewProtocol { diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index e5d1ae73..a9989b3b 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDSTokens import VDS import MVMCore import Combine diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index 6966f3e6..2f9ae80a 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -7,8 +7,7 @@ // import UIKit -import VDSColorTokens -import VDSFormControlsTokens +import VDSTokens @objcMembers open class RadioButton: Control, MFButtonProtocol { //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift index 1d7808bd..56827bec 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicator.swift @@ -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 { //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift index f5c0adeb..3631bfc0 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CarouselIndicator/CarouselIndicatorModel.swift @@ -7,7 +7,7 @@ // import Foundation -import VDSColorTokens +import VDSTokens open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelProtocol, EnableableModelProtocol { //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift b/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift index a1339cf3..4fbbd712 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/IconModel.swift @@ -8,7 +8,7 @@ import Foundation import VDS -import VDSColorTokens +import VDSTokens open class IconModel: MoleculeModelProtocol { diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index 8a473016..2cfe9b99 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDSTokens import VDS public class LineModel: MoleculeModelProtocol, Invertable { diff --git a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift index f6627dd3..27400a2c 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift @@ -8,7 +8,7 @@ import Foundation import VDS -import VDSColorTokens +import VDSTokens import MVMCore open class TooltipModel: MoleculeModelProtocol { diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 9e524462..3e6ed245 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -8,7 +8,7 @@ import Foundation import VDS -import VDSColorTokens +import VDSTokens //-------------------------------------------------- // MARK: - Codable Extensions diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift index 3075a2ae..a280e0b4 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/LockUps/TitleLockupModel.swift @@ -6,7 +6,7 @@ // Copyright © 2022 Verizon Wireless. All rights reserved. // -import VDSColorTokens +import VDSTokens import VDS public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift index 65b116f5..370b47a6 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBar.swift @@ -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 { diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index b984a9da..9a700903 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -7,7 +7,7 @@ // import Foundation -import VDSColorTokens +import VDSTokens open class TabBarModel: MoleculeModelProtocol { public static var identifier: String = "tabBar" diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index ca4ca068..5a34245d 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDSTokens import VDS @objc public protocol TabsDelegate { diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index e09761d5..a7acadf6 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -7,7 +7,7 @@ // import UIKit -import VDSColorTokens +import VDSTokens import VDS open class TabsModel: MoleculeModelProtocol { diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index d39cdeaf..67fc779f 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -6,7 +6,7 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -import VDSColorTokens +import VDSTokens public enum NavigationItemStyle: String, Codable { case light diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 741fb830..0c35fd1f 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -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 From da701bac232512e1f70f0459154abd0771742eb7 Mon Sep 17 00:00:00 2001 From: Krishna Kishore Bandaru Date: Wed, 3 Apr 2024 18:18:54 +0530 Subject: [PATCH 04/49] Added missing code --- MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift index 965656a6..2ce1254b 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift @@ -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)") + } } } From c4dad0bddd2f68ce5087e69d3f9d2b5c0d5b6b28 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Tue, 9 Apr 2024 11:00:15 -0400 Subject: [PATCH 05/49] Digital PCT265 bugfix - Added missing deprecated decodes for headers. --- .../DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift | 2 +- .../DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift | 2 +- .../DesignedComponents/Headers/H2/HeadersH2LinkModel.swift | 2 +- .../Headers/H2/HeadersH2TinyButtonModel.swift | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift index 3b4d0b7e..9590fefc 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2ButtonsModel.swift @@ -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) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift index 4f7129da..784966cf 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2CaretLinkModel.swift @@ -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) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift index 1ec6590d..0a104f9f 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2LinkModel.swift @@ -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) } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift index 91a1c472..aba4e48b 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/Headers/H2/HeadersH2TinyButtonModel.swift @@ -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) } From 077ee85dc0be654ceb3edae8aa9ff9e541b8875c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 13:39:45 -0500 Subject: [PATCH 06/49] removed ternary Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index e5d1ae73..12c65867 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -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 From 5fbf076aa703cb6318cdf8662d92ca6f307f66e0 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 13:40:09 -0500 Subject: [PATCH 07/49] refactored NotificationMoleculeView/Model Signed-off-by: Matt Bruce --- .../NotificationMoleculeModel.swift | 102 +++++++------- .../NotificationMoleculeView.swift | 131 +++++++++--------- 2 files changed, 115 insertions(+), 118 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index 9958b59a..f9387064 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -5,7 +5,7 @@ // Created by Scott Pfeil on 9/15/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // - +import VDS open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { @@ -21,6 +21,19 @@ 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 + } + } } //-------------------------------------------------- @@ -33,19 +46,22 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { public var headline: LabelModel public var body: LabelModel? public var button: ButtonModel? - public var closeButton: NotificationXButtonModel? - public var style: NotificationMoleculeModel.Style = .success + public var secondaryButton: ButtonModel? + public var closeButton: ButtonModel? + 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: ButtonModel? = nil) { self.headline = headline self.style = style self.backgroundColor = backgroundColor self.body = body self.button = button + self.secondaryButton = secondaryButton self.closeButton = closeButton super.init() } @@ -55,57 +71,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { //-------------------------------------------------- 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 +85,9 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { case headline case body case button + case secondaryButton case closeButton + case inverted case style } @@ -134,7 +102,9 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { headline = try typeContainer.decode(LabelModel.self, forKey: .headline) body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button) - closeButton = try typeContainer.decodeIfPresent(NotificationXButtonModel.self, forKey: .closeButton) + secondaryButton = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .secondaryButton) + closeButton = try typeContainer.decodeIfPresent(ButtonModel.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 } @@ -149,7 +119,29 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { 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.encode(style, forKey: .style) } } + +extension NotificationMoleculeModel { + public var surface: Surface { + inverted ? .dark : .light + } +} + +extension ButtonModel { + public func toNotficationButtonModel(delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) -> VDS.Notification.ButtonModel { + return .init(text: title, onClick: { [weak self] _ in + guard let self else { return } + self.onClick(delegateObject: delegateObject, additionalData) + }) + } + + public func onClick(delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + Task(priority: .userInitiated) { + try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: action, additionalData: MVMCoreUIActionHandler.add(sourceModel: self, to: additionalData), delegateObject: delegateObject) + } + } +} diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift index 200dea16..7c4643bb 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift @@ -7,90 +7,95 @@ // 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 buttonModel = viewModel.button { + primaryButtonModel = buttonModel.toNotficationButtonModel(delegateObject: delegateObject, additionalData) + } + + if let buttonModel = viewModel.secondaryButton { + secondaryButtonModel = buttonModel.toNotficationButtonModel(delegateObject: delegateObject, additionalData) + } + + if let accessibilityIdentifier = viewModel.accessibilityIdentifier { + self.accessibilityIdentifier = accessibilityIdentifier + } + + if let closeButton = viewModel.closeButton { + onCloseClick = { [weak self] _ in + guard let self else { return } + closeButton.onClick(delegateObject: self.delegateObject, 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! - public var horizontalStack: Stack! - // 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.createStack(with: [headline, body], spacing: 0) - horizontalStack = Stack.createStack(with: [(view: labelStack, model: StackItemModel()),(view: button, model: StackItemModel(horizontalAlignment: .fill)),(view: closeButton, model: StackItemModel(horizontalAlignment: .fill))], axis: .horizontal) - 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)" } } From f6a29a734c1620a908232bb468e4457d1bcca611 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 14:01:26 -0500 Subject: [PATCH 08/49] updated collapsablenotification view/model Signed-off-by: Matt Bruce --- .../TopNotification/CollapsableNotification.swift | 8 +++++--- .../TopNotification/CollapsableNotificationModel.swift | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 4c677029..612f3873 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -10,6 +10,7 @@ import Foundation import Combine import Dispatch import MVMCore +import VDSColorTokens @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() { @@ -110,6 +111,7 @@ import MVMCore } } initialState() + backgroundColor = bottomView.backgroundColor } open func performBlockOperation(with block: @escaping (MVMCoreBlockOperation) -> Void) { @@ -214,7 +216,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 +228,7 @@ extension CollapsableNotification: AccessibilityProtocol { if !topView.isHidden { return topView } else { - return bottomView.headline + return bottomView.titleLabel } } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift index 3d366347..480665e2 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift @@ -19,7 +19,7 @@ open class CollapsableNotificationModel: NotificationMoleculeModel { public var collapseTime: Int = 5 public var initiallyCollapsed = false - public init(with topLabel: LabelModel, headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, topAction: ActionModelProtocol? = nil, collapseTime: Int? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, closeButton: NotificationXButtonModel? = nil) { + public init(with topLabel: LabelModel, headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, topAction: ActionModelProtocol? = nil, collapseTime: Int? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, closeButton: ButtonModel? = nil) { self.topLabel = topLabel self.topAction = topAction if let collapseTime = collapseTime { From 2e1bb7358ffcb76eb44fddb99ba7ecd40e012bb3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 16:55:58 -0500 Subject: [PATCH 09/49] added executeAction helper method Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift index c3c07b6a..3869b398 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeViewProtocol.swift @@ -66,6 +66,14 @@ extension MoleculeViewProtocol { set(with: model, delegateObject, additionalData) } } + + public func executeAction(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 From 89e6ea43d0bd7ceade223d179bc01df3fec65b72 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 16:56:51 -0500 Subject: [PATCH 10/49] put back to NotificationXBUttonModel Signed-off-by: Matt Bruce --- .../CollapsableNotificationModel.swift | 2 +- .../NotificationMoleculeModel.swift | 21 +++---------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift index 480665e2..3d366347 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift @@ -19,7 +19,7 @@ open class CollapsableNotificationModel: NotificationMoleculeModel { public var collapseTime: Int = 5 public var initiallyCollapsed = false - public init(with topLabel: LabelModel, headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, topAction: ActionModelProtocol? = nil, collapseTime: Int? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, closeButton: ButtonModel? = nil) { + public init(with topLabel: LabelModel, headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, topAction: ActionModelProtocol? = nil, collapseTime: Int? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, closeButton: NotificationXButtonModel? = nil) { self.topLabel = topLabel self.topAction = topAction if let collapseTime = collapseTime { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index f9387064..998fb689 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -47,7 +47,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { public var body: LabelModel? public var button: ButtonModel? public var secondaryButton: ButtonModel? - public var closeButton: ButtonModel? + public var closeButton: NotificationXButtonModel? public var style: Style = .success public var inverted: Bool = false @@ -55,7 +55,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { // MARK: - Initializer //-------------------------------------------------- - public init(with headline: LabelModel, style: NotificationMoleculeModel.Style = .success, backgroundColor: Color? = nil, body: LabelModel? = nil, button: ButtonModel? = nil, secondaryButton: ButtonModel? = nil, closeButton: ButtonModel? = 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 @@ -103,7 +103,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { 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(ButtonModel.self, forKey: .closeButton) + 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 @@ -130,18 +130,3 @@ extension NotificationMoleculeModel { inverted ? .dark : .light } } - -extension ButtonModel { - public func toNotficationButtonModel(delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) -> VDS.Notification.ButtonModel { - return .init(text: title, onClick: { [weak self] _ in - guard let self else { return } - self.onClick(delegateObject: delegateObject, additionalData) - }) - } - - public func onClick(delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - Task(priority: .userInitiated) { - try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: action, additionalData: MVMCoreUIActionHandler.add(sourceModel: self, to: additionalData), delegateObject: delegateObject) - } - } -} From b23351386b4161c57c34d89e039381214247466b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 10 Apr 2024 16:56:59 -0500 Subject: [PATCH 11/49] using helper now Signed-off-by: Matt Bruce --- .../NotificationMoleculeView.swift | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift index 7c4643bb..38c58aa9 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeView.swift @@ -28,12 +28,18 @@ import VDS title = viewModel.headline.text subTitle = viewModel.body?.text - if let buttonModel = viewModel.button { - primaryButtonModel = buttonModel.toNotficationButtonModel(delegateObject: delegateObject, additionalData) + 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 buttonModel = viewModel.secondaryButton { - secondaryButtonModel = buttonModel.toNotficationButtonModel(delegateObject: delegateObject, 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 { @@ -43,9 +49,9 @@ import VDS if let closeButton = viewModel.closeButton { onCloseClick = { [weak self] _ in guard let self else { return } - closeButton.onClick(delegateObject: self.delegateObject, self.additionalData) - } + self.executeAction(model: closeButton, delegateObject: self.delegateObject, additionalData: self.additionalData) } } + hideCloseButton = viewModel.closeButton == nil style = viewModel.style.toVDSStyle } From bd93cfdfe888b7cc2b0f0799ec97275bd49f3b65 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 12:28:02 -0500 Subject: [PATCH 12/49] map notification label to topLabel Signed-off-by: Matt Bruce --- .../Molecules/TopNotification/CollapsableNotification.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 612f3873..6372e7ca 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -99,6 +99,8 @@ import VDSColorTokens 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, From 277f54599ee9bc013286b627102827c06ce961ed Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 12:28:18 -0500 Subject: [PATCH 13/49] omit text color Signed-off-by: Matt Bruce --- .../TopNotification/CollapsableNotificationModel.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift index 3d366347..e6c32afd 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift @@ -33,14 +33,6 @@ open class CollapsableNotificationModel: NotificationMoleculeModel { 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 } From ae8f19ba510aa2d5871dacd8c071904d2a9f22f4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 12:28:31 -0500 Subject: [PATCH 14/49] set default color to black Signed-off-by: Matt Bruce --- .../TopNotification/CollapsableNotificationTopView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift index 01c0b3d5..1a9512d1 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift @@ -52,7 +52,7 @@ import Foundation open override func reset() { super.reset() label.setFontStyle(.BoldBodySmall) - label.textColor = .white + label.textColor = .black label.textAlignment = .center } From 7d6591a3940db115e0d4e3ac2b9b76dabf5bdef7 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 12:29:28 -0500 Subject: [PATCH 15/49] default implementation for model in protocol used for vds component integration Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift index 1bcc78c6..4bebf0c7 100644 --- a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift @@ -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 } From 1048a2989130f2fcefdcdeb61d0ed724a5cf03f1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 13:06:39 -0500 Subject: [PATCH 16/49] added rbg helper to UIColor extension Signed-off-by: Matt Bruce --- MVMCoreUI/Categories/UIColor+Extension.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MVMCoreUI/Categories/UIColor+Extension.swift b/MVMCoreUI/Categories/UIColor+Extension.swift index 78363630..f4ef0f7f 100644 --- a/MVMCoreUI/Categories/UIColor+Extension.swift +++ b/MVMCoreUI/Categories/UIColor+Extension.swift @@ -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 //-------------------------------------------------- From 473c98cca431db3a0a43c3cb12bb8d3f68efae9d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 14:04:12 -0500 Subject: [PATCH 17/49] removed color since now this is driven by vds Signed-off-by: Matt Bruce --- .../Molecules/TopNotification/NotificationXButton.swift | 1 - .../TopNotification/NotificationXButtonModel.swift | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift index d0071668..c102d064 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift @@ -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 { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index ac1c8905..0206b79d 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -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) } } From 8fd6a2e7c4f5fdd5785ddaaccbe3f46e6e2bcaf8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 11 Apr 2024 14:08:21 -0500 Subject: [PATCH 18/49] removed background color coding Signed-off-by: Matt Bruce --- .../Molecules/TopNotification/NotificationMoleculeModel.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index 998fb689..ddf90a77 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -97,7 +97,6 @@ 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) @@ -114,7 +113,6 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { open override func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encode(headline, forKey: .headline) try container.encodeIfPresent(body, forKey: .body) From 79cccbb47103d5595823d0d8a66aa0dd0bb0bbcb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 12 Apr 2024 08:38:02 -0500 Subject: [PATCH 19/49] removed ContainerModel Signed-off-by: Matt Bruce --- .../NotificationMoleculeModel.swift | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index ddf90a77..7fac6d43 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -7,7 +7,7 @@ // import VDS -open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { +open class NotificationMoleculeModel: MoleculeModelProtocol { /** The style of the notification: @@ -39,7 +39,7 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - + public var id: String = UUID().uuidString public class var identifier: String { "notification" } public var accessibilityIdentifier: String? public var backgroundColor: Color? @@ -63,15 +63,6 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { self.button = button self.secondaryButton = secondaryButton self.closeButton = closeButton - super.init() - } - - //-------------------------------------------------- - // MARK: - Default - //-------------------------------------------------- - - open override func setDefaults() { - } //-------------------------------------------------- @@ -107,10 +98,9 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol { 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(accessibilityIdentifier, forKey: .accessibilityIdentifier) From 1edffd8e24614bc2f53d331d825f10e2b2f39837 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 12 Apr 2024 08:39:28 -0500 Subject: [PATCH 20/49] added encoding for inverted Signed-off-by: Matt Bruce --- .../Molecules/TopNotification/NotificationMoleculeModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift index 7fac6d43..0fc5d5d5 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationMoleculeModel.swift @@ -109,6 +109,7 @@ open class NotificationMoleculeModel: MoleculeModelProtocol { 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) } } From 59a5c6a3e79fb4aaf98dce9ac2352f270d0d516d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 12 Apr 2024 10:22:12 -0500 Subject: [PATCH 21/49] added BadgeIndicator Atom Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 12 +- .../Atomic/Atoms/Views/BadgeIndicator.swift | 70 +++++++++++ .../Atoms/Views/BadgeIndicatorModel.swift | 111 ++++++++++++++++++ .../Atomic/Extensions/VDS-Enums+Codable.swift | 4 + .../OtherHandlers/CoreUIModelMapping.swift | 1 + 5 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/BadgeIndicator.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 038ecb6c..6a08a82b 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -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 */; }; @@ -575,6 +573,8 @@ 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 */; }; 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 */; }; @@ -777,8 +777,6 @@ 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadableDecodingErrors.swift; sourceTree = ""; }; 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = ""; }; 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; - 7199C8152A4F3A64001568B7 /* AccessibilityHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityHandler.swift; sourceTree = ""; }; - 71BE969D2AD96BE6000B5DB7 /* RotorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = ""; }; 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = ""; }; 8D070BB1241B56AD0099AC56 /* ListRightVariableTotalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalData.swift; sourceTree = ""; }; 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = ""; }; @@ -1179,6 +1177,8 @@ DBC4391A224421A0001AB423 /* CaretLink.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretLink.swift; sourceTree = ""; }; EA05EFA8278DDE2C00828819 /* ClearFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearFormFieldEffectModel.swift; sourceTree = ""; }; EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearableModelProtocol.swift; sourceTree = ""; }; + EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeIndicator.swift; sourceTree = ""; }; + EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeIndicatorModel.swift; sourceTree = ""; }; EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = ""; }; EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = ""; }; EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = ""; }; @@ -2268,6 +2268,8 @@ AA07EA922510A451009A2AE3 /* Star.swift */, B4CC8FBE29DF34730005D28B /* BadgeModel.swift */, B4CC8FBC29DF34680005D28B /* Badge.swift */, + EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */, + EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */, EA985C3F2970939A00F2FF2E /* TileletModel.swift */, EA985C3D2970938F00F2FF2E /* Tilelet.swift */, EA7D81612B2B6E7F00D29F9E /* IconModel.swift */, @@ -2684,6 +2686,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 */, @@ -2989,6 +2992,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 */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicator.swift b/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicator.swift new file mode 100644 index 00000000..3eb78919 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicator.swift @@ -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 } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift b/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift new file mode 100644 index 00000000..059f4c7f --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift @@ -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 { + self.init() + let container = try decoder.container(keyedBy: CodingKeys.self) + 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) + } +} diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 9e524462..caed0f13 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -16,6 +16,10 @@ 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.ButtonGroup.Alignment: Codable {} extension VDS.Icon.Name: Codable {} extension VDS.Icon.Size: Codable {} diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 6a14767e..c864acdb 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -74,6 +74,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: Video.self, for: VideoModel.self) ModelRegistry.register(handler: Tilelet.self, for: TileletModel.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: Tooltip.self, for: TooltipModel.self) From c50e6adfd6c5ebae5155b639a09287ca7b96f252 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 12 Apr 2024 12:22:59 -0500 Subject: [PATCH 22/49] removed embed Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2e45f290..64bcc3ed 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -600,24 +600,9 @@ 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 */; }; - EAD715AB2BBC8FAF00DEDA6A /* VDSTokens.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EAD715A92BBC8FAF00DEDA6A /* VDSTokens.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXCopyFilesBuildPhase section */ - EAD715AC2BBC8FAF00DEDA6A /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - EAD715AB2BBC8FAF00DEDA6A /* VDSTokens.xcframework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ 01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; 0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggleModel.swift; sourceTree = ""; }; @@ -2599,7 +2584,6 @@ D29DF0C821E404D4003B2FB9 /* Sources */, D29DF0C921E404D4003B2FB9 /* Frameworks */, D29DF0CA21E404D4003B2FB9 /* Resources */, - EAD715AC2BBC8FAF00DEDA6A /* Embed Frameworks */, ); buildRules = ( ); From a74362cc0c695350d514281cf08352197760a7bb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 12 Apr 2024 13:06:15 -0500 Subject: [PATCH 23/49] fixed issue with taking out ContainerModel Signed-off-by: Matt Bruce --- .../Molecules/TopNotification/CollapsableNotification.swift | 2 +- .../TopNotification/CollapsableNotificationModel.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 6372e7ca..cef93935 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -10,7 +10,7 @@ import Foundation import Combine import Dispatch import MVMCore -import VDSColorTokens +import VDSTokens @objcMembers open class CollapsableNotification: View { //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift index e6c32afd..4c87a4e4 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationModel.swift @@ -26,10 +26,10 @@ 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 } @@ -61,6 +61,7 @@ open class CollapsableNotificationModel: NotificationMoleculeModel { self.initiallyCollapsed = initiallyCollapsed } try super.init(from: decoder) + setDefaults() } open override func encode(to encoder: Encoder) throws { From c6fccb014a177af24beec2c8fe1718d27668eb74 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 12 Apr 2024 13:10:51 -0500 Subject: [PATCH 24/49] initial button icon Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift | 9 +++ .../Atomic/Atoms/Views/ButtonIconModel.swift | 80 +++++++++++++++++++ .../Atomic/Extensions/VDS-Enums+Codable.swift | 4 + 4 files changed, 101 insertions(+) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 6a08a82b..5f715a0c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -575,6 +575,8 @@ 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 */; }; @@ -1179,6 +1181,8 @@ EA05EFAA278DE53600828819 /* ClearableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearableModelProtocol.swift; sourceTree = ""; }; EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeIndicator.swift; sourceTree = ""; }; EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeIndicatorModel.swift; sourceTree = ""; }; + EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconModel.swift; sourceTree = ""; }; + EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = ""; }; EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = ""; }; EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = ""; }; EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = ""; }; @@ -2270,6 +2274,8 @@ B4CC8FBC29DF34680005D28B /* Badge.swift */, EA1758492BC97EF100A5C0D9 /* BadgeIndicatorModel.swift */, EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */, + EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */, + EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */, EA985C3F2970939A00F2FF2E /* TileletModel.swift */, EA985C3D2970938F00F2FF2E /* Tilelet.swift */, EA7D81612B2B6E7F00D29F9E /* IconModel.swift */, @@ -2911,6 +2917,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 */, @@ -2938,6 +2945,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 */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift b/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift new file mode 100644 index 00000000..71aef24a --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift @@ -0,0 +1,9 @@ +// +// ButtonIcon.swift +// MVMCoreUI +// +// Created by Matt Bruce on 4/12/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation diff --git a/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift new file mode 100644 index 00000000..ea6f7a8e --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift @@ -0,0 +1,80 @@ +// +// 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: 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 badgeIndicator: BadgeIndicatorModel? + public var expandDirection = ButtonIcon.BadgeIndicatorModel.ExpandDirection.right + 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 selectedable: Bool = false + public var iconOffSet: CGPoint = .zero + + private enum CodingKeys: String, CodingKey { + case id + case inverted + 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 selectedable + case iconOffSet + } + + required public convenience init(from decoder: Decoder) throws { + self.init() + let container = try decoder.container(keyedBy: CodingKeys.self) + id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false + 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 + + } + + 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) + } +} diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index caed0f13..59bf6966 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -20,6 +20,10 @@ 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 {} From 02973badbde55a1860ae2377314a1b814fe2ddd5 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 15 Apr 2024 13:12:04 -0500 Subject: [PATCH 25/49] refactor Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift b/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift index 059f4c7f..bdc724b6 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/BadgeIndicatorModel.swift @@ -14,7 +14,7 @@ open class BadgeIndicatorModel: MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "badgeIndicator" + public static var identifier: String { "badgeIndicator" } public var id: String = UUID().uuidString public var backgroundColor: Color? @@ -64,8 +64,8 @@ open class BadgeIndicatorModel: MoleculeModelProtocol { } required public convenience init(from decoder: Decoder) throws { - self.init() 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) From 122f5b6c977d72be322ec35d6b0c76787c7a85c3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 15 Apr 2024 13:12:15 -0500 Subject: [PATCH 26/49] added ButtonIcon Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift | 63 ++++++++++++++ .../Atomic/Atoms/Views/ButtonIconModel.swift | 86 ++++++++++++++++--- .../OtherHandlers/CoreUIModelMapping.swift | 1 + 3 files changed, 138 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift b/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift index 71aef24a..389033cb 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift @@ -7,3 +7,66 @@ // 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 + + 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 } +} + diff --git a/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift index ea6f7a8e..ed93e969 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ButtonIconModel.swift @@ -9,8 +9,7 @@ import Foundation import VDS - -open class ButtonIconModel: MoleculeModelProtocol { +open class ButtonIconModel: ButtonModelProtocol, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -23,8 +22,10 @@ open class ButtonIconModel: MoleculeModelProtocol { //-------------------------------------------------- public var surface: Surface { inverted ? .dark : .light } public var inverted: Bool = false - public var badgeIndicator: BadgeIndicatorModel? - public var expandDirection = ButtonIcon.BadgeIndicatorModel.ExpandDirection.right + 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 @@ -35,12 +36,48 @@ open class ButtonIconModel: MoleculeModelProtocol { public var fitToIcon: Bool = false public var hideBorder: Bool = true public var showBadgeIndicator: Bool = false - public var selectedable: Bool = false - public var iconOffSet: CGPoint = .zero + 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 @@ -53,15 +90,19 @@ open class ButtonIconModel: MoleculeModelProtocol { case fitToIcon case hideBorder case showBadgeIndicator - case selectedable - case iconOffSet + case selectable + case iconOffset } - - required public convenience init(from decoder: Decoder) throws { - self.init() + + //-------------------------------------------------- + // 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 @@ -69,12 +110,33 @@ open class ButtonIconModel: MoleculeModelProtocol { 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) } } diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index c864acdb..97f87e28 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -76,6 +76,7 @@ open class CoreUIModelMapping: ModelMapping { 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 From 6e5abcc91205b79182fc7d1733d7556c0e131264 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 15 Apr 2024 15:14:56 -0500 Subject: [PATCH 27/49] added tileContainer view/model Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++ .../Atomic/Atoms/Views/TileContainer.swift | 89 +++++++++++++++++ .../Atoms/Views/TileContainerModel.swift | 99 +++++++++++++++++++ .../Atomic/Extensions/VDS-Enums+Codable.swift | 48 +++++++++ 4 files changed, 244 insertions(+) create mode 100644 MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 4e9fdca8..b7c94d3f 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -578,6 +578,8 @@ 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 */; }; @@ -1184,6 +1186,8 @@ EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = ""; }; EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = ""; }; EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = ""; }; + EA6642902BCDA97300D81DC4 /* TileContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainer.swift; sourceTree = ""; }; + EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainerModel.swift; sourceTree = ""; }; EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = ""; }; EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; @@ -2274,6 +2278,8 @@ EA1758472BC97ED800A5C0D9 /* BadgeIndicator.swift */, EA17584B2BC9894800A5C0D9 /* ButtonIconModel.swift */, EA17584D2BC9895A00A5C0D9 /* ButtonIcon.swift */, + EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */, + EA6642902BCDA97300D81DC4 /* TileContainer.swift */, EA985C3F2970939A00F2FF2E /* TileletModel.swift */, EA985C3D2970938F00F2FF2E /* Tilelet.swift */, EA7D81612B2B6E7F00D29F9E /* IconModel.swift */, @@ -3063,6 +3069,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 */, @@ -3189,6 +3196,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 */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift new file mode 100644 index 00000000..3c588795 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -0,0 +1,89 @@ +// +// 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? + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public convenience required init() { + self.init(frame: .zero) + } + + //-------------------------------------------------- + // MARK: - Public + //-------------------------------------------------- + public func viewModelDidUpdate() { + + if molecule != nil { + molecule?.set(with: viewModel.molecule, delegateObject, additionalData) + } else if let moleculeView = ModelRegistry.createMolecule(viewModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { + addContentView(moleculeView) + } + + padding = viewModel.padding + color = viewModel.color + backgroundEffect = viewModel.backgroundEffect + aspectRatio = viewModel.aspectRatio + width = viewModel.width + height = viewModel.height + showBorder = viewModel.showBorder + showDropShadows = viewModel.showDropShadwows + //setup 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) + } + } + } + + //-------------------------------------------------- + // 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 + } + + //-------------------------------------------------- + // 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) + } + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift new file mode 100644 index 00000000..bb20d38d --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -0,0 +1,99 @@ +// +// 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, MoleculeModelProtocol { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "tileContainer" + public var id: String = UUID().uuidString + public var backgroundColor: Color? + public var padding: TileContainer.Padding = .padding4X + public var aspectRatio: TileContainer.AspectRatio = .ratio1x1 + public var color: TileContainer.BackgroundColor = .secondary + public var backgroundEffect: TileContainer.BackgroundEffect = .none + public var molecule: MoleculeModelProtocol + + private enum CodingKeys: String, CodingKey { + case id + case moleculeName + case molecule + case padding + case aspectRatio + case color + case backgroundEffect + } + 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.decodeModel(codingKey: .molecule) + padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? .padding4X + color = try container.decodeIfPresent(TileContainer.BackgroundColor.self, forKey: .color) ?? .secondary + backgroundEffect = try container.decodeIfPresent(TileContainer.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none + aspectRatio = try container.decodeIfPresent(TileContainer.AspectRatio.self, forKey: .aspectRatio) ?? .none + 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.encodeIfPresent(padding, forKey: .padding) + try container.encodeIfPresent(color, forKey: .color) + try container.encodeIfPresent(backgroundEffect, forKey: .backgroundEffect) + try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio) + try super.encode(to: encoder) + } +} + + +open class TileContainerBaseModel: Codable { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + 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 showDropShadwows: Bool = false + + private enum CodingKeys: String, CodingKey { + case backgroundImage + case action + case padding + case imageFallbackColor + case width + case height + case showBorder + case showDropShadows + } + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + backgroundImage = try container.decodeIfPresent(String.self, forKey: .backgroundImage) + width = try container.decodeIfPresent(CGFloat.self, forKey: .width) + height = try container.decodeIfPresent(CGFloat.self, forKey: .height) + action = try container.decodeModelIfPresent(codingKey: .action) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(backgroundImage, forKey: .backgroundImage) + try container.encodeIfPresent(width, forKey: .width) + try container.encodeIfPresent(height, forKey: .height) + try container.encodeModelIfPresent(action, forKey: .action) + } + + +} diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 19efa0a9..0cd9ba2e 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -100,6 +100,54 @@ extension VDS.TileContainerBase.BackgroundColor: Codable { } } +extension VDS.TileContainerBase.BackgroundEffect: Codable { + enum Error: Swift.Error { + case valueNotFound(type: String) + } + 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) From 61a5f4d7d1e7854f1d72b69dd8fdf56eec0f0375 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 15 Apr 2024 15:16:12 -0500 Subject: [PATCH 28/49] registered tilecontainer Signed-off-by: Matt Bruce --- MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 97f87e28..bbde1bf9 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -73,6 +73,7 @@ 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) From 44cbeeb69510ba16a8669bebb356a57742c33a83 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 15 Apr 2024 15:16:28 -0500 Subject: [PATCH 29/49] refactored the Tilelet with missing tilecontainer properties Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift | 8 +++- .../Atomic/Atoms/Views/TileletModel.swift | 47 +++++++++---------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift b/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift index 09f905e7..28ece685 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift @@ -39,10 +39,16 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{ // MARK: - Public //-------------------------------------------------- public func viewModelDidUpdate() { - color = viewModel.color + padding = viewModel.padding + color = viewModel.color + backgroundEffect = viewModel.backgroundEffect aspectRatio = viewModel.aspectRatio width = viewModel.width + height = viewModel.height + showBorder = viewModel.showBorder + showDropShadows = viewModel.showDropShadwows + if let value = viewModel.textWidth { textWidth = .value(value) } else if let percentage = viewModel.textPercentage { diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift index 62fac7e9..2abd1eec 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift @@ -9,7 +9,7 @@ import Foundation import VDS -open class TileletModel: MoleculeModelProtocol { +open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -17,23 +17,23 @@ 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 color: Tilelet.BackgroundColor = .black + public var padding: Tilelet.Padding = .large + public var aspectRatio: Tilelet.AspectRatio = .ratio1x1 + public var backgroundEffect: Tilelet.BackgroundEffect = .none 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 backgroundEffect case color case padding case aspectRatio @@ -42,27 +42,25 @@ open class TileletModel: MoleculeModelProtocol { 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 + backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor) + color = try container.decodeIfPresent(Tilelet.BackgroundColor.self, forKey: .color) ?? Tilelet.BackgroundColor.black + backgroundEffect = try container.decodeIfPresent(Tilelet.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none + padding = try container.decodeIfPresent(Tilelet.Padding.self, forKey: .padding) ?? Tilelet.Padding.small + aspectRatio = try container.decodeIfPresent(Tilelet.AspectRatio.self, forKey: .aspectRatio) ?? Tilelet.AspectRatio.none + 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,7 +97,7 @@ 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) @@ -112,9 +110,8 @@ open class TileletModel: MoleculeModelProtocol { 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) } } From 300047fdbe7893f0b575bf71b4dbd25e781ef4ef Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 16 Apr 2024 10:45:47 -0500 Subject: [PATCH 30/49] updated the loadImage made ViewModelMolecule optional Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/TileContainer.swift | 57 +++++++++++++++++-- .../Atoms/Views/TileContainerModel.swift | 5 +- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 3c588795..8356089c 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -35,10 +35,18 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ //-------------------------------------------------- public func viewModelDidUpdate() { - if molecule != nil { - molecule?.set(with: viewModel.molecule, delegateObject, additionalData) - } else if let moleculeView = ModelRegistry.createMolecule(viewModel.molecule, delegateObject: delegateObject, additionalData: additionalData) { - addContentView(moleculeView) + if let moleculeModel = viewModel.molecule{ + if molecule != nil { + molecule?.set(with: moleculeModel, delegateObject, additionalData) + } else if let moleculeView = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { + addContentView(moleculeView) + } + } else { + molecule = nil + } + + if let imageName = viewModel.backgroundImage { + loadImage(imageName) } padding = viewModel.padding @@ -61,6 +69,21 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ } } } + + 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 @@ -86,4 +109,30 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) } } + + public func needsToBeConstrained() -> Bool { true } + + public func horizontalAlignment() -> UIStackView.Alignment { .leading } +} + +extension UIImageView { + public func loadImage(withName imageName: String?, format: String? = nil, width: CGFloat? = nil, height: CGFloat? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) { + + MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in + + let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in + guard let self = self else { return } + self.image = image + completionHandler?(image,data,isFallbackImage) + })} + + let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback") + if let format = format, format.lowercased().contains("gif") { + // Gifs aren't supported by default and need special handling + MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: Int(width ?? 0), useHeight: height != nil, heightForS7: Int(height ?? 0), format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) + } else { + MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: Int(width ?? 0), useHeight: height != nil, heightForS7: Int(height ?? 0), format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) + } + }) + } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index bb20d38d..72ffb974 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -21,7 +21,7 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { public var aspectRatio: TileContainer.AspectRatio = .ratio1x1 public var color: TileContainer.BackgroundColor = .secondary public var backgroundEffect: TileContainer.BackgroundEffect = .none - public var molecule: MoleculeModelProtocol + public var molecule: MoleculeModelProtocol? private enum CodingKeys: String, CodingKey { case id @@ -35,7 +35,7 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { 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.decodeModel(codingKey: .molecule) + molecule = try container.decodeModelIfPresent(codingKey: .molecule) padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? .padding4X color = try container.decodeIfPresent(TileContainer.BackgroundColor.self, forKey: .color) ?? .secondary backgroundEffect = try container.decodeIfPresent(TileContainer.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none @@ -47,6 +47,7 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { 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 container.encodeIfPresent(padding, forKey: .padding) try container.encodeIfPresent(color, forKey: .color) try container.encodeIfPresent(backgroundEffect, forKey: .backgroundEffect) From f5d9423b1bb2f01e10604debfae22945fca84698 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 16 Apr 2024 11:47:08 -0500 Subject: [PATCH 31/49] removed code not nedded Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/TileContainer.swift | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 8356089c..4737c2db 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -109,30 +109,8 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ self.delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) } } - - public func needsToBeConstrained() -> Bool { true } - - public func horizontalAlignment() -> UIStackView.Alignment { .leading } } -extension UIImageView { - public func loadImage(withName imageName: String?, format: String? = nil, width: CGFloat? = nil, height: CGFloat? = nil, customFallbackImage: String? = nil, allowServerParameters: Bool = false, localBundle: Bundle? = nil, completionHandler: MVMCoreGetImageBlock? = nil) { - - MVMCoreDispatchUtility.performBlock(onMainThread: { [unowned self] in - - let finishedLoadingBlock: MVMCoreGetImageBlock = {[weak self] (image, data, isFallbackImage) in MVMCoreDispatchUtility.performBlock(onMainThread: { [weak self] in - guard let self = self else { return } - self.image = image - completionHandler?(image,data,isFallbackImage) - })} - - let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback") - if let format = format, format.lowercased().contains("gif") { - // Gifs aren't supported by default and need special handling - MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: Int(width ?? 0), useHeight: height != nil, heightForS7: Int(height ?? 0), format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) - } else { - MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: Int(width ?? 0), useHeight: height != nil, heightForS7: Int(height ?? 0), format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock) - } - }) - } +extension TileContainer: MVMCoreUIViewConstrainingProtocol { + public func horizontalAlignment() -> UIStackView.Alignment { .leading } } From 03318e863fff9b560a12facd269ff579620ed595 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 16 Apr 2024 14:27:17 -0500 Subject: [PATCH 32/49] refactored backgroundEffect Signed-off-by: Matt Bruce --- .../Atoms/Views/TileContainerModel.swift | 72 +++++++++++++++++-- .../Atomic/Atoms/Views/TileletModel.swift | 7 +- .../Atomic/Extensions/VDS-Enums+Codable.swift | 48 ------------- 3 files changed, 70 insertions(+), 57 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index 72ffb974..9933cdf1 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -20,8 +20,11 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { public var padding: TileContainer.Padding = .padding4X public var aspectRatio: TileContainer.AspectRatio = .ratio1x1 public var color: TileContainer.BackgroundColor = .secondary - public var backgroundEffect: TileContainer.BackgroundEffect = .none public var molecule: MoleculeModelProtocol? + public var backgroundEffect: TileContainer.BackgroundEffect { + guard let effect = backgroundEffectContainer else { return .none } + return .convert(from: effect) + } private enum CodingKeys: String, CodingKey { case id @@ -30,7 +33,6 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { case padding case aspectRatio case color - case backgroundEffect } required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) @@ -38,7 +40,6 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { molecule = try container.decodeModelIfPresent(codingKey: .molecule) padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? .padding4X color = try container.decodeIfPresent(TileContainer.BackgroundColor.self, forKey: .color) ?? .secondary - backgroundEffect = try container.decodeIfPresent(TileContainer.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none aspectRatio = try container.decodeIfPresent(TileContainer.AspectRatio.self, forKey: .aspectRatio) ?? .none try super.init(from: decoder) } @@ -50,7 +51,6 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { try container.encodeModelIfPresent(molecule, forKey: .molecule) try container.encodeIfPresent(padding, forKey: .padding) try container.encodeIfPresent(color, forKey: .color) - try container.encodeIfPresent(backgroundEffect, forKey: .backgroundEffect) try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio) try super.encode(to: encoder) } @@ -69,6 +69,7 @@ open class TileContainerBaseModel: Codable { public var height: CGFloat? public var showBorder: Bool = false public var showDropShadwows: Bool = false + internal var backgroundEffectContainer: BackgroundEffectContainer? private enum CodingKeys: String, CodingKey { case backgroundImage @@ -79,6 +80,7 @@ open class TileContainerBaseModel: Codable { case height case showBorder case showDropShadows + case backgroundEffect } required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) @@ -86,6 +88,7 @@ open class TileContainerBaseModel: Codable { width = try container.decodeIfPresent(CGFloat.self, forKey: .width) height = try container.decodeIfPresent(CGFloat.self, forKey: .height) action = try container.decodeModelIfPresent(codingKey: .action) + backgroundEffectContainer = try container.decodeIfPresent(BackgroundEffectContainer.self, forKey: .backgroundEffect) } public func encode(to encoder: Encoder) throws { @@ -93,8 +96,65 @@ open class TileContainerBaseModel: Codable { try container.encodeIfPresent(backgroundImage, forKey: .backgroundImage) try container.encodeIfPresent(width, forKey: .width) try container.encodeIfPresent(height, forKey: .height) + try container.encodeIfPresent(backgroundEffectContainer, forKey: .backgroundEffect) try container.encodeModelIfPresent(action, forKey: .action) } - - +} + +internal struct BackgroundEffectContainer: Codable { + public enum BackgroundEffectType: String, Codable { + case transparency + case none + case gradient + } + + public struct GradientValue: Codable { + public let firstColor: String + public let secondColor: String + } + + private enum CodingKeys: String, CodingKey { + case type + case value + } + + public let type: BackgroundEffectType + public let value: GradientValue? + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + type = try container.decode(BackgroundEffectType.self, forKey: .type) + if type == .gradient { + value = try container.decode(GradientValue.self, forKey: .value) + } else { + value = nil + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(type, forKey: .type) + switch type { + case .transparency, .none: + break // No value to encode + case .gradient: + try container.encode(value, forKey: .value) + } + } +} + +extension TileContainerBase.BackgroundEffect { + internal static func convert(from effect: BackgroundEffectContainer) -> Self { + switch effect.type { + case .transparency: + return .transparency + case .none: + return .none + case .gradient: + guard let value = effect.value else { + fatalError("Gradient must have a value") + } + return .gradient(value.firstColor, value.secondColor) + } + } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift index 2abd1eec..6afc9c12 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift @@ -20,7 +20,10 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { public var color: Tilelet.BackgroundColor = .black public var padding: Tilelet.Padding = .large public var aspectRatio: Tilelet.AspectRatio = .ratio1x1 - public var backgroundEffect: Tilelet.BackgroundEffect = .none + public var backgroundEffect: Tilelet.BackgroundEffect { + guard let effect = backgroundEffectContainer else { return .none } + return .convert(from: effect) + } public var badge: Tilelet.BadgeModel? public var title: LabelModel? public var subTitle: LabelModel? @@ -33,7 +36,6 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { case id case moleculeName case backgroundColor - case backgroundEffect case color case padding case aspectRatio @@ -50,7 +52,6 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor) color = try container.decodeIfPresent(Tilelet.BackgroundColor.self, forKey: .color) ?? Tilelet.BackgroundColor.black - backgroundEffect = try container.decodeIfPresent(Tilelet.BackgroundEffect.self, forKey: .backgroundEffect) ?? .none padding = try container.decodeIfPresent(Tilelet.Padding.self, forKey: .padding) ?? Tilelet.Padding.small aspectRatio = try container.decodeIfPresent(Tilelet.AspectRatio.self, forKey: .aspectRatio) ?? Tilelet.AspectRatio.none badge = try container.decodeIfPresent(Tilelet.BadgeModel.self, forKey: .badge) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 0cd9ba2e..19efa0a9 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -100,54 +100,6 @@ extension VDS.TileContainerBase.BackgroundColor: Codable { } } -extension VDS.TileContainerBase.BackgroundEffect: Codable { - enum Error: Swift.Error { - case valueNotFound(type: String) - } - 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) From 08a2079654ce59897b9313866723459cc92cacd4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 16 Apr 2024 14:35:56 -0500 Subject: [PATCH 33/49] rearranged Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index 9933cdf1..079f2823 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -17,10 +17,10 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { public static var identifier: String = "tileContainer" public var id: String = UUID().uuidString public var backgroundColor: Color? + public var molecule: MoleculeModelProtocol? public var padding: TileContainer.Padding = .padding4X public var aspectRatio: TileContainer.AspectRatio = .ratio1x1 public var color: TileContainer.BackgroundColor = .secondary - public var molecule: MoleculeModelProtocol? public var backgroundEffect: TileContainer.BackgroundEffect { guard let effect = backgroundEffectContainer else { return .none } return .convert(from: effect) From 0ddf76b576a729260d2c95f7dafe052720d7e99b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 16 Apr 2024 15:15:02 -0500 Subject: [PATCH 34/49] refactored out base enums into base model Signed-off-by: Matt Bruce --- .../Atoms/Views/TileContainerModel.swift | 72 +++++++++---------- .../Atomic/Atoms/Views/TileletModel.swift | 22 +----- 2 files changed, 36 insertions(+), 58 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index 079f2823..56693c53 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -9,7 +9,7 @@ import Foundation import VDS -open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { +open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -17,30 +17,18 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { public static var identifier: String = "tileContainer" public var id: String = UUID().uuidString public var backgroundColor: Color? + public var molecule: MoleculeModelProtocol? - public var padding: TileContainer.Padding = .padding4X - public var aspectRatio: TileContainer.AspectRatio = .ratio1x1 - public var color: TileContainer.BackgroundColor = .secondary - public var backgroundEffect: TileContainer.BackgroundEffect { - guard let effect = backgroundEffectContainer else { return .none } - return .convert(from: effect) - } private enum CodingKeys: String, CodingKey { case id case moleculeName case molecule - case padding - case aspectRatio - case color } 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) - padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? .padding4X - color = try container.decodeIfPresent(TileContainer.BackgroundColor.self, forKey: .color) ?? .secondary - aspectRatio = try container.decodeIfPresent(TileContainer.AspectRatio.self, forKey: .aspectRatio) ?? .none try super.init(from: decoder) } @@ -49,15 +37,12 @@ open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { try container.encode(id, forKey: .id) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeModelIfPresent(molecule, forKey: .molecule) - try container.encodeIfPresent(padding, forKey: .padding) - try container.encodeIfPresent(color, forKey: .color) - try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio) try super.encode(to: encoder) } } -open class TileContainerBaseModel: Codable { +open class TileContainerBaseModel> : Codable{ //-------------------------------------------------- // MARK: - Properties @@ -69,12 +54,32 @@ open class TileContainerBaseModel: Codable { public var height: CGFloat? public var showBorder: Bool = false public var showDropShadwows: Bool = false - internal var backgroundEffectContainer: BackgroundEffectContainer? + public var padding = PaddingType.defaultValue + public var color: TileContainerType.BackgroundColor = .black + public var aspectRatio: TileContainerType.AspectRatio = .ratio1x1 + internal var backgroundEffectCodable: BackgroundEffectCodable? + public var backgroundEffect: TileContainerType.BackgroundEffect { + guard let effect = backgroundEffectCodable else { return .none } + switch effect.type { + case .transparency: + return .transparency + case .none: + return .none + case .gradient: + guard let value = effect.value else { + fatalError("Gradient must have a value") + } + return .gradient(value.firstColor, value.secondColor) + } + } + private enum CodingKeys: String, CodingKey { case backgroundImage case action case padding + case color + case aspectRatio case imageFallbackColor case width case height @@ -88,7 +93,11 @@ open class TileContainerBaseModel: Codable { width = try container.decodeIfPresent(CGFloat.self, forKey: .width) height = try container.decodeIfPresent(CGFloat.self, forKey: .height) action = try container.decodeModelIfPresent(codingKey: .action) - backgroundEffectContainer = try container.decodeIfPresent(BackgroundEffectContainer.self, forKey: .backgroundEffect) + 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 + backgroundEffectCodable = try container.decodeIfPresent(BackgroundEffectCodable.self, forKey: .backgroundEffect) + } public func encode(to encoder: Encoder) throws { @@ -96,12 +105,15 @@ open class TileContainerBaseModel: Codable { try container.encodeIfPresent(backgroundImage, forKey: .backgroundImage) try container.encodeIfPresent(width, forKey: .width) try container.encodeIfPresent(height, forKey: .height) - try container.encodeIfPresent(backgroundEffectContainer, forKey: .backgroundEffect) + try container.encodeIfPresent(backgroundEffectCodable, forKey: .backgroundEffect) + try container.encodeIfPresent(padding, forKey: .padding) + try container.encodeIfPresent(color, forKey: .color) + try container.encodeIfPresent(aspectRatio, forKey: .aspectRatio) try container.encodeModelIfPresent(action, forKey: .action) } } -internal struct BackgroundEffectContainer: Codable { +internal struct BackgroundEffectCodable: Codable { public enum BackgroundEffectType: String, Codable { case transparency case none @@ -142,19 +154,3 @@ internal struct BackgroundEffectContainer: Codable { } } } - -extension TileContainerBase.BackgroundEffect { - internal static func convert(from effect: BackgroundEffectContainer) -> Self { - switch effect.type { - case .transparency: - return .transparency - case .none: - return .none - case .gradient: - guard let value = effect.value else { - fatalError("Gradient must have a value") - } - return .gradient(value.firstColor, value.secondColor) - } - } -} diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift index 6afc9c12..b287a9ff 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileletModel.swift @@ -9,7 +9,7 @@ import Foundation import VDS -open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { +open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -17,13 +17,7 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { public static var identifier: String = "tilelet" public var id: String = UUID().uuidString public var backgroundColor: Color? - public var color: Tilelet.BackgroundColor = .black - public var padding: Tilelet.Padding = .large - public var aspectRatio: Tilelet.AspectRatio = .ratio1x1 - public var backgroundEffect: Tilelet.BackgroundEffect { - guard let effect = backgroundEffectContainer else { return .none } - return .convert(from: effect) - } + public var badge: Tilelet.BadgeModel? public var title: LabelModel? public var subTitle: LabelModel? @@ -35,10 +29,6 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { private enum CodingKeys: String, CodingKey { case id case moleculeName - case backgroundColor - case color - case padding - case aspectRatio case badge case title case subTitle @@ -50,10 +40,6 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { 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 - backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor) - color = try container.decodeIfPresent(Tilelet.BackgroundColor.self, forKey: .color) ?? Tilelet.BackgroundColor.black - padding = try container.decodeIfPresent(Tilelet.Padding.self, forKey: .padding) ?? Tilelet.Padding.small - aspectRatio = try container.decodeIfPresent(Tilelet.AspectRatio.self, forKey: .aspectRatio) ?? Tilelet.AspectRatio.none 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) @@ -102,10 +88,6 @@ open class TileletModel: TileContainerBaseModel, MoleculeModelProtocol { 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) From c87bbb3a7861d4b6471845202b074fcbe46623e2 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 17 Apr 2024 09:43:50 -0500 Subject: [PATCH 35/49] refdactored to use better codable for the BackgroundEffect Enum Signed-off-by: Matt Bruce --- .../Atoms/Views/TileContainerModel.swift | 63 +------------------ .../Atomic/Extensions/VDS-Enums+Codable.swift | 47 ++++++++++++++ 2 files changed, 50 insertions(+), 60 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index 56693c53..0c03df02 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -57,22 +57,7 @@ open class TileContainerBaseModel Date: Wed, 17 Apr 2024 16:24:03 -0500 Subject: [PATCH 36/49] VDS Team removed 2x and replaced with 3x in the spec. Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 3e6ed245..d78e7be6 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -112,8 +112,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": From c48eab03eca01a71062a396758caedb46f705b37 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Wed, 17 Apr 2024 19:23:45 -0400 Subject: [PATCH 37/49] Digital PCT265 defect CXTDT-546577 - Track UI updates from module changes. --- .../Atomic/Protocols/MoleculeDelegateProtocol.swift | 3 ++- MVMCoreUI/BaseControllers/ViewController.swift | 3 ++- .../Behaviors/ReplaceableMoleculeBehaviorModel.swift | 9 ++++++--- MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift | 3 +++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift b/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift index e7a4bdef..e8cae35b 100644 --- a/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/MoleculeDelegateProtocol.swift @@ -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 { diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 5997847d..452d2962 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -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) } } diff --git a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift index 2e38017c..e52ee464 100644 --- a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift +++ b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift @@ -62,7 +62,7 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior { } } if moleculeModels.count > 0 { - delegateObject?.moleculeDelegate?.replaceMoleculeData(moleculeModels) + delegateObject?.moleculeDelegate?.replaceMoleculeData(moleculeModels, completionHandler: nil) } } @@ -95,8 +95,11 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior { return nil } } - if modules.count > 0 { - delegateObject?.moleculeDelegate?.replaceMoleculeData(modules) + guard modules.count > 0 else { return } + 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) } } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift index e74bc580..74a27f7f 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.swift @@ -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]) { } } From 652fcddcdace74048e4bc2eddf02910203870009 Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Tue, 23 Apr 2024 09:40:22 -0400 Subject: [PATCH 38/49] Digital PCT265 defect CXTDT-546577 - Remove transcendsPageUpdates to prevent multiple replaces from muliple ReplaceMoleculeBehaviors listening and replacing. --- .../ReplaceableMoleculeBehaviorModel.swift | 2 -- MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig | 13 +++++++++++++ MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig create mode 100644 MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig diff --git a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift index e52ee464..d8d0c476 100644 --- a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift +++ b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift @@ -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 diff --git a/MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig b/MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig new file mode 100644 index 00000000..91c90442 --- /dev/null +++ b/MVMCoreUI/SupportingFiles/mvmcoreui.xcconfig @@ -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" diff --git a/MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig b/MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig new file mode 100644 index 00000000..d6815c1d --- /dev/null +++ b/MVMCoreUI/SupportingFiles/mvmcoreui_dev.xcconfig @@ -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" From adda10efb052e0fc85ef7c9952c5f15f44f8034c Mon Sep 17 00:00:00 2001 From: "Hedden, Kyle Matthew" Date: Tue, 23 Apr 2024 09:41:35 -0400 Subject: [PATCH 39/49] Digital PCT265 defect CXTDT-546577 - Logging for clarity. --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++++++- .../Behaviors/ReplaceableMoleculeBehaviorModel.swift | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 64bcc3ed..8fafb0c9 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -771,6 +771,8 @@ 5822720A2B1FC55F00F75BAE /* RotorHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RotorHandler.swift; sourceTree = ""; }; 5846ABF52B4762A600FA6C76 /* PollingBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PollingBehaviorModel.swift; sourceTree = ""; }; 5870636E2ACF238E00CA18D5 /* ReadableDecodingErrors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadableDecodingErrors.swift; sourceTree = ""; }; + 5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui.xcconfig; sourceTree = ""; }; + 5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = mvmcoreui_dev.xcconfig; sourceTree = ""; }; 58A9DD7C2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplaceableMoleculeBehaviorModel.swift; sourceTree = ""; }; 608211262AC6AF8200C3FC39 /* MVMCoreUILoggingHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingHandler.swift; sourceTree = ""; }; 8D070BAF241B56530099AC56 /* ListRightVariableTotalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableTotalDataModel.swift; sourceTree = ""; }; @@ -2345,6 +2347,8 @@ D29DF31421ECECA7003B2FB9 /* SupportingFiles */ = { isa = PBXGroup; children = ( + 5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */, + 5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */, D29DF32721EE8736003B2FB9 /* Strings */, D29DF26621E6A9E4003B2FB9 /* ThirdParty */, D29DF31521ECECC0003B2FB9 /* Fonts */, @@ -3230,6 +3234,7 @@ /* Begin XCBuildConfiguration section */ D29DF0D221E404D4003B2FB9 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 5878F0A52BD7E6BE00ADE23D /* mvmcoreui_dev.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -3288,7 +3293,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 = ""; @@ -3297,6 +3302,7 @@ }; D29DF0D321E404D4003B2FB9 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 5878F0A42BD7E68800ADE23D /* mvmcoreui.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; BUILD_LIBRARY_FOR_DISTRIBUTION = YES; diff --git a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift index d8d0c476..51428234 100644 --- a/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift +++ b/MVMCoreUI/Behaviors/ReplaceableMoleculeBehaviorModel.swift @@ -94,6 +94,10 @@ public class ReplaceableMoleculeBehavior: PageMoleculeTransformationBehavior { } } 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 } From 5698f1f5c1fe8f9b6e98c351f7a504d40e43ec1c Mon Sep 17 00:00:00 2001 From: Xi Zhang Date: Tue, 23 Apr 2024 17:18:59 -0400 Subject: [PATCH 40/49] Provide an API for checking selected date is today. --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++++ .../DateDropdownEntryField.swift | 8 +------ ...ateDropdownEntryFieldModel+Extension.swift | 21 +++++++++++++++++++ .../DateDropdownEntryFieldModel.swift | 6 ++++++ 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8fafb0c9..5d09ab93 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -152,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 */; }; @@ -752,6 +753,7 @@ 444FB7C02821B73200DFE692 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = ""; }; 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = ""; }; 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = ""; }; + 4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateDropdownEntryFieldModel+Extension.swift"; sourceTree = ""; }; 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; @@ -1339,6 +1341,7 @@ children = ( 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */, 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */, + 4B002AC92BD855EC009BC9C1 /* DateDropdownEntryFieldModel+Extension.swift */, ); path = "Date Dropdown"; sourceTree = ""; @@ -3084,6 +3087,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 */, diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryField.swift index 234809d3..129dbc0b 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryField.swift @@ -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) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel+Extension.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel+Extension.swift new file mode 100644 index 00000000..9ce5d051 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel+Extension.swift @@ -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()) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel.swift index 53c7206c..f2f4df05 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Date Dropdown/DateDropdownEntryFieldModel.swift @@ -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 //-------------------------------------------------- From c9589e9b94c06cce2735cfa9e186b8f8f65dddfe Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 24 Apr 2024 17:15:11 -0500 Subject: [PATCH 41/49] added nameforReuse Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 4737c2db..941e9b3e 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -97,6 +97,16 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ 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 model = model as? ButtonGroupModel else { + return "tileContainer<>" + } + return "tileContainer<\(model.moleculeName)>" + } + //-------------------------------------------------- // MARK: - Overrides From 980ffaee67641088cd2f31731472edfe2c41ea64 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 24 Apr 2024 17:15:36 -0500 Subject: [PATCH 42/49] removed carriage return Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 941e9b3e..d93c8799 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -107,7 +107,6 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ return "tileContainer<\(model.moleculeName)>" } - //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- From 725d80b5ce560616e256ac31aa6343cd7db736b3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 24 Apr 2024 17:24:20 -0500 Subject: [PATCH 43/49] added praentmoleculemodel protocol Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/TileContainerModel.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index 0c03df02..b6932ef9 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -9,7 +9,7 @@ import Foundation import VDS -open class TileContainerModel: TileContainerBaseModel, MoleculeModelProtocol { +open class TileContainerModel: TileContainerBaseModel, ParentMoleculeModelProtocol, MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties @@ -19,7 +19,15 @@ open class TileContainerModel: TileContainerBaseModel Bool { + return try replaceChildMolecule(at: &self.molecule, with: molecule) + } + private enum CodingKeys: String, CodingKey { case id case moleculeName From dac871125855796ccc75266e6bd316aee7324bb6 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Apr 2024 09:07:40 -0500 Subject: [PATCH 44/49] ensure molecule is removed from parent Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index d93c8799..7c2c13ac 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -21,7 +21,13 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ public var delegateObject: MVMCoreUIDelegateObject? public var additionalData: [AnyHashable: Any]? - public var molecule: MoleculeViewProtocol? + public var molecule: MoleculeViewProtocol? { + willSet { + if newValue == nil { + molecule?.removeFromSuperview() + } + } + } //-------------------------------------------------- // MARK: - Initializers From 0f3d7c13208ec8bdf273add2e00f8e77b05d54c0 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Apr 2024 09:13:25 -0500 Subject: [PATCH 45/49] removed setting the molecule to nil Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 7c2c13ac..f74c7885 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -47,8 +47,6 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ } else if let moleculeView = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { addContentView(moleculeView) } - } else { - molecule = nil } if let imageName = viewModel.backgroundImage { From 9292e6a8d0ac3bbdbbc26c91469a23bb9f34b607 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Apr 2024 09:18:49 -0500 Subject: [PATCH 46/49] set the molecule to the moleculeView found Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index f74c7885..77f32707 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -41,10 +41,11 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ //-------------------------------------------------- public func viewModelDidUpdate() { - if let moleculeModel = viewModel.molecule{ - if molecule != nil { - molecule?.set(with: moleculeModel, delegateObject, additionalData) + if let moleculeModel = viewModel.molecule { + if let molecule { + molecule.set(with: moleculeModel, delegateObject, additionalData) } else if let moleculeView = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { + molecule = moleculeView addContentView(moleculeView) } } From e25a0cadc1724e6c780ac3dea0c39feebe93bdd1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Apr 2024 09:55:50 -0500 Subject: [PATCH 47/49] updated nameforreuse Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 77f32707..57b8b8f2 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -42,7 +42,8 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ public func viewModelDidUpdate() { if let moleculeModel = viewModel.molecule { - if let 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 @@ -106,10 +107,13 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ /// 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 model = model as? ButtonGroupModel else { - return "tileContainer<>" - } - return "tileContainer<\(model.moleculeName)>" + 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)>" } //-------------------------------------------------- From ce8b5b85cb841d0e20a86084d4d89bded015cf28 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 25 Apr 2024 14:56:00 -0500 Subject: [PATCH 48/49] sync properties also ensured same properties were in Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Views/TileContainer.swift | 23 +++++--- .../Atoms/Views/TileContainerModel.swift | 28 +++++++--- MVMCoreUI/Atomic/Atoms/Views/Tilelet.swift | 56 +++++++++++++++---- 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift index 57b8b8f2..e00c2784 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainer.swift @@ -51,19 +51,12 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ } } + // set backgroundImage if let imageName = viewModel.backgroundImage { loadImage(imageName) } - padding = viewModel.padding - color = viewModel.color - backgroundEffect = viewModel.backgroundEffect - aspectRatio = viewModel.aspectRatio - width = viewModel.width - height = viewModel.height - showBorder = viewModel.showBorder - showDropShadows = viewModel.showDropShadwows - //setup action + //set action if let action = viewModel.action { //add the subscriber onClick = { [weak self] control in @@ -74,6 +67,18 @@ open class TileContainer: VDS.TileContainer, VDSMoleculeViewProtocol{ 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) { diff --git a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift index b6932ef9..895bb027 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TileContainerModel.swift @@ -55,37 +55,44 @@ open class TileContainerBaseModel Date: Thu, 25 Apr 2024 15:14:55 -0500 Subject: [PATCH 49/49] forgot to add the action Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift b/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift index 389033cb..89237662 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ButtonIcon.swift @@ -27,6 +27,14 @@ open class ButtonIcon: VDS.ButtonIcon, VDSMoleculeViewProtocol { 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