Merge branch 'develop' into feature/badge
This commit is contained in:
commit
48c3e4b86a
@ -129,6 +129,8 @@
|
||||
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 */; };
|
||||
22B678FD29E82B0300CF4196 /* ListNotificationAuthModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22B678FC29E82B0300CF4196 /* ListNotificationAuthModel.swift */; };
|
||||
27559EFC27D691D3000836C1 /* ViewMaskingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */; };
|
||||
27577DCD286CA959001EC47E /* MoleculeMaskingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */; };
|
||||
279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; };
|
||||
@ -202,7 +204,6 @@
|
||||
9458C3172406C8FD00930963 /* UIFont+FontWrapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */; };
|
||||
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; };
|
||||
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C0150924215643005811A9 /* ActionTopAlertModel.swift */; };
|
||||
94C0150C2421564A005811A9 /* ActionCollapseNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C0150B2421564A005811A9 /* ActionCollapseNotificationModel.swift */; };
|
||||
94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */; };
|
||||
94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */; };
|
||||
@ -278,15 +279,20 @@
|
||||
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */; };
|
||||
AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */; };
|
||||
AF1C33652883B5A4006B1001 /* ActionTopNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33642883B5A4006B1001 /* ActionTopNotificationHandler.swift */; };
|
||||
AF1C33672883B712006B1001 /* ActionPopupHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33662883B712006B1001 /* ActionPopupHandler.swift */; };
|
||||
AF1C336928859778006B1001 /* ActionAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336828859778006B1001 /* ActionAlertHandler.swift */; };
|
||||
AF1C336B28859C73006B1001 /* ActionTopAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336A28859C73006B1001 /* ActionTopAlertHandler.swift */; };
|
||||
AF1C336D28859EE1006B1001 /* ActionOpenPanelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336C28859EE1006B1001 /* ActionOpenPanelHandler.swift */; };
|
||||
AF1C336F2885A16A006B1001 /* ActionCollapseNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */; };
|
||||
AF1C33712885AE76006B1001 /* MVMCoreUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */; };
|
||||
AF1C33732885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */; };
|
||||
AF60A7F62892D2E300919EEB /* ActionDismissNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */; };
|
||||
AF60A7F82892D34D00919EEB /* ActionDismissNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */; };
|
||||
AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */; };
|
||||
AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509629E477C0009DC2AD /* AlertHandler.swift */; };
|
||||
AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E509729E477C0009DC2AD /* AlertController.swift */; };
|
||||
AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4931F29E5CA73001A9663 /* AlertOperation.swift */; };
|
||||
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 */; };
|
||||
@ -346,8 +352,8 @@
|
||||
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */; };
|
||||
D20923592450ECE00044AD09 /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20923582450ECE00044AD09 /* TableView.swift */; };
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
D20C7009250BF99B0095B21C /* TopNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C7008250BF99B0095B21C /* TopNotificationModel.swift */; };
|
||||
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */; };
|
||||
D20C7009250BF99B0095B21C /* NotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C7008250BF99B0095B21C /* NotificationModel.swift */; };
|
||||
D20C700B250BFDE40095B21C /* NotificationContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C700A250BFDE40095B21C /* NotificationContainerView.swift */; };
|
||||
D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20F3B43252E00E4004B3F56 /* PageProtocol.swift */; };
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; };
|
||||
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
||||
@ -366,7 +372,7 @@
|
||||
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
|
||||
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */; };
|
||||
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
|
||||
D23118B325124E18001C8440 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* Notification.swift */; };
|
||||
D23118B325124E18001C8440 /* NotificationMoleculeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* NotificationMoleculeView.swift */; };
|
||||
D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; };
|
||||
D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */; };
|
||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; };
|
||||
@ -457,16 +463,6 @@
|
||||
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */; };
|
||||
D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */; };
|
||||
D29DF12921E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */; };
|
||||
D29DF12C21E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */; };
|
||||
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */; };
|
||||
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */; };
|
||||
D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */; };
|
||||
D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF15321E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF17521E69E1F003B2FB9 /* ButtonDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -525,10 +521,8 @@
|
||||
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C521A823EDE79E00CA2634 /* ViewController.swift */; };
|
||||
D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C78CD124228BBD00B69FDE /* ActionOpenPanelModel.swift */; };
|
||||
D2CAC7CB251104E100C75681 /* NotificationXButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */; };
|
||||
D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CC251104FE00C75681 /* NotificationModel.swift */; };
|
||||
D2CAC7CD251104FE00C75681 /* NotificationMoleculeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CC251104FE00C75681 /* NotificationMoleculeModel.swift */; };
|
||||
D2CAC7CF2511052300C75681 /* CollapsableNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */; };
|
||||
D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */; };
|
||||
D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */; };
|
||||
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */; };
|
||||
D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */; };
|
||||
D2D3957A252FDBB300047B11 /* ModalSectionListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D39579252FDBB300047B11 /* ModalSectionListTemplate.swift */; };
|
||||
@ -558,27 +552,9 @@
|
||||
D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */; };
|
||||
D2ED27EB254B0CE700A1C293 /* UIAlertActionStyle+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */; };
|
||||
D2ED27EC254B0CE700A1C293 /* UIAlertControllerStyle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */; };
|
||||
D2ED27ED254B0CE700A1C293 /* ActionPopupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27E8254B0CE600A1C293 /* ActionPopupModel.swift */; };
|
||||
D2ED27EE254B0CE700A1C293 /* ActionAlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27E9254B0CE600A1C293 /* ActionAlertModel.swift */; };
|
||||
D2ED27EF254B0CE700A1C293 /* AlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27EA254B0CE700A1C293 /* AlertModel.swift */; };
|
||||
D2ED27FB254B0E0300A1C293 /* MVMCoreAlertDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED27F2254B0E0200A1C293 /* MVMCoreAlertDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27F3254B0E0200A1C293 /* MVMCoreAlertObject+Swift.swift */; };
|
||||
D2ED27FD254B0E0300A1C293 /* MVMCoreAlertOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27F4254B0E0200A1C293 /* MVMCoreAlertOperation.m */; };
|
||||
D2ED27FE254B0E0300A1C293 /* MVMCoreAlertObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED27F5254B0E0200A1C293 /* MVMCoreAlertObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED27FF254B0E0300A1C293 /* MVMCoreAlertHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED27F6254B0E0200A1C293 /* MVMCoreAlertHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED2800254B0E0300A1C293 /* MVMCoreAlertHandler+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27F7254B0E0200A1C293 /* MVMCoreAlertHandler+Extension.swift */; };
|
||||
D2ED2801254B0E0300A1C293 /* MVMCoreAlertOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED27F8254B0E0200A1C293 /* MVMCoreAlertOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED2802254B0E0300A1C293 /* MVMCoreAlertObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27F9254B0E0200A1C293 /* MVMCoreAlertObject.m */; };
|
||||
D2ED2803254B0E0300A1C293 /* MVMCoreAlertHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27FA254B0E0300A1C293 /* MVMCoreAlertHandler.m */; };
|
||||
D2ED280C254B0EB800A1C293 /* MVMCoreTopAlertAnimationDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2805254B0EB700A1C293 /* MVMCoreTopAlertAnimationDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED280D254B0EB800A1C293 /* MVMCoreTopAlertOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2806254B0EB700A1C293 /* MVMCoreTopAlertOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED280E254B0EB800A1C293 /* MVMCoreTopAlertOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D2ED2807254B0EB700A1C293 /* MVMCoreTopAlertOperation.m */; };
|
||||
D2ED280F254B0EB800A1C293 /* MVMCoreTopAlertViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2808254B0EB700A1C293 /* MVMCoreTopAlertViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED2810254B0EB800A1C293 /* MVMCoreTopAlertDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2809254B0EB700A1C293 /* MVMCoreTopAlertDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED2811254B0EB800A1C293 /* MVMCoreTopAlertObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED280A254B0EB700A1C293 /* MVMCoreTopAlertObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2ED280B254B0EB800A1C293 /* MVMCoreTopAlertObject.m */; };
|
||||
D2ED2815254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2814254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED2818254B115400A1C293 /* MVMCoreUIActionDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2817254B112900A1C293 /* MVMCoreUIActionDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2ED27FC254B0E0300A1C293 /* AlertObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27F3254B0E0200A1C293 /* AlertObject.swift */; };
|
||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; };
|
||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
||||
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */; };
|
||||
@ -741,6 +717,8 @@
|
||||
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
|
||||
1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; };
|
||||
1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; };
|
||||
22B678F829E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetNotificationAuthStatusBehavior.swift; sourceTree = "<group>"; };
|
||||
22B678FC29E82B0300CF4196 /* ListNotificationAuthModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListNotificationAuthModel.swift; sourceTree = "<group>"; };
|
||||
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewMaskingProtocol.swift; sourceTree = "<group>"; };
|
||||
27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeMaskingProtocol.swift; sourceTree = "<group>"; };
|
||||
279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = "<group>"; };
|
||||
@ -815,7 +793,6 @@
|
||||
9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+FontWrapping.h"; sourceTree = "<group>"; };
|
||||
9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+FontWrapping.m"; sourceTree = "<group>"; };
|
||||
948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = "<group>"; };
|
||||
94C0150924215643005811A9 /* ActionTopAlertModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionTopAlertModel.swift; sourceTree = "<group>"; };
|
||||
94C0150B2421564A005811A9 /* ActionCollapseNotificationModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionCollapseNotificationModel.swift; sourceTree = "<group>"; };
|
||||
94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeModel.swift; sourceTree = "<group>"; };
|
||||
94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeUnderlineModel.swift; sourceTree = "<group>"; };
|
||||
@ -890,15 +867,20 @@
|
||||
AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = "<group>"; };
|
||||
AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = "<group>"; };
|
||||
AF1C33642883B5A4006B1001 /* ActionTopNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionTopNotificationHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C33662883B712006B1001 /* ActionPopupHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionPopupHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C336828859778006B1001 /* ActionAlertHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionAlertHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C336A28859C73006B1001 /* ActionTopAlertHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionTopAlertHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C336C28859EE1006B1001 /* ActionOpenPanelHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenPanelHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCollapseNotificationHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIActionHandler.swift; sourceTree = "<group>"; };
|
||||
AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIActionOpenPageHandler.swift; sourceTree = "<group>"; };
|
||||
AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDismissNotificationModel.swift; sourceTree = "<group>"; };
|
||||
AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDismissNotificationHandler.swift; sourceTree = "<group>"; };
|
||||
AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAccessibilityTraits+Codable.swift"; sourceTree = "<group>"; };
|
||||
AF7E509629E477C0009DC2AD /* AlertHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertHandler.swift; sourceTree = "<group>"; };
|
||||
AF7E509729E477C0009DC2AD /* AlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertController.swift; sourceTree = "<group>"; };
|
||||
AFA4931F29E5CA73001A9663 /* AlertOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertOperation.swift; sourceTree = "<group>"; };
|
||||
AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationHandler.swift; sourceTree = "<group>"; };
|
||||
AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUILoggingDelegateProtocol.swift; sourceTree = "<group>"; };
|
||||
AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = "<group>"; };
|
||||
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
|
||||
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
|
||||
B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; };
|
||||
@ -958,8 +940,8 @@
|
||||
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerModelBase.swift; sourceTree = "<group>"; };
|
||||
D20923582450ECE00044AD09 /* TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = "<group>"; };
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
|
||||
D20C7008250BF99B0095B21C /* TopNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopNotificationModel.swift; sourceTree = "<group>"; };
|
||||
D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D20C7008250BF99B0095B21C /* NotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationModel.swift; sourceTree = "<group>"; };
|
||||
D20C700A250BFDE40095B21C /* NotificationContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContainerView.swift; sourceTree = "<group>"; };
|
||||
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageProtocol.swift; sourceTree = "<group>"; };
|
||||
D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModel.swift; sourceTree = "<group>"; };
|
||||
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||
@ -978,7 +960,7 @@
|
||||
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTemplateModel.swift; sourceTree = "<group>"; };
|
||||
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D23118B225124E18001C8440 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
|
||||
D23118B225124E18001C8440 /* NotificationMoleculeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationMoleculeView.swift; sourceTree = "<group>"; };
|
||||
D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
D2351C7B24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinks.swift; sourceTree = "<group>"; };
|
||||
D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = "<group>"; };
|
||||
@ -1069,16 +1051,6 @@
|
||||
D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSLayoutConstraint+MFConvenience.m"; sourceTree = "<group>"; };
|
||||
D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUISplitViewController.h; sourceTree = "<group>"; };
|
||||
D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISplitViewController.m; sourceTree = "<group>"; };
|
||||
D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertMainView.h; sourceTree = "<group>"; };
|
||||
D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertView.h; sourceTree = "<group>"; };
|
||||
D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertExpandableView.m; sourceTree = "<group>"; };
|
||||
D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertShortView.h; sourceTree = "<group>"; };
|
||||
D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertBaseView.h; sourceTree = "<group>"; };
|
||||
D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertView.m; sourceTree = "<group>"; };
|
||||
D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertMainView.m; sourceTree = "<group>"; };
|
||||
D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertShortView.m; sourceTree = "<group>"; };
|
||||
D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertExpandableView.h; sourceTree = "<group>"; };
|
||||
D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertBaseView.m; sourceTree = "<group>"; };
|
||||
D29DF13821E68636003B2FB9 /* MFStyler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFStyler.h; sourceTree = "<group>"; };
|
||||
D29DF13921E68637003B2FB9 /* MFStyler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFStyler.m; sourceTree = "<group>"; };
|
||||
D29DF14421E68728003B2FB9 /* MFSizeObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFSizeObject.m; sourceTree = "<group>"; };
|
||||
@ -1139,10 +1111,8 @@
|
||||
D2C521A823EDE79E00CA2634 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
D2C78CD124228BBD00B69FDE /* ActionOpenPanelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionOpenPanelModel.swift; sourceTree = "<group>"; };
|
||||
D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButtonModel.swift; sourceTree = "<group>"; };
|
||||
D2CAC7CC251104FE00C75681 /* NotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationModel.swift; sourceTree = "<group>"; };
|
||||
D2CAC7CC251104FE00C75681 /* NotificationMoleculeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationMoleculeModel.swift; sourceTree = "<group>"; };
|
||||
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationModel.swift; sourceTree = "<group>"; };
|
||||
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertMainView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertExpandableView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooterModel.swift; sourceTree = "<group>"; };
|
||||
D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooter.swift; sourceTree = "<group>"; };
|
||||
D2D39579252FDBB300047B11 /* ModalSectionListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalSectionListTemplate.swift; sourceTree = "<group>"; };
|
||||
@ -1171,27 +1141,9 @@
|
||||
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderFooterView.swift; sourceTree = "<group>"; };
|
||||
D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertActionStyle+Codable.swift"; sourceTree = "<group>"; };
|
||||
D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIAlertControllerStyle+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2ED27E8254B0CE600A1C293 /* ActionPopupModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionPopupModel.swift; sourceTree = "<group>"; };
|
||||
D2ED27E9254B0CE600A1C293 /* ActionAlertModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionAlertModel.swift; sourceTree = "<group>"; };
|
||||
D2ED27EA254B0CE700A1C293 /* AlertModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertModel.swift; sourceTree = "<group>"; };
|
||||
D2ED27F2254B0E0200A1C293 /* MVMCoreAlertDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreAlertDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
D2ED27F3254B0E0200A1C293 /* MVMCoreAlertObject+Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MVMCoreAlertObject+Swift.swift"; sourceTree = "<group>"; };
|
||||
D2ED27F4254B0E0200A1C293 /* MVMCoreAlertOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreAlertOperation.m; sourceTree = "<group>"; };
|
||||
D2ED27F5254B0E0200A1C293 /* MVMCoreAlertObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreAlertObject.h; sourceTree = "<group>"; };
|
||||
D2ED27F6254B0E0200A1C293 /* MVMCoreAlertHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreAlertHandler.h; sourceTree = "<group>"; };
|
||||
D2ED27F7254B0E0200A1C293 /* MVMCoreAlertHandler+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MVMCoreAlertHandler+Extension.swift"; sourceTree = "<group>"; };
|
||||
D2ED27F8254B0E0200A1C293 /* MVMCoreAlertOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreAlertOperation.h; sourceTree = "<group>"; };
|
||||
D2ED27F9254B0E0200A1C293 /* MVMCoreAlertObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreAlertObject.m; sourceTree = "<group>"; };
|
||||
D2ED27FA254B0E0300A1C293 /* MVMCoreAlertHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreAlertHandler.m; sourceTree = "<group>"; };
|
||||
D2ED2805254B0EB700A1C293 /* MVMCoreTopAlertAnimationDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertAnimationDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
D2ED2806254B0EB700A1C293 /* MVMCoreTopAlertOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertOperation.h; sourceTree = "<group>"; };
|
||||
D2ED2807254B0EB700A1C293 /* MVMCoreTopAlertOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreTopAlertOperation.m; sourceTree = "<group>"; };
|
||||
D2ED2808254B0EB700A1C293 /* MVMCoreTopAlertViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertViewProtocol.h; sourceTree = "<group>"; };
|
||||
D2ED2809254B0EB700A1C293 /* MVMCoreTopAlertDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
D2ED280A254B0EB700A1C293 /* MVMCoreTopAlertObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertObject.h; sourceTree = "<group>"; };
|
||||
D2ED280B254B0EB800A1C293 /* MVMCoreTopAlertObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreTopAlertObject.m; sourceTree = "<group>"; };
|
||||
D2ED2814254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreGlobalTopAlertDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
D2ED2817254B112900A1C293 /* MVMCoreUIActionDelegateProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIActionDelegateProtocol.h; sourceTree = "<group>"; };
|
||||
D2ED27F3254B0E0200A1C293 /* AlertObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertObject.swift; sourceTree = "<group>"; };
|
||||
D2FA83D12513EA6900564112 /* NotificationXButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButton.swift; sourceTree = "<group>"; };
|
||||
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotification.swift; sourceTree = "<group>"; };
|
||||
D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationTopView.swift; sourceTree = "<group>"; };
|
||||
@ -1441,6 +1393,7 @@
|
||||
27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */,
|
||||
D23A900826125FFB007E14CE /* GetContactBehavior.swift */,
|
||||
D270E5662642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift */,
|
||||
22B678F829E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift */,
|
||||
);
|
||||
path = Behaviors;
|
||||
sourceTree = "<group>";
|
||||
@ -1522,8 +1475,6 @@
|
||||
94C01508242155FE005811A9 /* Actions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
94C0150924215643005811A9 /* ActionTopAlertModel.swift */,
|
||||
AF1C336A28859C73006B1001 /* ActionTopAlertHandler.swift */,
|
||||
94C0150B2421564A005811A9 /* ActionCollapseNotificationModel.swift */,
|
||||
AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */,
|
||||
D2C78CD124228BBD00B69FDE /* ActionOpenPanelModel.swift */,
|
||||
@ -1531,8 +1482,6 @@
|
||||
D2ED27E9254B0CE600A1C293 /* ActionAlertModel.swift */,
|
||||
D2ED27EA254B0CE700A1C293 /* AlertModel.swift */,
|
||||
AF1C336828859778006B1001 /* ActionAlertHandler.swift */,
|
||||
D2ED27E8254B0CE600A1C293 /* ActionPopupModel.swift */,
|
||||
AF1C33662883B712006B1001 /* ActionPopupHandler.swift */,
|
||||
C6687440259D92D400F32D13 /* ActionTopNotificationModel.swift */,
|
||||
AF1C33642883B5A4006B1001 /* ActionTopNotificationHandler.swift */,
|
||||
AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */,
|
||||
@ -1599,6 +1548,7 @@
|
||||
children = (
|
||||
AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */,
|
||||
AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */,
|
||||
22B678FC29E82B0300CF4196 /* ListNotificationAuthModel.swift */,
|
||||
AA7F47722541AD560015A2C1 /* ListStarRatingModel.swift */,
|
||||
AA7F47752541AD6A0015A2C1 /* ListStarRating.swift */,
|
||||
);
|
||||
@ -1633,6 +1583,7 @@
|
||||
EA985C862981AB0F00F2FF2E /* VDS-Tilelet+Codable.swift */,
|
||||
EA985C882981AB7100F2FF2E /* VDS-TextStyle.swift */,
|
||||
EA985C8A2983259900F2FF2E /* VDS-LabelAttributeModel.swift */,
|
||||
AF766D252A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -2043,7 +1994,7 @@
|
||||
D29DF11921E68467003B2FB9 /* Containers */,
|
||||
D22D1F582204D2590077CEC0 /* Legacy */,
|
||||
D29DF10F21E67A7D003B2FB9 /* BaseControllers */,
|
||||
D29DF11E21E6851E003B2FB9 /* TopAlert */,
|
||||
D29DF11E21E6851E003B2FB9 /* Notification */,
|
||||
D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */,
|
||||
D29DF0D021E404D4003B2FB9 /* Info.plist */,
|
||||
);
|
||||
@ -2166,31 +2117,14 @@
|
||||
path = Containers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D29DF11E21E6851E003B2FB9 /* TopAlert */ = {
|
||||
D29DF11E21E6851E003B2FB9 /* Notification */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2ED2814254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h */,
|
||||
D2ED2805254B0EB700A1C293 /* MVMCoreTopAlertAnimationDelegateProtocol.h */,
|
||||
D2ED2809254B0EB700A1C293 /* MVMCoreTopAlertDelegateProtocol.h */,
|
||||
D2ED280A254B0EB700A1C293 /* MVMCoreTopAlertObject.h */,
|
||||
D2ED280B254B0EB800A1C293 /* MVMCoreTopAlertObject.m */,
|
||||
D2ED2806254B0EB700A1C293 /* MVMCoreTopAlertOperation.h */,
|
||||
D2ED2807254B0EB700A1C293 /* MVMCoreTopAlertOperation.m */,
|
||||
D2ED2808254B0EB700A1C293 /* MVMCoreTopAlertViewProtocol.h */,
|
||||
D20C7008250BF99B0095B21C /* TopNotificationModel.swift */,
|
||||
D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */,
|
||||
D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */,
|
||||
D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */,
|
||||
D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */,
|
||||
D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */,
|
||||
D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */,
|
||||
D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */,
|
||||
D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */,
|
||||
D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */,
|
||||
D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */,
|
||||
D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */,
|
||||
AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */,
|
||||
D20C7008250BF99B0095B21C /* NotificationModel.swift */,
|
||||
D20C700A250BFDE40095B21C /* NotificationContainerView.swift */,
|
||||
);
|
||||
path = TopAlert;
|
||||
path = Notification;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D29DF13321E68604003B2FB9 /* Styles */ = {
|
||||
@ -2340,11 +2274,11 @@
|
||||
D29DF27821E7A533003B2FB9 /* MVMCoreUISession.m */,
|
||||
D29DF27321E79E81003B2FB9 /* MVMCoreUILoggingHandler.h */,
|
||||
D29DF27421E79E81003B2FB9 /* MVMCoreUILoggingHandler.m */,
|
||||
AFA4933E29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift */,
|
||||
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */,
|
||||
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */,
|
||||
D2092352244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift */,
|
||||
D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */,
|
||||
D2ED2817254B112900A1C293 /* MVMCoreUIActionDelegateProtocol.h */,
|
||||
AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */,
|
||||
D23A90672614B0B4007E14CE /* CoreUIModelMapping.swift */,
|
||||
);
|
||||
@ -2496,13 +2430,11 @@
|
||||
children = (
|
||||
D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */,
|
||||
D2FA83D12513EA6900564112 /* NotificationXButton.swift */,
|
||||
D2CAC7CC251104FE00C75681 /* NotificationModel.swift */,
|
||||
D23118B225124E18001C8440 /* Notification.swift */,
|
||||
D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */,
|
||||
D2CAC7CC251104FE00C75681 /* NotificationMoleculeModel.swift */,
|
||||
D23118B225124E18001C8440 /* NotificationMoleculeView.swift */,
|
||||
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */,
|
||||
D2FA83D32514F80C00564112 /* CollapsableNotification.swift */,
|
||||
D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */,
|
||||
D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */,
|
||||
);
|
||||
path = TopNotification;
|
||||
sourceTree = "<group>";
|
||||
@ -2538,15 +2470,11 @@
|
||||
D2ED27D8254B0C1F00A1C293 /* Alerts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2ED27F2254B0E0200A1C293 /* MVMCoreAlertDelegateProtocol.h */,
|
||||
D2ED27F6254B0E0200A1C293 /* MVMCoreAlertHandler.h */,
|
||||
D2ED27FA254B0E0300A1C293 /* MVMCoreAlertHandler.m */,
|
||||
D2ED27F7254B0E0200A1C293 /* MVMCoreAlertHandler+Extension.swift */,
|
||||
D2ED27F5254B0E0200A1C293 /* MVMCoreAlertObject.h */,
|
||||
D2ED27F9254B0E0200A1C293 /* MVMCoreAlertObject.m */,
|
||||
D2ED27F3254B0E0200A1C293 /* MVMCoreAlertObject+Swift.swift */,
|
||||
D2ED27F8254B0E0200A1C293 /* MVMCoreAlertOperation.h */,
|
||||
D2ED27F4254B0E0200A1C293 /* MVMCoreAlertOperation.m */,
|
||||
AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */,
|
||||
D2ED27F3254B0E0200A1C293 /* AlertObject.swift */,
|
||||
AF7E509729E477C0009DC2AD /* AlertController.swift */,
|
||||
AF7E509629E477C0009DC2AD /* AlertHandler.swift */,
|
||||
AFA4931F29E5CA73001A9663 /* AlertOperation.swift */,
|
||||
);
|
||||
path = Alerts;
|
||||
sourceTree = "<group>";
|
||||
@ -2582,7 +2510,6 @@
|
||||
D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */,
|
||||
D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */,
|
||||
D29DF2CE21E7C104003B2FB9 /* MFLoadingViewController.h in Headers */,
|
||||
D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */,
|
||||
D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */,
|
||||
D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */,
|
||||
D20492A424329A2800A5EED6 /* MVMCoreUIPagingProtocol.h in Headers */,
|
||||
@ -2591,29 +2518,14 @@
|
||||
D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */,
|
||||
D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */,
|
||||
01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */,
|
||||
D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */,
|
||||
D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */,
|
||||
D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */,
|
||||
D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */,
|
||||
D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */,
|
||||
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */,
|
||||
D2ED2811254B0EB800A1C293 /* MVMCoreTopAlertObject.h in Headers */,
|
||||
D2ED27FE254B0E0300A1C293 /* MVMCoreAlertObject.h in Headers */,
|
||||
D2ED280F254B0EB800A1C293 /* MVMCoreTopAlertViewProtocol.h in Headers */,
|
||||
D2ED280C254B0EB800A1C293 /* MVMCoreTopAlertAnimationDelegateProtocol.h in Headers */,
|
||||
D2ED280D254B0EB800A1C293 /* MVMCoreTopAlertOperation.h in Headers */,
|
||||
D2ED2801254B0E0300A1C293 /* MVMCoreAlertOperation.h in Headers */,
|
||||
D2ED2818254B115400A1C293 /* MVMCoreUIActionDelegateProtocol.h in Headers */,
|
||||
D2ED27FB254B0E0300A1C293 /* MVMCoreAlertDelegateProtocol.h in Headers */,
|
||||
D2ED2810254B0EB800A1C293 /* MVMCoreTopAlertDelegateProtocol.h in Headers */,
|
||||
D2ED27FF254B0E0300A1C293 /* MVMCoreAlertHandler.h in Headers */,
|
||||
D2ED2815254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h in Headers */,
|
||||
D29DF26F21E6AA0B003B2FB9 /* FLAnimatedImageView.h in Headers */,
|
||||
D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */,
|
||||
D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */,
|
||||
D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */,
|
||||
D29DF12921E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h in Headers */,
|
||||
D29DF12C21E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -2726,7 +2638,7 @@
|
||||
AAB9C10824346F4B00151545 /* RadioSwatches.swift in Sources */,
|
||||
94C2D9A923872E5E0006CF46 /* LabelAttributeImageModel.swift in Sources */,
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */,
|
||||
D2ED27FC254B0E0300A1C293 /* AlertObject.swift in Sources */,
|
||||
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
||||
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */,
|
||||
AAC23FAD24D92A0D009208DF /* ListThreeColumnSpeedTestModel.swift in Sources */,
|
||||
@ -2772,17 +2684,15 @@
|
||||
011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */,
|
||||
EA985C892981AB7100F2FF2E /* VDS-TextStyle.swift in Sources */,
|
||||
BB2BF0EA2452A9BB001D0FC2 /* ListDeviceComplexButtonSmall.swift in Sources */,
|
||||
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */,
|
||||
D20C700B250BFDE40095B21C /* NotificationContainerView.swift in Sources */,
|
||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */,
|
||||
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */,
|
||||
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */,
|
||||
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
|
||||
BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */,
|
||||
012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */,
|
||||
8D8067D12444472F00203BE8 /* ListRightVariablePriceChangeAllTextAndLinksModel.swift in Sources */,
|
||||
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */,
|
||||
D2ED2802254B0E0300A1C293 /* MVMCoreAlertObject.m in Sources */,
|
||||
D224798C231450C8003FCCF9 /* HeadlineBodyToggle.swift in Sources */,
|
||||
9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */,
|
||||
522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */,
|
||||
@ -2801,7 +2711,6 @@
|
||||
AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */,
|
||||
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
|
||||
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
|
||||
AF1C33672883B712006B1001 /* ActionPopupHandler.swift in Sources */,
|
||||
D23A900926125FFB007E14CE /* GetContactBehavior.swift in Sources */,
|
||||
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */,
|
||||
AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */,
|
||||
@ -2809,7 +2718,6 @@
|
||||
D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */,
|
||||
D28764AC245898A400CB882D /* ThreeLayerFillMiddleTemplateModel.swift in Sources */,
|
||||
BBBBC87D24374A4900B0F079 /* ListThreeColumnBillChangesDividerModel.swift in Sources */,
|
||||
D2ED2800254B0E0300A1C293 /* MVMCoreAlertHandler+Extension.swift in Sources */,
|
||||
D2ED27EE254B0CE700A1C293 /* ActionAlertModel.swift in Sources */,
|
||||
D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */,
|
||||
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
|
||||
@ -2820,11 +2728,9 @@
|
||||
0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */,
|
||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */,
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
||||
D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */,
|
||||
AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */,
|
||||
D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */,
|
||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */,
|
||||
D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */,
|
||||
AA07EA932510A451009A2AE3 /* Star.swift in Sources */,
|
||||
D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */,
|
||||
D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */,
|
||||
@ -2851,7 +2757,6 @@
|
||||
52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */,
|
||||
525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */,
|
||||
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
|
||||
D2ED280E254B0EB800A1C293 /* MVMCoreTopAlertOperation.m in Sources */,
|
||||
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */,
|
||||
D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */,
|
||||
AA37CBD3251907200027344C /* StarsModel.swift in Sources */,
|
||||
@ -2863,8 +2768,6 @@
|
||||
0A0FEC7425D42A5E00AF2548 /* BaseItemPickerEntryField.swift in Sources */,
|
||||
D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */,
|
||||
D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */,
|
||||
D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */,
|
||||
D2ED27ED254B0CE700A1C293 /* ActionPopupModel.swift in Sources */,
|
||||
94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */,
|
||||
943820842432382400B43AF3 /* WebView.swift in Sources */,
|
||||
0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */,
|
||||
@ -2878,6 +2781,7 @@
|
||||
8DDD6C1D244D90B8006A2232 /* ListThreeColumnDataUsage.swift in Sources */,
|
||||
0A849EFE246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift in Sources */,
|
||||
D28764FB245A33A500CB882D /* TwoLinkViewModel.swift in Sources */,
|
||||
AFA4932029E5CA73001A9663 /* AlertOperation.swift in Sources */,
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
|
||||
AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */,
|
||||
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
|
||||
@ -2899,6 +2803,7 @@
|
||||
D28A838323CCBD3F00DFE4FC /* WheelModel.swift in Sources */,
|
||||
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */,
|
||||
0A9D091D2433796500D2E6C0 /* BarsCarouselIndicatorModel.swift in Sources */,
|
||||
AFA4933F29E874F0001A9663 /* MVMCoreUILoggingDelegateProtocol.swift in Sources */,
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */,
|
||||
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */,
|
||||
AF1C33712885AE76006B1001 /* MVMCoreUIActionHandler.swift in Sources */,
|
||||
@ -2911,7 +2816,6 @@
|
||||
01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */,
|
||||
AA104ADA244734DB004D2810 /* HeadersH1LandingPageHeader.swift in Sources */,
|
||||
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
|
||||
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
|
||||
94F6516D2437954100631BF9 /* Tabs.swift in Sources */,
|
||||
5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */,
|
||||
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
|
||||
@ -2921,8 +2825,7 @@
|
||||
8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */,
|
||||
D2092357244FA1EF0044AD09 /* ThreeLayerModelBase.swift in Sources */,
|
||||
D2FD4A4925199BD9000C28A9 /* AccessibilityProtocol.swift in Sources */,
|
||||
D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */,
|
||||
D2ED2803254B0E0300A1C293 /* MVMCoreAlertHandler.m in Sources */,
|
||||
D2CAC7CD251104FE00C75681 /* NotificationMoleculeModel.swift in Sources */,
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */,
|
||||
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */,
|
||||
D20923592450ECE00044AD09 /* TableView.swift in Sources */,
|
||||
@ -2939,6 +2842,7 @@
|
||||
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
|
||||
444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */,
|
||||
D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */,
|
||||
AF766D262A3CD4C600749099 /* UIAccessibilityTraits+Codable.swift in Sources */,
|
||||
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
|
||||
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
|
||||
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */,
|
||||
@ -2977,6 +2881,7 @@
|
||||
AA7F47732541AD560015A2C1 /* ListStarRatingModel.swift in Sources */,
|
||||
AA7F47762541AD6A0015A2C1 /* ListStarRating.swift in Sources */,
|
||||
0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */,
|
||||
AF7E509829E477C1009DC2AD /* AlertHandler.swift in Sources */,
|
||||
D2ED27EB254B0CE700A1C293 /* UIAlertActionStyle+Codable.swift in Sources */,
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
|
||||
@ -3006,12 +2911,12 @@
|
||||
D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */,
|
||||
C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */,
|
||||
32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */,
|
||||
AF1C336B28859C73006B1001 /* ActionTopAlertHandler.swift in Sources */,
|
||||
011D958524042432000E3791 /* RulesProtocol.swift in Sources */,
|
||||
4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */,
|
||||
D23118B325124E18001C8440 /* Notification.swift in Sources */,
|
||||
D23118B325124E18001C8440 /* NotificationMoleculeView.swift in Sources */,
|
||||
AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */,
|
||||
AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */,
|
||||
AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */,
|
||||
D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */,
|
||||
D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */,
|
||||
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */,
|
||||
@ -3022,7 +2927,6 @@
|
||||
3265B30224BCA737000D154B /* HeadersH1NoButtonsBodyTextModel.swift in Sources */,
|
||||
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
|
||||
D264FAAC2441009400D98315 /* RadioBoxCollectionViewCell.swift in Sources */,
|
||||
D2ED27FD254B0E0300A1C293 /* MVMCoreAlertOperation.m in Sources */,
|
||||
BB2C969224330F73006FF80C /* ListRightVariableTextLinkAllTextAndLinks.swift in Sources */,
|
||||
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */,
|
||||
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */,
|
||||
@ -3048,15 +2952,17 @@
|
||||
324FB6AC24936717002552C7 /* ListLeftVariableNumberedListBodyText.swift in Sources */,
|
||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */,
|
||||
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */,
|
||||
22B678FD29E82B0300CF4196 /* ListNotificationAuthModel.swift in Sources */,
|
||||
AA7F32AB246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift in Sources */,
|
||||
8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */,
|
||||
AF60A7F82892D34D00919EEB /* ActionDismissNotificationHandler.swift in Sources */,
|
||||
D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */,
|
||||
AA104AC924472DC7004D2810 /* HeadersH1ButtonModel.swift in Sources */,
|
||||
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */,
|
||||
D20C7009250BF99B0095B21C /* TopNotificationModel.swift in Sources */,
|
||||
D20C7009250BF99B0095B21C /* NotificationModel.swift in Sources */,
|
||||
D29C558A25C05C7D0082E7D6 /* BGVideoImageMoleculeModel.swift in Sources */,
|
||||
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */,
|
||||
AFA4932229E5EF2E001A9663 /* NotificationHandler.swift in Sources */,
|
||||
BB2FB3BD247E7EF200DF73CD /* Tags.swift in Sources */,
|
||||
AA104ADC244734EA004D2810 /* HeadersH1LandingPageHeaderModel.swift in Sources */,
|
||||
BBAA4F03243D8E3B005AAD5F /* RadioBoxes.swift in Sources */,
|
||||
@ -3078,13 +2984,13 @@
|
||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */,
|
||||
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */,
|
||||
0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */,
|
||||
94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */,
|
||||
BB3BC12F2550094500297977 /* ListLeftVariableIconWithRightCaretAllTextLinks.swift in Sources */,
|
||||
012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */,
|
||||
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
|
||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
|
||||
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
|
||||
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */,
|
||||
AF7E509929E477C1009DC2AD /* AlertController.swift in Sources */,
|
||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
|
||||
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
|
||||
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */,
|
||||
@ -3116,12 +3022,12 @@
|
||||
AA45AA0D24BF0276007A6EA7 /* LockUpsPlanNames.swift in Sources */,
|
||||
8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */,
|
||||
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */,
|
||||
D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */,
|
||||
0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */,
|
||||
0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */,
|
||||
01F2C20427C81F9700DC3D36 /* SubNavInteractor.swift.swift in Sources */,
|
||||
D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */,
|
||||
0A51F3E32475CB73002E08B6 /* LoadingSpinner.swift in Sources */,
|
||||
22B678F929E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift in Sources */,
|
||||
BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */,
|
||||
012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */,
|
||||
B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */,
|
||||
@ -3176,7 +3082,6 @@
|
||||
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */,
|
||||
D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */,
|
||||
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
|
||||
D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */,
|
||||
0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */,
|
||||
EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */,
|
||||
C003506123AA94CD00B6AC29 /* Button.swift in Sources */,
|
||||
@ -3191,7 +3096,6 @@
|
||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */,
|
||||
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
|
||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */,
|
||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */,
|
||||
|
||||
38
MVMCoreUI/Alerts/AlertController.swift
Normal file
38
MVMCoreUI/Alerts/AlertController.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// AlertController.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 3/24/23.
|
||||
// Copyright © 2023 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
public class AlertController: UIAlertController {
|
||||
@objc dynamic public var visible = false
|
||||
private let visibleKey = "isVisible"
|
||||
|
||||
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
return MVMCoreGetterUtility.isOnIPad() ? .all : .portrait
|
||||
}
|
||||
|
||||
public override var description: String {
|
||||
return "\(super.description)|title=\(title ?? "")|message=\(message ?? "")"
|
||||
}
|
||||
|
||||
public override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
willChangeValue(forKey: visibleKey)
|
||||
visible = true
|
||||
didChangeValue(forKey: visibleKey)
|
||||
}
|
||||
|
||||
public override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
willChangeValue(forKey: visibleKey)
|
||||
visible = false
|
||||
didChangeValue(forKey: visibleKey)
|
||||
}
|
||||
}
|
||||
|
||||
19
MVMCoreUI/Alerts/AlertDelegateProtocol.swift
Normal file
19
MVMCoreUI/Alerts/AlertDelegateProtocol.swift
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// AlertDelegateProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/17/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
public protocol AlertDelegateProtocol {
|
||||
// All are performed on the main thread.
|
||||
@MainActor func alertShown(_ alertController: UIAlertController)
|
||||
@MainActor func alertCancelled(_ alertController: UIAlertController)
|
||||
@MainActor func alertDismissed(_ alertController: UIAlertController)
|
||||
@MainActor func alertPaused(_ alertController: UIAlertController)
|
||||
@MainActor func alertUnpaused(_ alertController: UIAlertController)
|
||||
}
|
||||
96
MVMCoreUI/Alerts/AlertHandler.swift
Normal file
96
MVMCoreUI/Alerts/AlertHandler.swift
Normal file
@ -0,0 +1,96 @@
|
||||
//
|
||||
// AlertHandler.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 4/10/23.
|
||||
// Copyright © 2023 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import MVMCore
|
||||
|
||||
public class AlertHandler {
|
||||
|
||||
/// Returns the handler stored in the CoreUIObject
|
||||
public static func shared() -> Self {
|
||||
return MVMCoreActionUtility.fatalClassCheck(object: CoreUIObject.sharedInstance()?.alertHandler)
|
||||
}
|
||||
|
||||
/// The operation queue of alert operations.
|
||||
private var queue = {
|
||||
let queue = OperationQueue()
|
||||
queue.maxConcurrentOperationCount = 1
|
||||
return queue
|
||||
}()
|
||||
|
||||
public init() {}
|
||||
|
||||
/// Returns if an alert is currently showing in the hierarchy, even if it is not the top presented view.
|
||||
public func isAlertShowing() -> Bool {
|
||||
return queue.operations.contains(where: { operation in
|
||||
return !operation.isCancelled &&
|
||||
!operation.isFinished &&
|
||||
operation.isExecuting
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns if a greedy alert is currently showing in the hierarchy, even if it is not the top presented view.
|
||||
public func isGreedyAlertShowing() -> Bool {
|
||||
return queue.operations.contains(where: { operation in
|
||||
return !operation.isCancelled &&
|
||||
!operation.isFinished &&
|
||||
operation.isExecuting &&
|
||||
(operation as? AlertOperation)?.alertObject.isGreedy ?? false
|
||||
})
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public func createAlertController(with alertModel: AlertModelProtocol) -> AlertController {
|
||||
// ActionSheets are not supported on iPad interfaces without a source rect (i.e. a source element) which isn't currently supported for our generic handling.
|
||||
// TODO: Find a way to support this.
|
||||
var alertStyle = alertModel.preferredStyle
|
||||
if alertStyle == .actionSheet, UIDevice.current.userInterfaceIdiom != .phone {
|
||||
alertStyle = .alert
|
||||
}
|
||||
|
||||
// Create the alert. Adds the actions one by one.
|
||||
let alertController = AlertController(title: alertModel.title, message: alertModel.message, preferredStyle: alertStyle)
|
||||
for action in alertModel.actions {
|
||||
alertController.addAction(action)
|
||||
}
|
||||
if let index = alertModel.preferredActionIndex {
|
||||
alertController.preferredAction = alertModel.actions[index]
|
||||
}
|
||||
return alertController
|
||||
}
|
||||
|
||||
/// Shows an alert using the alert object.
|
||||
@MainActor
|
||||
public func queueAlertToShow(with alertObject: AlertObject) -> UIAlertController {
|
||||
|
||||
// It's a greedy alert! Clear all alerts that are queued up and the one that is showing
|
||||
if alertObject.isGreedy {
|
||||
removeAllAlertViews()
|
||||
}
|
||||
|
||||
let alertController = createAlertController(with: alertObject.alertModel)
|
||||
let alertOperation = AlertOperation(with: alertController, alertObject: alertObject)
|
||||
queue.addOperation(alertOperation)
|
||||
return alertController
|
||||
}
|
||||
|
||||
/** Iterates through all scheduled alerts and cancels any that match the provided predicate.
|
||||
* @param predicate The predicate block to decide whether to cancel an alert.
|
||||
*/
|
||||
public func cancelAlert(using predicate: ((AlertObject) -> Bool)) {
|
||||
for case let operation as AlertOperation in queue.operations {
|
||||
if predicate(operation.alertObject) {
|
||||
operation.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Cancels all current alerts
|
||||
public func removeAllAlertViews() {
|
||||
queue.cancelAllOperations()
|
||||
}
|
||||
}
|
||||
35
MVMCoreUI/Alerts/AlertObject.swift
Normal file
35
MVMCoreUI/Alerts/AlertObject.swift
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// AlertObject.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 7/10/20.
|
||||
// Copyright © 2020 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import MVMCore
|
||||
|
||||
public protocol AlertModelProtocol {
|
||||
var title: String? { get }
|
||||
var message: String? { get }
|
||||
var actions: [UIAlertAction] { get }
|
||||
var preferredActionIndex: Int? { get }
|
||||
var preferredStyle: UIAlertController.Style { get }
|
||||
}
|
||||
|
||||
/// An object with properties for managing the alert.
|
||||
public struct AlertObject {
|
||||
|
||||
/// Greedy alerts dismiss any other alerts and do not allow any other alerts to show until finished.
|
||||
public var isGreedy = false
|
||||
|
||||
/// The alert model for the alert to show.
|
||||
public var alertModel: AlertModelProtocol
|
||||
|
||||
public weak var alertDelegate: AlertDelegateProtocol?
|
||||
|
||||
public init(alertModel: AlertModelProtocol, isGreedy: Bool = false, alertDelegate: AlertDelegateProtocol? = nil) {
|
||||
self.alertModel = alertModel
|
||||
self.isGreedy = isGreedy
|
||||
self.alertDelegate = alertDelegate
|
||||
}
|
||||
}
|
||||
138
MVMCoreUI/Alerts/AlertOperation.swift
Normal file
138
MVMCoreUI/Alerts/AlertOperation.swift
Normal file
@ -0,0 +1,138 @@
|
||||
//
|
||||
// AlertOperation.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 4/11/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import MVMCore
|
||||
import Dispatch
|
||||
import Combine
|
||||
|
||||
public class AlertOperation: MVMCoreOperation {
|
||||
|
||||
private actor Properties {
|
||||
private var isDisplayed: Bool = false
|
||||
|
||||
func set(displayed: Bool) {
|
||||
isDisplayed = displayed
|
||||
}
|
||||
|
||||
func getIsDisplayed() -> Bool {
|
||||
return isDisplayed
|
||||
}
|
||||
}
|
||||
private var properties = Properties()
|
||||
|
||||
public let alertController: AlertController
|
||||
|
||||
public let alertObject: AlertObject
|
||||
|
||||
/// For tracking isVisible changes of the alert controller.
|
||||
private var cancellable: Cancellable?
|
||||
|
||||
/// Blocks the navigation queue to ensure no other navigation happens while an alert is displayed.
|
||||
private var blockingOperation: MVMCoreOperation?
|
||||
|
||||
public init(with alert: AlertController, alertObject: AlertObject) {
|
||||
self.alertController = alert
|
||||
self.alertObject = alertObject
|
||||
super.init()
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopObservingAlertView()
|
||||
}
|
||||
|
||||
public override func main() {
|
||||
guard !checkAndHandleForCancellation() else { return }
|
||||
|
||||
// Observe for when it is removed.
|
||||
observeForCurrentAlertViewDismissal()
|
||||
|
||||
Task(priority: .high) {
|
||||
guard let viewControllerToPresentOn = await NavigationHandler.shared().getViewControllerToPresentOn() else {
|
||||
markAsFinished()
|
||||
return
|
||||
}
|
||||
|
||||
// Presents the alert.
|
||||
let presentationOperation = await NavigationOperation(with: .present(viewController: alertController, onController: viewControllerToPresentOn), tryToReplace: false)
|
||||
|
||||
let blockingOperation = MVMCoreOperation()
|
||||
blockingOperation.addDependency(presentationOperation)
|
||||
self.blockingOperation = blockingOperation
|
||||
|
||||
// Block other navigation until this alert is removed.
|
||||
NavigationHandler.shared().navigationQueue.addOperation(blockingOperation)
|
||||
|
||||
await NavigationHandler.shared().navigate(with: presentationOperation)
|
||||
|
||||
// We finished but it was not displayed yet. It's possible that it was cancelled. Finish this task
|
||||
if await !self.properties.getIsDisplayed() {
|
||||
self.markAsFinished()
|
||||
} else {
|
||||
(CoreUIObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject)
|
||||
if self.isCancelled {
|
||||
await self.dismissAlertView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override func cancel() {
|
||||
super.cancel()
|
||||
Task { @MainActor in
|
||||
self.alertObject.alertDelegate?.alertCancelled(self.alertController)
|
||||
await self.dismissAlertView()
|
||||
}
|
||||
}
|
||||
|
||||
private func dismissAlertView() async {
|
||||
guard await properties.getIsDisplayed() else { return }
|
||||
await withCheckedContinuation { continuation in
|
||||
Task {
|
||||
let dismissOperation = await NavigationOperation(with: .dismiss(viewController: alertController))
|
||||
dismissOperation.queuePriority = .veryHigh
|
||||
let task = Task(priority: .high) { await NavigationHandler.shared().navigate(with: dismissOperation) }
|
||||
blockingOperation?.markAsFinished()
|
||||
_ = await task.result
|
||||
continuation.resume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override func markAsFinished() {
|
||||
blockingOperation?.markAsFinished()
|
||||
super.markAsFinished()
|
||||
}
|
||||
|
||||
// MARK: Observer Functions
|
||||
|
||||
private func observeForCurrentAlertViewDismissal() {
|
||||
stopObservingAlertView()
|
||||
cancellable = alertController.publisher(for: \AlertController.visible).sink() { [weak self] visible in
|
||||
guard let self = self else { return }
|
||||
Task {
|
||||
guard await self.properties.getIsDisplayed() != visible else { return }
|
||||
await self.properties.set(displayed: visible)
|
||||
Task { @MainActor in
|
||||
if visible {
|
||||
self.alertObject.alertDelegate?.alertShown(self.alertController)
|
||||
} else {
|
||||
self.alertObject.alertDelegate?.alertDismissed(self.alertController)
|
||||
|
||||
// Is visible was set to NO, meaning that the alertview is no longer visible.
|
||||
self.stopObservingAlertView()
|
||||
self.markAsFinished()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func stopObservingAlertView() {
|
||||
cancellable?.cancel()
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertDelegateProtocol.h
|
||||
// mobilefirst
|
||||
//
|
||||
// Created by Pfeil, Scott Robert on 8/8/17.
|
||||
// Copyright © 2017 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// Called for popup style alerts.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@class MVMCoreAlertObject;
|
||||
@class MVMCoreLoadObject;
|
||||
@class MVMCoreErrorObject;
|
||||
|
||||
@protocol MVMCoreAlertDelegateProtocol
|
||||
|
||||
@optional
|
||||
|
||||
// helps tracking alert state
|
||||
- (nullable NSDictionary *)additionalAlertDataToTrackForAlertWithObject:(nullable MVMCoreAlertObject *)alertObject;
|
||||
|
||||
// All are performed on the main thread.
|
||||
- (void)alertShown:(nonnull UIAlertController *)alertController;
|
||||
- (void)alertCancelled:(nonnull UIAlertController *)alertController;
|
||||
- (void)alertDismissed:(nonnull UIAlertController *)alertController;
|
||||
- (void)alertPaused:(nonnull UIAlertController *)alertController;
|
||||
- (void)alertUnpaused:(nonnull UIAlertController *)alertController;
|
||||
|
||||
/** Get the alert object whose data will be presented. Overwrite this to alter how you want the alert to show.
|
||||
* @param loadObject The load object.
|
||||
* @param errorObject An error object if there was an error.
|
||||
* @return Returns the alert object.
|
||||
* Details: Gets the alert that will display to the screen. Easier to subclass here to avoid subclassing the displaying logic. */
|
||||
- (nullable MVMCoreAlertObject *)alertObjectToShow:(nonnull MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)errorObject;
|
||||
|
||||
@end
|
||||
@ -1,69 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertHandler+Extension.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Scott Pfeil on 9/15/20.
|
||||
// Copyright © 2020 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension MVMCoreAlertHandler {
|
||||
|
||||
/// Re-evaluates the queue operations
|
||||
@objc func reevaluteQueue() {
|
||||
var highestReadyOperation: MVMCoreTopAlertOperation?
|
||||
var executingOperation: MVMCoreTopAlertOperation?
|
||||
for case let operation as MVMCoreTopAlertOperation in topAlertQueue.operations {
|
||||
guard !operation.isCancelled,
|
||||
!operation.isFinished else { continue }
|
||||
if operation.isReady,
|
||||
highestReadyOperation == nil || operation.queuePriority.rawValue > highestReadyOperation!.queuePriority.rawValue {
|
||||
highestReadyOperation = operation
|
||||
}
|
||||
if operation.isExecuting {
|
||||
executingOperation = operation
|
||||
}
|
||||
}
|
||||
guard let currentOperation = executingOperation else { return }
|
||||
|
||||
// Cancel the executing operation if it is no longer ready to run. Re-add for later if it is persistent.
|
||||
guard currentOperation.isReady else {
|
||||
currentOperation.reAddAfterCancel = currentOperation.topAlertObject.persistent
|
||||
currentOperation.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
// If the highest priority operation is not executing, and the executing operation is persistent, cancel it.
|
||||
if let newOperation = highestReadyOperation,
|
||||
currentOperation != newOperation,
|
||||
currentOperation.topAlertObject.persistent {
|
||||
currentOperation.reAddAfterCancel = true
|
||||
currentOperation.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers to know when pages change.
|
||||
@objc func registerForPageChanges() {
|
||||
MVMCoreNavigationHandler.shared()?.addDelegate(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension MVMCoreAlertHandler: MVMCorePresentationDelegateProtocol {
|
||||
// Update displayable for each top alert operation when page type changes, in top queue priority order.
|
||||
public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) {
|
||||
guard topAlertQueue.operations.count > 0 else { return }
|
||||
let viewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController)
|
||||
guard viewController == MVMCoreUISplitViewController.main()?.getCurrentViewController() else { return }
|
||||
let pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType
|
||||
topAlertQueue.operations.compactMap {
|
||||
$0 as? MVMCoreTopAlertOperation
|
||||
}.sorted {
|
||||
$0.queuePriority.rawValue > $1.queuePriority.rawValue
|
||||
}.forEach {
|
||||
$0.updateDisplayable(byPageType: pageType)
|
||||
}
|
||||
reevaluteQueue()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertHandler.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 3/10/14.
|
||||
// Copyright (c) 2014 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// Keeps track of alerts and handles them. Should always use this to present alerts in mf.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <MVMCoreUI/MVMCoreTopAlertObject.h>
|
||||
#import <MVMCoreUI/MVMCoreAlertDelegateProtocol.h>
|
||||
|
||||
@class MVMCoreAlertObject;
|
||||
@class MVMCoreTopAlertOperation;
|
||||
|
||||
@interface MVMCoreAlertHandler : NSObject
|
||||
|
||||
// An operation queue for displaying popup alerts.
|
||||
@property (nonnull, strong, nonatomic) NSOperationQueue *popupAlertQueue;
|
||||
|
||||
// An operation queue for top alerts
|
||||
@property (nonnull, strong, nonatomic) NSOperationQueue *topAlertQueue;
|
||||
|
||||
/// Returns the shared instance of this singleton
|
||||
+ (nullable instancetype)sharedAlertHandler;
|
||||
|
||||
#pragma mark - Popup Alert Functions
|
||||
|
||||
/// Returns if any alert is currently showing (even if supressed).
|
||||
- (BOOL)alertCurrentlyShowing;
|
||||
|
||||
/// Returns if a greedy alert is currently showing (even if supressed).
|
||||
- (BOOL)greedyAlertShowing;
|
||||
|
||||
/** Shows the popup with the passed in parameter.
|
||||
* @param title The title of the alert.
|
||||
* @param message The message of the alert.
|
||||
* @param actions An array of actions for the alert.
|
||||
* @param isGreedy Sets up a greedy popup. In other words, any popups currently shown or queued are dismissed.
|
||||
* @return Returns the UIAlertController.
|
||||
*/
|
||||
- (nonnull UIAlertController *)showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nullable NSArray<UIAlertAction *>*)actions isGreedy:(BOOL)isGreedy;
|
||||
|
||||
/** Shows the alert.
|
||||
* @param title The title of the alert.
|
||||
* @param message The message of the alert.
|
||||
* @param actions An array of actions for the alert.
|
||||
* @param alertStyle Popup or action sheet
|
||||
* @param isGreedy Sets up a greedy alert. In other words, any alerts currently shown or queued are dismissed.
|
||||
* @param alertDelegate The delegate to be notified.
|
||||
* @return Returns the UIAlertController.
|
||||
*/
|
||||
- (nonnull UIAlertController *)showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nullable NSArray<UIAlertAction *>*)actions alertStyle:(UIAlertControllerStyle)alertStyle isGreedy:(BOOL)isGreedy alertDelegate:(nullable NSObject <MVMCoreAlertDelegateProtocol>*)alertDelegate;
|
||||
|
||||
/** Shows the popup with the passed in alert object. This is a convenience method that automatically handles using the proper alert type based on what's available.
|
||||
* @param alertObject The alert object to use for the alert.
|
||||
* @return Returns UIAlertController.
|
||||
*/
|
||||
- (nonnull UIAlertController *)showAlertWithAlertObject:(nonnull MVMCoreAlertObject *)alertObject;
|
||||
|
||||
/** Cancels and removes an alert operation for the given alertObject.
|
||||
* @param alertObject The alertObject scheduled to be shown.
|
||||
*/
|
||||
- (void)removeAlertViewForObject:(nonnull MVMCoreAlertObject *)alertObject;
|
||||
|
||||
/** Iterates through all scheduled alerts and cancels any that match the provided predicate.
|
||||
* @param predicate The predicate block to decide whether to cancel an alert.
|
||||
*/
|
||||
- (void)removeAlertViewUsingPredicate:(BOOL(^_Nonnull)(MVMCoreAlertObject * _Nonnull obj))predicate;
|
||||
|
||||
/// Removes all alerts.
|
||||
- (void)removeAllAlertViews;
|
||||
|
||||
#pragma mark - Supression Functions
|
||||
|
||||
/// Returns true if alerts are supressed.
|
||||
- (BOOL)mfAlertsSupressed;
|
||||
|
||||
/// Supresses the alerts (Used by other "apps" in our app).
|
||||
- (void)supressMFAlerts;
|
||||
|
||||
/// Unsupresses the alerts (Used by other "apps" in our app).
|
||||
- (void)unSupressMFAlerts;
|
||||
|
||||
#pragma mark - Top Alert Functions
|
||||
|
||||
/// Show based on the object. Will be used by the architecture. Creates an operation and calls addTopAlertOperation.
|
||||
- (void)showTopAlertWithObject:(nullable MVMCoreTopAlertObject *)topAlertObject;
|
||||
|
||||
/// Adds the top alert operation to the queue.
|
||||
- (void)addTopAlertOperation:(nonnull MVMCoreTopAlertOperation *)topAlertOperation;
|
||||
|
||||
/// Convenience functions
|
||||
- (void)showTopAlertErrorWithMessage:(nullable NSString *)message;
|
||||
- (void)showTopAlertConfirmationWithMessage:(nullable NSString *)message;
|
||||
- (void)showTopAlertWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData;
|
||||
- (void)showTopAlertWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler;
|
||||
|
||||
/// Hides the current alert view.
|
||||
- (void)hideTopAlertView;
|
||||
|
||||
/// Hides a persistent alert based on the type string.
|
||||
- (void)hidePersistentTopAlertViewOfType:(nullable NSString *)type;
|
||||
|
||||
/// Hides a alert based on the type string.
|
||||
- (void)hideTopAlertViewOfType:(nullable NSString *)type;
|
||||
|
||||
/// Removes a scheduled top alert given its top alert object.
|
||||
- (void)removeTopAlertForObject:(nonnull MVMCoreTopAlertObject *)topAlertObject;
|
||||
|
||||
/// Removes all top alerts.
|
||||
- (void)removeAllTopAlerts;
|
||||
|
||||
/// Returns YES if the persistent type is already registered in the alert queue.
|
||||
- (BOOL)hasPersistentTopAlertOfType:(nullable NSString *)type;
|
||||
|
||||
@end
|
||||
@ -1,274 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertHandler.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 3/10/14.
|
||||
// Copyright (c) 2014 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreAlertHandler.h"
|
||||
#import "MVMCoreAlertObject.h"
|
||||
@import MVMCore.MVMCoreAlertController;
|
||||
#import "MVMCoreAlertOperation.h"
|
||||
#import "MVMCoreTopAlertOperation.h"
|
||||
@import MVMCore.MVMCoreJSONConstants;
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
@import MVMCore.NSArray_MFConvenience;
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
|
||||
@interface MVMCoreAlertHandler ()
|
||||
|
||||
// Flag that keeps track of if the alerts are supressed or not.
|
||||
@property (assign, nonatomic) BOOL mfAlertsSupressed;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCoreAlertHandler
|
||||
|
||||
+ (instancetype)sharedAlertHandler {
|
||||
static dispatch_once_t once;
|
||||
static id sharedInstance;
|
||||
|
||||
dispatch_once(&once, ^{
|
||||
sharedInstance = [[self alloc] init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (nullable instancetype)init {
|
||||
if (self = [super init]) {
|
||||
self.popupAlertQueue = [[NSOperationQueue alloc] init];
|
||||
self.popupAlertQueue.maxConcurrentOperationCount = 1;
|
||||
self.topAlertQueue = [[NSOperationQueue alloc] init];
|
||||
self.topAlertQueue.maxConcurrentOperationCount = 1;
|
||||
[self registerForPageChanges];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Popup Alert Functions
|
||||
|
||||
- (BOOL)alertCurrentlyShowing {
|
||||
return (self.popupAlertQueue.operationCount > 0);
|
||||
}
|
||||
|
||||
- (BOOL)greedyAlertShowing {
|
||||
if ([self alertCurrentlyShowing]) {
|
||||
NSInteger index = [self.popupAlertQueue.operations indexOfObjectPassingTest:^BOOL(__kindof MVMCoreAlertOperation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (obj.isExecuting && obj.isGreedy && stop) {
|
||||
*stop = YES;
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}];
|
||||
return (index != NSNotFound);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (nonnull UIAlertController *)showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nullable NSArray<UIAlertAction *>*)actions isGreedy:(BOOL)isGreedy {
|
||||
return [self showAlertWithTitle:title message:message actions:actions isGreedy:isGreedy alertDelegate:nil];
|
||||
}
|
||||
|
||||
- (nonnull UIAlertController *)showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nullable NSArray<UIAlertAction *>*)actions isGreedy:(BOOL)isGreedy alertDelegate:(nullable NSObject <MVMCoreAlertDelegateProtocol>*)alertDelegate {
|
||||
return [self showAlertWithTitle:title message:message actions:actions alertStyle:UIAlertControllerStyleAlert isGreedy:isGreedy alertDelegate:alertDelegate];
|
||||
}
|
||||
|
||||
- (nonnull UIAlertController *)showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nullable NSArray<UIAlertAction *>*)actions alertStyle:(UIAlertControllerStyle)alertStyle isGreedy:(BOOL)isGreedy alertDelegate:(nullable NSObject <MVMCoreAlertDelegateProtocol>*)alertDelegate {
|
||||
|
||||
// It's a greedy alert! Clear all alerts that are queued up and the one that is showing
|
||||
if (isGreedy) {
|
||||
[self removeAllAlertViews];
|
||||
}
|
||||
|
||||
if (alertStyle == UIAlertControllerStyleActionSheet && UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) {
|
||||
// ActionSheets are not supported on iPad interfaces without a source rect (i.e. a source element) which isn't currently supported for our generic handling.
|
||||
alertStyle = UIAlertControllerStyleAlert;
|
||||
}
|
||||
|
||||
// Create the alert. Adds the actions one by one.
|
||||
MVMCoreAlertController *alertController = [MVMCoreAlertController alertControllerWithTitle:(title ?: @"") message:message preferredStyle:alertStyle];
|
||||
for (NSUInteger i = 0; i < [actions count]; i++) {
|
||||
UIAlertAction *action = [actions objectAtIndex:i ofType:[UIAlertAction class]];
|
||||
if (action) {
|
||||
[alertController addAction:action];
|
||||
}
|
||||
}
|
||||
|
||||
MVMCoreAlertOperation *alertOperation = [[MVMCoreAlertOperation alloc] initWithAlert:alertController isGreedy:isGreedy alertDelegate:alertDelegate];
|
||||
[self.popupAlertQueue addOperation:alertOperation];
|
||||
return alertController;
|
||||
}
|
||||
|
||||
- (nonnull UIAlertController *)showAlertWithAlertObject:(nonnull MVMCoreAlertObject *)alertObject {
|
||||
MVMCoreAlertController *controller = (MVMCoreAlertController *)[self showAlertWithTitle:alertObject.title message:alertObject.message actions:alertObject.actions alertStyle:alertObject.alertStyle isGreedy:alertObject.isGreedy alertDelegate:alertObject.alertDelegate];
|
||||
controller.alertObject = alertObject;
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (void)removeAlertViewForObject:(MVMCoreAlertObject *)alertObject {
|
||||
for (MVMCoreAlertOperation *operation in self.popupAlertQueue.operations) {
|
||||
if ([operation.currentAlertView isKindOfClass:[MVMCoreAlertController class]] && [(MVMCoreAlertController *)operation.currentAlertView alertObject] == alertObject) {
|
||||
[operation cancel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeAlertViewUsingPredicate:(BOOL(^)(MVMCoreAlertObject *obj))predicate {
|
||||
for (MVMCoreAlertOperation *operation in self.popupAlertQueue.operations) {
|
||||
if ([operation.currentAlertView isKindOfClass:[MVMCoreAlertController class]]) {
|
||||
MVMCoreAlertObject *alertObject = [(MVMCoreAlertController *)operation.currentAlertView alertObject];
|
||||
if (alertObject && predicate(alertObject)) {
|
||||
[operation cancel];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeAllAlertViews {
|
||||
[self.popupAlertQueue cancelAllOperations];
|
||||
}
|
||||
|
||||
#pragma mark - Supression Functions
|
||||
|
||||
- (BOOL)mfAlertsSupressed {
|
||||
return _mfAlertsSupressed;
|
||||
}
|
||||
|
||||
- (void)supressMFAlerts {
|
||||
if (!self.mfAlertsSupressed) {
|
||||
self.mfAlertsSupressed = YES;
|
||||
for (MVMCoreAlertOperation *operation in self.popupAlertQueue.operations) {
|
||||
[operation pause];
|
||||
}
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
[operation pause];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unSupressMFAlerts {
|
||||
if (self.mfAlertsSupressed) {
|
||||
self.mfAlertsSupressed = NO;
|
||||
for (MVMCoreAlertOperation *operation in self.popupAlertQueue.operations) {
|
||||
[operation unpause];
|
||||
}
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
[operation unpause];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Top Alert Functions
|
||||
|
||||
- (void)addTopAlertOperation:(nonnull MVMCoreTopAlertOperation *)topAlertOperation {
|
||||
__block MVMCoreTopAlertOperation *alertOperation = topAlertOperation;
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[alertOperation setCompletionBlock:^{
|
||||
|
||||
// If the alert was cancelled to show another with higher priority, re-add to the operation when cancelled to the queue.
|
||||
if (alertOperation.reAddAfterCancel) {
|
||||
MVMCoreTopAlertOperation *newOperation = [alertOperation copy];
|
||||
newOperation.reAddAfterCancel = NO;
|
||||
[weakSelf addTopAlertOperation:newOperation];
|
||||
}
|
||||
alertOperation = nil;
|
||||
}];
|
||||
|
||||
NSString *currentPageType = ((UIViewController<MVMCoreViewControllerProtocol> *)[[MVMCoreUISplitViewController mainSplitViewController] getCurrentDetailViewController]).pageType;
|
||||
[alertOperation updateDisplayableByPageType:currentPageType];
|
||||
|
||||
[self.topAlertQueue addOperation:alertOperation];
|
||||
[self reevaluteQueue];
|
||||
}
|
||||
|
||||
- (void)showTopAlertWithObject:(nullable MVMCoreTopAlertObject *)topAlertObject {
|
||||
MVMCoreTopAlertOperation *alertOperation = [[MVMCoreTopAlertOperation alloc] initWithTopAlertObject:topAlertObject];
|
||||
[self addTopAlertOperation:alertOperation];
|
||||
}
|
||||
|
||||
- (void)showTopAlertErrorWithMessage:(nullable NSString *)message {
|
||||
|
||||
MVMCoreTopAlertObject *topAlertObject = [[MVMCoreTopAlertObject alloc] initWithType:ValueTypeError message:message];
|
||||
[self showTopAlertWithObject:topAlertObject];
|
||||
}
|
||||
|
||||
- (void)showTopAlertConfirmationWithMessage:(nullable NSString *)message {
|
||||
|
||||
MVMCoreTopAlertObject *topAlertObject = [[MVMCoreTopAlertObject alloc] initWithType:ValueTypeSuccess message:message];
|
||||
[self showTopAlertWithObject:topAlertObject];
|
||||
}
|
||||
|
||||
- (void)showTopAlertWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData {
|
||||
|
||||
MVMCoreTopAlertObject *topAlertObject = [[MVMCoreTopAlertObject alloc] initWithType:type message:message subMessage:subMessage persistent:persistent actionMap:actionMap additionalData:additionalData];
|
||||
[self showTopAlertWithObject:topAlertObject];
|
||||
}
|
||||
|
||||
- (void)showTopAlertWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler {
|
||||
|
||||
MVMCoreTopAlertObject *topAlertObject = [[MVMCoreTopAlertObject alloc] initWithType:type message:message subMessage:subMessage persistent:persistent buttonTitle:buttonTitle userActionHandler:userActionHandler];
|
||||
[self showTopAlertWithObject:topAlertObject];
|
||||
}
|
||||
|
||||
- (void)hideTopAlertView {
|
||||
|
||||
MVMCoreTopAlertOperation *currentOperation = [self.topAlertQueue.operations firstObject];
|
||||
currentOperation.topAlertObject.persistent = NO;
|
||||
currentOperation.reAddAfterCancel = NO;
|
||||
[currentOperation cancel];
|
||||
}
|
||||
|
||||
- (BOOL)hasPersistentTopAlertOfType:(nullable NSString *)type {
|
||||
BOOL hasAlert = NO;
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
if (operation.topAlertObject.persistent && [operation.topAlertObject.type isEqualToString:type]) {
|
||||
hasAlert = YES;
|
||||
}
|
||||
}
|
||||
return hasAlert;
|
||||
}
|
||||
|
||||
- (void)hidePersistentTopAlertViewOfType:(nullable NSString *)type {
|
||||
if (type) {
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
|
||||
// Cancel all persistent operations of this type.
|
||||
if (operation.topAlertObject.persistent && [operation.topAlertObject.type isEqualToString:type]) {
|
||||
operation.reAddAfterCancel = NO;
|
||||
[operation cancel];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideTopAlertViewOfType:(nullable NSString *)type {
|
||||
if (type) {
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
|
||||
// Cancel all operations of this type.
|
||||
if ([operation.topAlertObject.type isEqualToString:type]) {
|
||||
operation.reAddAfterCancel = NO;
|
||||
[operation cancel];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeTopAlertForObject:(MVMCoreTopAlertObject *)topAlertObject {
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
// Finds an cancels top alerts associated with the object.
|
||||
if (operation.topAlertObject == topAlertObject) {
|
||||
operation.reAddAfterCancel = NO;
|
||||
[operation cancel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeAllTopAlerts {
|
||||
[self.topAlertQueue cancelAllOperations];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,84 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertObject+Swift.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 7/10/20.
|
||||
// Copyright © 2020 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
public extension MVMCoreAlertObject {
|
||||
|
||||
static func alertObject(from alertModel: AlertModel, actions: [UIAlertAction]? = nil, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> MVMCoreAlertObject? {
|
||||
|
||||
let actionsForAlert = actions ?? generateActions(from: alertModel.alertActions, additionalData: additionalData, delegateObject: delegateObject)
|
||||
|
||||
let alertObject = MVMCoreAlertObject(popupAlertWithTitle: alertModel.title,
|
||||
message: alertModel.message,
|
||||
actions: actionsForAlert,
|
||||
isGreedy: false)
|
||||
|
||||
alertObject?.alertStyle = alertModel.style
|
||||
alertObject?.pageJson = alertModel.analyticsData
|
||||
|
||||
return alertObject
|
||||
}
|
||||
|
||||
static func generateActions(from buttonModels: [AlertButtonModel], additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalHandling: ((AlertButtonModel, UIAlertAction)->())? = nil) -> [UIAlertAction] {
|
||||
return buttonModels.map { alertButtonModel in
|
||||
let alertAction = UIAlertAction(title: alertButtonModel.title, style: alertButtonModel.style) { action in
|
||||
Task(priority: .userInitiated) {
|
||||
do {
|
||||
try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(
|
||||
with: alertButtonModel.action,
|
||||
additionalData: additionalData,
|
||||
delegateObject: delegateObject
|
||||
)
|
||||
} catch {
|
||||
|
||||
}
|
||||
additionalHandling?(alertButtonModel, action)
|
||||
}
|
||||
}
|
||||
return alertAction
|
||||
}
|
||||
}
|
||||
|
||||
@objc static func alertObjectWith(action actionJson: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> MVMCoreAlertObject? {
|
||||
|
||||
guard let alertJson = actionJson?.optionalDictionaryForKey("alert"),
|
||||
(alertJson.optionalStringForKey(KeyTitle) != nil || alertJson.optionalStringForKey(KeyMessage) != nil),
|
||||
let actionsList = alertJson.optionalArrayForKey("alertActions") as? [[AnyHashable: Any]]
|
||||
else {
|
||||
error?.pointee = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), code: ErrorCode.popupFailed.rawValue, domain: ErrorDomainNative, location: String(describing: self))
|
||||
return nil
|
||||
}
|
||||
|
||||
var actionsForAlert: [UIAlertAction] = []
|
||||
|
||||
for actionJson in actionsList {
|
||||
let style = UIAlertAction.Style(rawValue: actionJson.stringForkey("style"))
|
||||
let alertAction = UIAlertAction(title: actionJson.optionalStringForKey(KeyTitle), style: style) { action in
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: actionJson.optionalDictionaryForKey("action"),
|
||||
additionalData: additionalData,
|
||||
delegateObject: delegateObject)
|
||||
}
|
||||
actionsForAlert.append(alertAction)
|
||||
}
|
||||
|
||||
let alertObject = MVMCoreAlertObject(popupAlertWithTitle: alertJson.optionalStringForKey(KeyTitle),
|
||||
message: alertJson.optionalStringForKey(KeyMessage),
|
||||
actions: actionsForAlert,
|
||||
isGreedy: false)
|
||||
|
||||
if let alertStyle = alertJson.optionalStringForKey("style") {
|
||||
alertObject?.alertStyle = UIAlertController.Style(rawValue: alertStyle)
|
||||
}
|
||||
|
||||
if let analyticsData = alertJson.optionalDictionaryForKey("analyticsData") {
|
||||
alertObject?.pageJson = ["analyticsData": analyticsData]
|
||||
}
|
||||
|
||||
return alertObject
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertObject.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/21/14.
|
||||
// Copyright (c) 2014 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// An object for keeping track of all alert variables. Easier to pass around.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
@import MVMCore.MVMCoreActionDelegateProtocol;
|
||||
@import MVMCore.MVMCoreLoadDelegateProtocol;
|
||||
@import MVMCore.MVMCorePresentationDelegateProtocol;
|
||||
#import <MVMCoreUI/MVMCoreAlertDelegateProtocol.h>
|
||||
|
||||
@class MVMCoreErrorObject;
|
||||
@class MVMCoreLoadObject;
|
||||
@class DelegateObject;
|
||||
|
||||
typedef NS_ENUM(NSInteger, MFAlertType) {
|
||||
MFAlertTypePopup = 0,
|
||||
MFAlertTypeField,
|
||||
MFAlertTypeTop,
|
||||
MFAlertTypeNone
|
||||
};
|
||||
|
||||
typedef void (^TextFieldErrorHandler)(NSArray * _Nonnull fieldErrors);
|
||||
|
||||
@interface MVMCoreAlertObject : NSObject
|
||||
|
||||
@property (nullable, strong, nonatomic) NSString *title;
|
||||
@property (nullable, copy, nonatomic) NSDictionary *pageJson;
|
||||
@property (nullable, strong, nonatomic) NSString *message;
|
||||
@property (nonnull, strong, nonatomic) NSArray *actions;
|
||||
@property (nonatomic) BOOL isGreedy;
|
||||
@property (nonatomic) UIAlertControllerStyle alertStyle;
|
||||
@property (nonatomic) MFAlertType type;
|
||||
@property (nonatomic) BOOL defaultAction;
|
||||
|
||||
@property (nonnull, strong, nonatomic) NSArray *fieldErrors;
|
||||
@property (nullable, nonatomic, copy) TextFieldErrorHandler textFieldErrorHandler;
|
||||
|
||||
// Set to be notified of popup style alert events.
|
||||
@property (nonatomic, weak, nullable) NSObject <MVMCoreAlertDelegateProtocol> *alertDelegate;
|
||||
|
||||
// Creates an alert object for an error with the passed in load object response info
|
||||
+ (nullable instancetype)alertObjectForLoadObject:(nullable MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error delegateObject:(nullable DelegateObject *)delegateObject;
|
||||
+ (nullable instancetype)alertObjectForPageType:(nullable NSString *)pageType responseInfo:(nullable NSDictionary *)responseInfo additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject;
|
||||
|
||||
// Initializes a popup style alert object. Look at the alert handler to see what each is used for.
|
||||
- (nullable instancetype)initPopupAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nonnull NSArray *)actions isGreedy:(BOOL)isGreedy;
|
||||
|
||||
// Initializes a popup style alert object using the error passed in. Message is formatted default style. By defualt uses the Okay button to just dismiss the error.
|
||||
- (nullable instancetype)initPopupAlertWithError:(nullable MVMCoreErrorObject *)error isGreedy:(BOOL)isGreedy;
|
||||
|
||||
// Same as above but no default actions. They are passed in.
|
||||
- (nullable instancetype)initPopupAlertWithError:(nullable MVMCoreErrorObject *)error actions:(nonnull NSArray *)actions isGreedy:(BOOL)isGreedy;
|
||||
|
||||
// Returns the alert object made with the page json. If there is not enough data to make, we will set error
|
||||
+ (nullable instancetype)alertObjectWithPage:(nullable NSDictionary *)page isGreedy:(BOOL)isGreedy additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error;
|
||||
|
||||
// Will show this alert in it's appropriate type style.
|
||||
- (void)showAlert;
|
||||
|
||||
@end
|
||||
@ -1,197 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertObject.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 11/21/14.
|
||||
// Copyright (c) 2014 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreAlertObject.h"
|
||||
#import "MVMCoreAlertHandler.h"
|
||||
#import "MVMCoreTopAlertObject.h"
|
||||
@import MVMCore.MVMCoreCache;
|
||||
@import MVMCore.MVMCoreErrorConstants;
|
||||
@import MVMCore.MVMCoreErrorObject;
|
||||
@import MVMCore.MVMCoreLoadObject;
|
||||
@import MVMCore.MVMCoreGetterUtility;
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
@import MVMCore.MVMCoreHardcodedStringsConstants;
|
||||
@import MVMCore.MVMCoreJSONConstants;
|
||||
@import MVMCore.Swift;
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
|
||||
@interface MVMCoreAlertObject ()
|
||||
|
||||
@property (strong, nonatomic) MVMCoreLoadObject *loadObject;
|
||||
@property (nullable, strong, nonatomic) NSString *systemDomain;
|
||||
@property (nullable, strong, nonatomic) MVMCoreTopAlertObject *topAlertObject;
|
||||
@end
|
||||
|
||||
@implementation MVMCoreAlertObject
|
||||
|
||||
+ (nullable instancetype)alertObjectForLoadObject:(nullable MVMCoreLoadObject *)loadObject error:(nullable MVMCoreErrorObject *)error delegateObject:(nullable DelegateObject *)delegateObject {
|
||||
|
||||
MVMCoreAlertObject *alert = nil;
|
||||
if (!error || [ErrorDomainServer isEqualToString:error.domain]) {
|
||||
alert = [MVMCoreAlertObject alertObjectForPageType:loadObject.pageType responseInfo:loadObject.responseInfoMap additionalData:loadObject.dataForPage delegateObject:delegateObject];
|
||||
} else {
|
||||
alert = [[MVMCoreAlertObject alloc] initPopupAlertWithError:error isGreedy:NO];
|
||||
}
|
||||
|
||||
// only if actions are empty, then go inside and set OK as default action
|
||||
if (alert.type == MFAlertTypePopup && alert.actions.count == 0) {
|
||||
alert.defaultAction = YES;
|
||||
alert.actions = @[[UIAlertAction actionWithTitle:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedOK] style:UIAlertActionStyleDefault handler:nil]];
|
||||
}
|
||||
return alert;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)alertObjectForPageType:(nullable NSString *)pageType responseInfo:(nullable NSDictionary *)responseInfo additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject {
|
||||
MVMCoreUIDelegateObject *alertDelegateObject = nil;
|
||||
if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) {
|
||||
alertDelegateObject = (MVMCoreUIDelegateObject *)delegateObject;
|
||||
}
|
||||
|
||||
__block MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
|
||||
alert.title = [responseInfo string:KeyErrorHeading] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorTitle];
|
||||
alert.message = [responseInfo string:KeyUserMessage] ?: [MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess];
|
||||
|
||||
NSString *messageStyle = [responseInfo stringForKey:KeyMessageStyle];
|
||||
if ([ValueTypeFieldErrors isEqualToString:[responseInfo string:KeyType]]) {
|
||||
|
||||
// field errors.
|
||||
alert.type = MFAlertTypeField;
|
||||
alert.fieldErrors = [responseInfo array:ValueTypeFieldErrors];
|
||||
} else {
|
||||
|
||||
// Check for top alert (persistent or regular).
|
||||
if ([messageStyle isEqualToString:ValueMessageStyleTopPersistent] || [messageStyle isEqualToString:ValueMessageStyleTop]) {
|
||||
|
||||
alert.topAlertObject = [[MVMCoreTopAlertObject alloc] initWithResponseInfo:responseInfo];
|
||||
alert.topAlertObject.delegate = alertDelegateObject.topAlertDelegate;
|
||||
alert.topAlertObject.pageType = pageType;
|
||||
alert.type = MFAlertTypeTop;
|
||||
} else if ([messageStyle isEqualToString:ValueMessageStylePopup]) {
|
||||
|
||||
// Perform a popup.
|
||||
alert.type = MFAlertTypePopup;
|
||||
alert.alertStyle = UIAlertControllerStyleAlert;
|
||||
|
||||
// Check if we have a popup driven by page object (otherwise by default it will just use response info title message with an OK button).
|
||||
NSString *pageTypeForPopup = [responseInfo stringForKey:@"popupPageType"];
|
||||
[[MVMCoreCache sharedCache] fetchJSONForPageType:pageTypeForPopup queue:nil waitUntilFinished:YES completionHandler:^(NSDictionary * _Nullable jsonDictionary) {
|
||||
|
||||
MVMCoreErrorObject *error = nil;
|
||||
MVMCoreAlertObject *popupAlert = [MVMCoreAlertObject alertObjectWithPage:jsonDictionary isGreedy:NO additionalData:additionalData delegateObject:delegateObject error:&error];
|
||||
if (error) {
|
||||
|
||||
// Error, popup page not found for page type.
|
||||
popupAlert = [[MVMCoreAlertObject alloc] initPopupAlertWithError:error isGreedy:NO];
|
||||
}
|
||||
|
||||
if (popupAlert) {
|
||||
alert = popupAlert;
|
||||
}
|
||||
}];
|
||||
} else if (messageStyle.length == 0 && pageType) {
|
||||
|
||||
// No message style!
|
||||
alert.type = MFAlertTypeNone;
|
||||
} else {
|
||||
|
||||
// Default to popup
|
||||
alert.type = MFAlertTypePopup;
|
||||
alert.alertStyle = UIAlertControllerStyleAlert;
|
||||
}
|
||||
}
|
||||
alert.alertDelegate = alertDelegateObject.alertDelegate;
|
||||
return alert;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initPopupAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(nonnull NSArray *)actions isGreedy:(BOOL)isGreedy {
|
||||
if (self = [super init]) {
|
||||
self.title = title;
|
||||
self.message = message;
|
||||
self.actions = actions;
|
||||
self.isGreedy = isGreedy;
|
||||
self.type = MFAlertTypePopup;
|
||||
self.alertStyle = UIAlertControllerStyleAlert;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initPopupAlertWithError:(nullable MVMCoreErrorObject *)error isGreedy:(BOOL)isGreedy {
|
||||
|
||||
if (self = [super init]) {
|
||||
self.title = error.title;
|
||||
self.message = [NSString stringWithFormat:@"%@ (%@)",error.messageToDisplay,[error stringErrorCode]];
|
||||
self.actions = @[[UIAlertAction actionWithTitle:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedOK] style:UIAlertActionStyleDefault handler:nil]];
|
||||
self.defaultAction = YES;
|
||||
self.isGreedy = isGreedy;
|
||||
self.type = MFAlertTypePopup;
|
||||
self.alertStyle = UIAlertControllerStyleAlert;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initPopupAlertWithError:(nullable MVMCoreErrorObject *)error actions:(nonnull NSArray *)actions isGreedy:(BOOL)isGreedy {
|
||||
|
||||
if (self = [super init]) {
|
||||
self.title = error.title;
|
||||
self.message = [NSString stringWithFormat:@"%@ (%@)",error.messageToDisplay,[error stringErrorCode]];
|
||||
self.actions = actions;
|
||||
self.isGreedy = isGreedy;
|
||||
self.type = MFAlertTypePopup;
|
||||
self.alertStyle = UIAlertControllerStyleAlert;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (nullable instancetype)alertObjectWithPage:(nullable NSDictionary *)page isGreedy:(BOOL)isGreedy additionalData:(nullable NSDictionary *)additionalData delegateObject:(nullable DelegateObject *)delegateObject error:(MVMCoreErrorObject *_Nullable *_Nullable)error {
|
||||
|
||||
MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init];
|
||||
alert.title = [page string:KeyTitle];
|
||||
alert.pageJson = page;
|
||||
alert.message = [page string:KeyMessage];
|
||||
alert.isGreedy = isGreedy;
|
||||
alert.type = MFAlertTypePopup;
|
||||
alert.alertStyle = UIAlertControllerStyleAlert;
|
||||
|
||||
NSArray <NSDictionary *> *actions = [page array:KeyLinks];
|
||||
NSMutableArray <UIAlertAction *> *actionsForAlert = [NSMutableArray array];
|
||||
for (NSDictionary *actionMap in actions) {
|
||||
[actionsForAlert addObject:[UIAlertAction actionWithTitle:[actionMap stringForKey:KeyTitle] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
|
||||
[[MVMCoreUIActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegateObject:delegateObject];
|
||||
}]];
|
||||
}
|
||||
alert.actions = actionsForAlert;
|
||||
|
||||
if ((alert.title.length > 0 || alert.message.length > 0) && alert.actions.count > 0) {
|
||||
return alert;
|
||||
} else {
|
||||
if (error) {
|
||||
id delegate = [delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]] ? ((MVMCoreUIDelegateObject *)delegateObject).alertDelegate : nil;
|
||||
*error = [[MVMCoreErrorObject alloc] initWithTitle:nil message:[MVMCoreGetterUtility hardcodedStringWithKey:HardcodedErrorUnableToProcess] code:ErrorCodePopupFailed domain:ErrorDomainNative location:[NSString stringWithFormat:@"%@_Popup_pageType:%@",NSStringFromClass([delegate class]),[page stringForKey:KeyPageType]]];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showAlert {
|
||||
|
||||
switch (self.type) {
|
||||
case MFAlertTypeField:
|
||||
self.textFieldErrorHandler(self.fieldErrors);
|
||||
break;
|
||||
case MFAlertTypeTop:
|
||||
[[MVMCoreAlertHandler sharedAlertHandler] showTopAlertWithObject:self.topAlertObject];
|
||||
break;
|
||||
case MFAlertTypePopup:
|
||||
[[MVMCoreAlertHandler sharedAlertHandler] showAlertWithAlertObject:self];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertOperation.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 9/28/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// Operation for handling an alert. Should NOT be on the main queue.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
@import MVMCore.MVMCoreOperation;
|
||||
#import <MVMCoreUI/MVMCoreAlertDelegateProtocol.h>
|
||||
|
||||
@interface MVMCoreAlertOperation : MVMCoreOperation
|
||||
|
||||
/// Alert controller to be displayed.
|
||||
@property (nonnull, readonly) UIAlertController *currentAlertView;
|
||||
|
||||
/// If this operation is temporarily paused.
|
||||
@property (readonly, getter=isPaused) BOOL paused;
|
||||
|
||||
/// If this alert is a greedy alert (See MVMCoreAlertHandler).
|
||||
@property (readonly, getter=isGreedy) BOOL greedy;
|
||||
|
||||
/// The alert delegate if needed.
|
||||
@property (readonly, nullable, nonatomic, weak) NSObject <MVMCoreAlertDelegateProtocol> *alertDelegate;
|
||||
|
||||
/// Initializes the operation with the alert to display and if it is greedy or not.
|
||||
- (nullable instancetype)initWithAlert:(nonnull UIAlertController *)alert isGreedy:(BOOL)isGreedy;
|
||||
- (nullable instancetype)initWithAlert:(nonnull UIAlertController *)alert isGreedy:(BOOL)isGreedy alertDelegate:(nullable id <MVMCoreAlertDelegateProtocol>)alertDelegate;
|
||||
|
||||
/// Pauses the operation. Temporarily removes any alert.
|
||||
- (void)pause;
|
||||
|
||||
/// Unpauses the operation, resuming any alert.
|
||||
- (void)unpause;
|
||||
|
||||
@end
|
||||
@ -1,242 +0,0 @@
|
||||
//
|
||||
// MVMCoreAlertOperation.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 9/28/15.
|
||||
// Copyright © 2015 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MVMCoreAlertOperation.h"
|
||||
#import <MVMCoreUI/MVMCoreAlertHandler.h>
|
||||
@import MVMCore.MVMCoreAlertController;
|
||||
@import MVMCore.MVMCoreNavigationHandler;
|
||||
|
||||
@interface MVMCoreAlertOperation () {
|
||||
__block BOOL _paused;
|
||||
__block BOOL _displayed;
|
||||
}
|
||||
|
||||
@property (readwrite, getter=isPaused) BOOL paused;
|
||||
|
||||
@property (readwrite, getter=isGreedy) BOOL greedy;
|
||||
|
||||
@property (readwrite, getter=isDisplayed) BOOL displayed;
|
||||
|
||||
@property (readwrite, nullable, nonatomic, weak) NSObject <MVMCoreAlertDelegateProtocol> *alertDelegate;
|
||||
|
||||
// The currently displayed alert view.
|
||||
@property (nullable, strong, nonatomic) UIAlertController *currentAlertView;
|
||||
|
||||
// A boolean to keep track of if we alreadys signed up to observe.
|
||||
@property (assign, nonatomic) BOOL alertBeingObserved;
|
||||
|
||||
// For thread safety
|
||||
@property (strong, nonatomic) dispatch_queue_t pausedQueue;
|
||||
@property (strong, nonatomic) dispatch_queue_t displayedQueue;
|
||||
|
||||
// Dismisses the alert.
|
||||
- (void)dismissAlertView;
|
||||
|
||||
// Begins observing for when the alert is dismissed.
|
||||
- (void)observeForCurrentAlertViewDismissal;
|
||||
|
||||
// Stops observing for when the alert is dismissed.
|
||||
- (void)stopObservingAlertView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCoreAlertOperation
|
||||
|
||||
// The context for kvo
|
||||
static void * XXContext = &XXContext;
|
||||
|
||||
- (instancetype)init {
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.pausedQueue = dispatch_queue_create("paused", DISPATCH_QUEUE_CONCURRENT);
|
||||
self.displayedQueue = dispatch_queue_create("displayed", DISPATCH_QUEUE_CONCURRENT);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithAlert:(nonnull UIAlertController *)alert isGreedy:(BOOL)isGreedy {
|
||||
|
||||
if (self = [self init]) {
|
||||
self.currentAlertView = alert;
|
||||
self.greedy = isGreedy;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithAlert:(nonnull UIAlertController *)alert isGreedy:(BOOL)isGreedy alertDelegate:(nullable NSObject <MVMCoreAlertDelegateProtocol>*)alertDelegate {
|
||||
if (self = [self initWithAlert:alert isGreedy:isGreedy]) {
|
||||
self.alertDelegate = alertDelegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self stopObservingAlertView];
|
||||
}
|
||||
|
||||
- (BOOL)isPaused {
|
||||
__block BOOL isPaused;
|
||||
dispatch_sync(self.pausedQueue, ^{
|
||||
isPaused = self->_paused;
|
||||
});
|
||||
return isPaused;
|
||||
}
|
||||
|
||||
- (void)setPaused:(BOOL)paused {
|
||||
dispatch_barrier_async(self.pausedQueue, ^{
|
||||
self->_paused = paused;
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)isDisplayed {
|
||||
__block BOOL isDisplayed;
|
||||
dispatch_sync(self.displayedQueue, ^{
|
||||
isDisplayed = self->_displayed;
|
||||
});
|
||||
return isDisplayed;
|
||||
}
|
||||
|
||||
- (void)setDisplayed:(BOOL)displayed {
|
||||
dispatch_barrier_async(self.displayedQueue, ^{
|
||||
self->_displayed = displayed;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)main {
|
||||
|
||||
// Always check for cancellation before launching the task.
|
||||
if ([self checkAndHandleForCancellation]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display alert only if alerts aren't supressed.
|
||||
if (![[MVMCoreAlertHandler sharedAlertHandler] mfAlertsSupressed] && self.currentAlertView) {
|
||||
|
||||
// Observe for when it is removed.
|
||||
[self observeForCurrentAlertViewDismissal];
|
||||
|
||||
// Adds the presentation to the animation queue.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] presentViewController:self.currentAlertView animated:YES delegate:nil completionHandler:^{
|
||||
|
||||
// We finished but it was not displayed yet. It's possible that it was cancelled. Finish this task
|
||||
if (!self.isDisplayed) {
|
||||
[self markAsFinished];
|
||||
} else if (self.isCancelled) {
|
||||
[self dismissAlertView];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
[super cancel];
|
||||
|
||||
// Notify delegate that the alert is cancelled.
|
||||
if ([self.alertDelegate respondsToSelector:@selector(alertCancelled:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.alertDelegate alertCancelled:self.currentAlertView];
|
||||
});
|
||||
}
|
||||
|
||||
[self dismissAlertView];
|
||||
}
|
||||
|
||||
- (void)dismissAlertView {
|
||||
|
||||
if (self.isDisplayed) {
|
||||
|
||||
// Dismisses.
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] dismissViewController:self.currentAlertView animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pause {
|
||||
[self willChangeValueForKey:@"isPaused"];
|
||||
self.paused = YES;
|
||||
[self didChangeValueForKey:@"isPaused"];
|
||||
|
||||
// Notify delegate of pause.
|
||||
if ([self.alertDelegate respondsToSelector:@selector(alertPaused:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.alertDelegate alertPaused:self.currentAlertView];
|
||||
});
|
||||
}
|
||||
|
||||
// Dismiss until unpaused.
|
||||
[self dismissAlertView];
|
||||
}
|
||||
|
||||
- (void)unpause {
|
||||
[self willChangeValueForKey:@"isPaused"];
|
||||
self.paused = NO;
|
||||
[self didChangeValueForKey:@"isPaused"];
|
||||
|
||||
// Notify delegate of unpause.
|
||||
if ([self.alertDelegate respondsToSelector:@selector(alertUnpaused:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.alertDelegate alertUnpaused:self.currentAlertView];
|
||||
});
|
||||
}
|
||||
|
||||
// Show alert...
|
||||
if (self.currentAlertView) {
|
||||
[self start];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Observer Functions
|
||||
|
||||
- (void)observeForCurrentAlertViewDismissal {
|
||||
if (!self.alertBeingObserved && ![[MVMCoreAlertHandler sharedAlertHandler] mfAlertsSupressed] && self.currentAlertView && [self.currentAlertView isKindOfClass:[UIAlertController class]]) {
|
||||
self.alertBeingObserved = YES;
|
||||
[self.currentAlertView addObserver:self forKeyPath:@"visible" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:XXContext];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopObservingAlertView {
|
||||
if (self.alertBeingObserved) {
|
||||
[self.currentAlertView removeObserver:self forKeyPath:@"visible" context:XXContext];
|
||||
self.alertBeingObserved = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
if (context == XXContext && [keyPath isEqualToString:@"visible"]) {
|
||||
if (![object isVisible]) {
|
||||
|
||||
self.displayed = NO;
|
||||
|
||||
// Notify delegate that the alert is dismissed.
|
||||
if ([self.alertDelegate respondsToSelector:@selector(alertDismissed:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.alertDelegate alertDismissed:self.currentAlertView];
|
||||
});
|
||||
}
|
||||
|
||||
// Is visible was set to NO, meaning that the alertview is no longer visible.
|
||||
if (!self.isPaused) {
|
||||
[self stopObservingAlertView];
|
||||
self.currentAlertView = nil;
|
||||
[self markAsFinished];
|
||||
}
|
||||
} else {
|
||||
|
||||
self.displayed = YES;
|
||||
|
||||
// Notify delegate that the alert is shown.
|
||||
if ([self.alertDelegate respondsToSelector:@selector(alertShown:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.alertDelegate alertShown:self.currentAlertView];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@ -10,29 +10,12 @@ import Foundation
|
||||
import MVMCore
|
||||
|
||||
/// Shows an alert using the model.
|
||||
open class ActionAlertHandler: MVMCoreJSONActionHandlerProtocol {
|
||||
open class ActionAlertHandler: MVMCoreActionHandlerProtocol {
|
||||
required public init() {}
|
||||
|
||||
open func performAction(with JSON: [AnyHashable : Any], model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
var error: MVMCoreErrorObject? = nil
|
||||
guard let alertObject = MVMCoreAlertObject.alertObjectWith(action: JSON, additionalData: additionalData, delegateObject: delegateObject, error: &error) else {
|
||||
throw MVMCoreError.errorObject(error!)
|
||||
}
|
||||
(delegateObject?.actionDelegate as? MVMCoreUIActionDelegateProtocol)?.willShowPopup(with: alertObject, alertJson: JSON)
|
||||
_ = await MainActor.run {
|
||||
MVMCoreAlertHandler.shared()?.showAlert(with: alertObject)
|
||||
}
|
||||
}
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
public func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
guard let model = model as? ActionAlertModel else { return }
|
||||
var error: MVMCoreErrorObject? = nil
|
||||
guard let alertObject = MVMCoreAlertObject.alertObject(from: model.alert, additionalData: additionalData, delegateObject: delegateObject, error: &error) else {
|
||||
throw MVMCoreError.errorObject(error!)
|
||||
}
|
||||
(delegateObject?.actionDelegate as? MVMCoreUIActionDelegateProtocol)?.willShowPopup(with: alertObject, alertJson: try MVMCoreActionHandler.convertActionToJSON(model))
|
||||
_ = await MainActor.run {
|
||||
MVMCoreAlertHandler.shared()?.showAlert(with: alertObject)
|
||||
}
|
||||
let alertObject = AlertObject(alertModel: model.alert, alertDelegate: (delegateObject as? MVMCoreUIDelegateObject)?.alertDelegate)
|
||||
_ = await AlertHandler.shared().queueAlertToShow(with: alertObject)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,11 +9,23 @@
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
/// Collapse the current top notification.
|
||||
/// Notifications that conform are collapsable and can collapse.
|
||||
public protocol CollapsableNotificationProtocol {
|
||||
/// Collapses the notification.
|
||||
@MainActor
|
||||
func collapse()
|
||||
}
|
||||
|
||||
/// Collapses the current notification if it can collapse, otherwise dismisses it.
|
||||
open class ActionCollapseNotificationHandler: MVMCoreActionHandlerProtocol {
|
||||
required public init() {}
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
CoreUIObject.sharedInstance()?.globalTopAlertDelegate?.getTopAlertView?().collapseNotification?()
|
||||
guard let notification = await NotificationHandler.shared()?.getCurrentNotification() else { return }
|
||||
guard let notification = notification.0 as? CollapsableNotificationProtocol else {
|
||||
NotificationHandler.shared()?.hideNotification()
|
||||
return
|
||||
}
|
||||
await notification.collapse()
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,15 +9,11 @@
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
/// Collapse the current top notification.
|
||||
/// Dismiss the current notification.
|
||||
open class ActionDismissNotificationHandler: MVMCoreActionHandlerProtocol {
|
||||
required public init() {}
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
await withCheckedContinuation { continuation in
|
||||
CoreUIObject.sharedInstance()?.globalTopAlertDelegate?.getTopAlertView?().hideAlertView?(true, completionHandler: { finished in
|
||||
continuation.resume()
|
||||
}) ?? continuation.resume()
|
||||
}
|
||||
NotificationHandler.shared()?.hideNotification()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
//
|
||||
// ActionPopupHandler.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 7/16/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
/// Shows a popup alert by grabbing the content from a Page in the cache using the pageType.
|
||||
open class ActionPopupHandler: MVMCoreActionHandlerProtocol {
|
||||
required public init() {}
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
guard let model = model as? ActionPopupModel else { return }
|
||||
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
||||
MVMCoreCache.shared()?.fetchJSON(forPageType: model.pageType, queue: nil, waitUntilFinished: true, completionHandler: { json in
|
||||
var error: MVMCoreErrorObject? = nil
|
||||
guard let alertObject = MVMCoreAlertObject(page: json, isGreedy: false, additionalData: additionalData, delegateObject: delegateObject, error: &error) else {
|
||||
continuation.resume(throwing: MVMCoreError.errorObject(error!))
|
||||
return
|
||||
}
|
||||
(delegateObject?.actionDelegate as? MVMCoreUIActionDelegateProtocol)?.willShowPopup(with: alertObject, alertJson: json!)
|
||||
Task { @MainActor in
|
||||
MVMCoreAlertHandler.shared()?.showAlert(with: alertObject)
|
||||
continuation.resume()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
//
|
||||
// ActionPopupModel.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 12/16/19.
|
||||
// Copyright © 2019 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import MVMCore
|
||||
|
||||
public struct ActionPopupModel: ActionModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "popup"
|
||||
public var actionType: String = ActionPopupModel.identifier
|
||||
public var pageType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(pageType: String, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
self.pageType = pageType
|
||||
self.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
//
|
||||
// ActionTopAlertHandler.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 7/18/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
/// Creates and shows an alert using the ResponseInfo of a Page found in the cache.
|
||||
open class ActionTopAlertHandler: MVMCoreActionHandlerProtocol {
|
||||
required public init() {}
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
guard let model = model as? ActionTopAlertModel else { return }
|
||||
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
||||
MVMCoreCache.shared()?.fetchJSON(forPageType: model.pageType, queue: nil, waitUntilFinished: true, completionHandler: { json in
|
||||
guard let responseInfo = json?.optionalDictionaryForKey(KeyResponseInfo) else {
|
||||
continuation.resume(throwing: ModelRegistry.Error.decoderOther(message: "Alert Page \(model.pageType) missing ResponseInfo"))
|
||||
return
|
||||
}
|
||||
|
||||
var alertObject = MVMCoreAlertObject(forPageType: model.pageType, responseInfo: responseInfo, additionalData: additionalData, delegateObject: delegateObject)
|
||||
if let object = alertObject,
|
||||
let closure = (delegateObject?.actionDelegate as? MVMCoreUIActionDelegateProtocol)?.willShowTopAlert {
|
||||
alertObject = closure(object, json!)
|
||||
}
|
||||
alertObject?.showAlert()
|
||||
continuation.resume()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
//
|
||||
// ActionTopAlertModel.swift
|
||||
// MVMCore
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 12/16/19.
|
||||
// Copyright © 2019 myverizon. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct ActionTopAlertModel: ActionModelProtocol {
|
||||
|
||||
public static var identifier: String = "topAlert"
|
||||
public var actionType: String = ActionTopAlertModel.identifier
|
||||
public var pageType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
public init(pageType: String, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
self.pageType = pageType
|
||||
self.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,6 @@ open class ActionTopNotificationHandler: MVMCoreActionHandlerProtocol {
|
||||
|
||||
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
|
||||
guard let model = model as? ActionTopNotificationModel else { return }
|
||||
await MVMCoreUITopAlertView.sharedGlobal()?.showTopAlert(with: model.topNotification)
|
||||
try await NotificationHandler.shared()?.showNotification(for: model.topNotification, delegateObject: delegateObject as? MVMCoreUIDelegateObject)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,11 +13,11 @@ public struct ActionTopNotificationModel: ActionModelProtocol {
|
||||
|
||||
public static var identifier: String = "topNotification"
|
||||
public var actionType: String = ActionTopNotificationModel.identifier
|
||||
public var topNotification: TopNotificationModel
|
||||
public var topNotification: NotificationModel
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
public init(topNotification: TopNotificationModel, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
public init(topNotification: NotificationModel, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||
self.topNotification = topNotification
|
||||
self.extraParameters = extraParameters
|
||||
self.analyticsData = analyticsData
|
||||
|
||||
@ -9,8 +9,7 @@
|
||||
import UIKit
|
||||
import MVMCore
|
||||
|
||||
|
||||
public class AlertButtonModel: Codable {
|
||||
public struct AlertButtonModel: Codable {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +17,7 @@ public class AlertButtonModel: Codable {
|
||||
public var title: String
|
||||
public var action: ActionModelProtocol
|
||||
public var style: UIAlertAction.Style = .default
|
||||
public var preferred: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
@ -37,13 +37,14 @@ public class AlertButtonModel: Codable {
|
||||
case title
|
||||
case action
|
||||
case style
|
||||
case preferred
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
title = try typeContainer.decode(String.self, forKey: .title)
|
||||
|
||||
@ -51,36 +52,61 @@ public class AlertButtonModel: Codable {
|
||||
self.style = UIAlertAction.Style(rawValue: style)
|
||||
}
|
||||
action = try typeContainer.decodeModel(codingKey: .action)
|
||||
preferred = try typeContainer.decodeIfPresent(Bool.self, forKey: .preferred) ?? false
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encode(style.rawValueString, forKey: .style)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encodeIfPresent(preferred, forKey: .preferred)
|
||||
}
|
||||
}
|
||||
|
||||
public class AlertModel: Codable {
|
||||
public struct AlertModel: Codable, Identifiable, AlertModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var title: String
|
||||
public var message: String
|
||||
public var style: UIAlertController.Style = .alert
|
||||
public var alertActions: [AlertButtonModel]
|
||||
|
||||
public var title: String?
|
||||
public var message: String?
|
||||
public var preferredStyle: UIAlertController.Style = .alert
|
||||
public var buttonModels: [AlertButtonModel]
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
public var id: String
|
||||
|
||||
public var delegateObject: DelegateObject?
|
||||
|
||||
public var actions: [UIAlertAction] {
|
||||
get {
|
||||
buttonModels.map({ alertButtonModel in
|
||||
return alertButtonModel.generateAction(delegateObject: delegateObject)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public var preferredActionIndex: Int? {
|
||||
get {
|
||||
buttonModels.firstIndex(where: { alertButtonModel in
|
||||
return alertButtonModel.preferred
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
// MARK: - Init
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(title: String, message: String, alertActions: [AlertButtonModel], style: UIAlertController.Style = .alert) {
|
||||
public init(title: String? = nil, message: String? = nil, buttonModels: [AlertButtonModel], style: UIAlertController.Style = .alert, delegateObject: DelegateObject? = nil, id: String = UUID().uuidString) {
|
||||
self.title = title
|
||||
self.message = message
|
||||
self.alertActions = alertActions
|
||||
self.style = style
|
||||
self.buttonModels = buttonModels
|
||||
self.preferredStyle = style
|
||||
self.delegateObject = delegateObject
|
||||
self.id = id
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -93,30 +119,46 @@ public class AlertModel: Codable {
|
||||
case alertActions
|
||||
case style
|
||||
case analyticsData
|
||||
case id
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
delegateObject = try decoder.get()
|
||||
title = try typeContainer.decode(String.self, forKey: .title)
|
||||
message = try typeContainer.decode(String.self, forKey: .message)
|
||||
alertActions = try typeContainer.decode([AlertButtonModel].self, forKey: .alertActions)
|
||||
buttonModels = try typeContainer.decode([AlertButtonModel].self, forKey: .alertActions)
|
||||
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
|
||||
|
||||
if let style = try typeContainer.decodeIfPresent(String.self, forKey: .style) {
|
||||
self.style = UIAlertController.Style(rawValue: style)
|
||||
self.preferredStyle = UIAlertController.Style(rawValue: style)
|
||||
}
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encode(message, forKey: .message)
|
||||
try container.encode(alertActions, forKey: .alertActions)
|
||||
try container.encode(style.rawValueString, forKey: .style)
|
||||
try container.encodeIfPresent(buttonModels, forKey: .alertActions)
|
||||
try container.encode(preferredStyle.rawValueString, forKey: .style)
|
||||
try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
|
||||
try container.encode(id, forKey: .id)
|
||||
}
|
||||
}
|
||||
|
||||
public extension AlertButtonModel {
|
||||
func generateAction(with additionalData: [AnyHashable: Any]? = nil, delegateObject: DelegateObject? = nil, additionalHandling: ((AlertButtonModel, UIAlertAction)->())? = nil) -> UIAlertAction {
|
||||
let alertAction = UIAlertAction(title: title, style: style) { action in
|
||||
Task(priority: .userInitiated) {
|
||||
try? await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(with: self.action, additionalData: additionalData, delegateObject: delegateObject)
|
||||
additionalHandling?(self, action)
|
||||
}
|
||||
}
|
||||
return alertAction
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
//--------------------------------------------------
|
||||
//Making static property as class property so that subclasses can override getter function of the property
|
||||
open class var identifier: String { "button" }
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var accessibilityIdentifier: String?
|
||||
public var accessibilityText: String?
|
||||
public var title: String
|
||||
@ -174,6 +176,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -201,6 +204,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
title = try typeContainer.decode(String.self, forKey: .title)
|
||||
@ -263,6 +267,7 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
|
||||
open 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.encode(title, forKey: .title)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
|
||||
@ -16,6 +16,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "caretLink"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var title: String
|
||||
@ -41,6 +42,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
case title
|
||||
@ -61,6 +63,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
title = try typeContainer.decode(String.self, forKey: .title)
|
||||
@ -94,6 +97,7 @@ public class CaretLinkModel: ButtonModelProtocol, MoleculeModelProtocol, Enablea
|
||||
|
||||
public 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.encode(title, forKey: .title)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -14,8 +14,9 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "imageButton"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
|
||||
public var image: ImageViewModel?
|
||||
|
||||
public var accessibilityText: String?
|
||||
@ -34,6 +35,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case image
|
||||
case backgroundColor
|
||||
@ -52,6 +54,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image)
|
||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
@ -77,6 +80,7 @@ open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGro
|
||||
|
||||
public 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(image, forKey: .image)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -15,6 +15,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
//--------------------------------------------------
|
||||
|
||||
public class var identifier: String { "link" }
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
@ -48,6 +49,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -91,6 +93,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
title = try typeContainer.decode(String.self, forKey: .title)
|
||||
@ -137,6 +140,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -11,11 +11,14 @@ import MVMCore
|
||||
|
||||
@objcMembers public class TagModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tag"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var label: LabelModel
|
||||
public var action: ActionModelProtocol?
|
||||
public var backgroundColor: Color?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case label
|
||||
case action
|
||||
@ -38,6 +41,7 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
label = try typeContainer.decode(LabelModel.self, forKey: .label)
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
@ -45,6 +49,7 @@ import MVMCore
|
||||
|
||||
public 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.encode(label, forKey: .label)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
|
||||
@ -11,10 +11,13 @@ import MVMCore
|
||||
|
||||
@objcMembers public class TagsModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tags"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var tags: [TagModel]
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case tags
|
||||
@ -30,12 +33,14 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
tags = try typeContainer.decode([TagModel].self, forKey: .tags)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
}
|
||||
|
||||
public 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.encode(tags, forKey: .tags)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -66,7 +66,7 @@ import MVMCore
|
||||
// MARK: - Setup
|
||||
//--------------------------------------------------
|
||||
|
||||
@objc public override func setupFieldContainerContent(_ container: UIView) {
|
||||
@objc open override func setupFieldContainerContent(_ container: UIView) {
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
container.addSubview(dropDownCaretView)
|
||||
@ -79,7 +79,7 @@ import MVMCore
|
||||
dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
|
||||
}
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.additionalData = additionalData
|
||||
guard let model = model as? BaseDropdownEntryFieldModel else { return }
|
||||
@ -87,7 +87,7 @@ import MVMCore
|
||||
dropDownCaretView.setOptional(with: model.caretView, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
@objc public override func dismissFieldInput(_ sender: Any?) {
|
||||
@objc open override func dismissFieldInput(_ sender: Any?) {
|
||||
if !textField.isFirstResponder {
|
||||
performDropdownAction()
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
public var caretView: CaretViewModel?
|
||||
public var action: ActionModelProtocol?
|
||||
|
||||
public override class var identifier: String { "" }
|
||||
open override class var identifier: String { "" }
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -26,6 +26,10 @@
|
||||
case action
|
||||
}
|
||||
|
||||
public override init(with text: String) {
|
||||
super.init(with: text)
|
||||
}
|
||||
|
||||
open override func setDefaults() {
|
||||
super.setDefaults()
|
||||
enableClipboardActions = false
|
||||
@ -42,7 +46,7 @@
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
open override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
|
||||
@ -16,6 +16,12 @@
|
||||
public var options: [String] = []
|
||||
public var selectedIndex: Int?
|
||||
|
||||
public init(with options: [String], selectedIndex: Int? = nil) {
|
||||
self.options = options
|
||||
self.selectedIndex = selectedIndex
|
||||
super.init(with: options.first ?? "")
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Validation
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -16,6 +16,7 @@ import Foundation
|
||||
//--------------------------------------------------
|
||||
|
||||
public class var identifier: String { "" }
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
@ -63,6 +64,7 @@ import Foundation
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -138,6 +140,7 @@ import Foundation
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||
@ -166,6 +169,7 @@ import Foundation
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
|
||||
@ -144,7 +144,9 @@ import MVMCore
|
||||
picker.displayedPropertyKeys = ["phoneNumbers"]
|
||||
picker.predicateForEnablingContact = NSPredicate(format: "phoneNumbers.@count > 0")
|
||||
picker.predicateForSelectionOfProperty = NSPredicate(format: "key == 'phoneNumbers'")
|
||||
MVMCoreNavigationHandler.shared()?.present(picker, animated: true)
|
||||
Task(priority: .userInitiated) {
|
||||
await NavigationHandler.shared().present(viewController: picker, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -215,8 +217,12 @@ import MVMCore
|
||||
|
||||
proprietorTextDelegate?.textFieldDidEndEditing?(textField)
|
||||
|
||||
if validateMDNTextField() && isNationalMDN {
|
||||
textField.text = MVMCoreUIUtility.formatMdn(textField.text)
|
||||
if validateMDNTextField() {
|
||||
if isNationalMDN {
|
||||
textField.text = MVMCoreUIUtility.formatMdn(textField.text)
|
||||
}
|
||||
// Validate the base input field along with triggering form field validation rules.
|
||||
validateText()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "checkbox"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var selected: Bool = false
|
||||
@ -51,6 +52,7 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case accessibilityIdentifier
|
||||
case checked
|
||||
@ -107,6 +109,8 @@
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
|
||||
if let borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) {
|
||||
@ -180,6 +184,7 @@
|
||||
|
||||
public 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(groupName, forKey: .groupName)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
|
||||
@ -14,6 +14,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "heart"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var isActive: Bool = false
|
||||
@ -27,6 +29,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -49,6 +52,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let isActive = try typeContainer.decodeIfPresent(Bool.self, forKey: .isActive) {
|
||||
self.isActive = isActive
|
||||
}
|
||||
@ -75,6 +80,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(isActive, forKey: .isActive)
|
||||
try container.encode(activeColor, forKey: .activeColor)
|
||||
|
||||
@ -13,6 +13,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "radioBox"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var text: String
|
||||
public var subText: String?
|
||||
public var backgroundColor: Color?
|
||||
@ -30,6 +32,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case text
|
||||
case subText
|
||||
@ -58,6 +61,8 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
text = try typeContainer.decode(String.self, forKey: .text)
|
||||
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||
@ -81,6 +86,7 @@ import MVMCore
|
||||
|
||||
public 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.encode(text, forKey: .text)
|
||||
try container.encodeIfPresent(subText, forKey: .subText)
|
||||
|
||||
@ -13,6 +13,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "radioBoxes"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var boxes: [RadioBoxModel]
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
@ -49,6 +51,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case enabled
|
||||
case readOnly
|
||||
@ -75,6 +78,7 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
@ -91,6 +95,7 @@ import MVMCore
|
||||
|
||||
public 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.encode(boxes, forKey: .boxes)
|
||||
try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor)
|
||||
|
||||
@ -26,7 +26,7 @@ import VDSFormControlsTokens
|
||||
}
|
||||
}
|
||||
public var enabledColor: UIColor {
|
||||
return radioModel?.inverted ?? false ? VDSFormControlsColor.borderOndark : VDSFormControlsColor.borderOnlight
|
||||
return radioModel?.inverted ?? false ? VDSColor.elementsPrimaryOndark : VDSColor.elementsPrimaryOnlight
|
||||
}
|
||||
public var disabledColor: UIColor {
|
||||
return radioModel?.inverted ?? false ? VDSColor.interactiveDisabledOndark : VDSColor.interactiveDisabledOnlight
|
||||
|
||||
@ -15,6 +15,8 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "radioButton"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var state: Bool = false
|
||||
@ -35,6 +37,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -80,6 +83,8 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
||||
self.state = state
|
||||
}
|
||||
@ -105,6 +110,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(state, forKey: .state)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
|
||||
@ -13,6 +13,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "radioSwatch"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var color: Color = Color(uiColor: .mvmBlue)
|
||||
@ -29,6 +31,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -54,6 +57,7 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
|
||||
@ -79,6 +83,7 @@ import MVMCore
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
|
||||
@ -13,6 +13,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "radioSwatches"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var swatches: [RadioSwatchModel]
|
||||
@ -43,6 +45,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -67,6 +70,7 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||
swatches = try typeContainer.decode([RadioSwatchModel].self, forKey: .swatches)
|
||||
@ -81,6 +85,7 @@ import MVMCore
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
|
||||
@ -13,6 +13,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "toggle"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var accessibilityIdentifier: String?
|
||||
public var backgroundColor: Color?
|
||||
public var selected: Bool = false
|
||||
@ -36,6 +38,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case state
|
||||
case animated
|
||||
@ -86,6 +89,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
|
||||
self.selected = state
|
||||
}
|
||||
@ -128,6 +133,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
|
||||
@ -17,8 +17,9 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
public static var identifier: String {
|
||||
return "arrow"
|
||||
}
|
||||
|
||||
public var moleculeName: String?
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var disabledColor: Color = Color(uiColor: .mvmCoolGray3)
|
||||
public var color: Color = Color(uiColor: .mvmBlack)
|
||||
@ -57,6 +58,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case disabledColor
|
||||
@ -75,7 +77,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
|
||||
if let disabledColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor) {
|
||||
@ -113,6 +115,7 @@ open class ArrowModel: MoleculeModelProtocol, EnableableModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(disabledColor, forKey: .disabledColor)
|
||||
|
||||
@ -15,6 +15,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "caretView"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var strokeColor: Color = Color(uiColor: .mvmBlack)
|
||||
public var strokeColor_inverted: Color = Color(uiColor: .mvmWhite)
|
||||
@ -28,6 +29,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case strokeColor
|
||||
@ -51,6 +53,8 @@ import MVMCore
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let strokeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .strokeColor) {
|
||||
self.strokeColor = strokeColor
|
||||
}
|
||||
@ -78,6 +82,7 @@ import MVMCore
|
||||
|
||||
public 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.encode(strokeColor, forKey: .strokeColor)
|
||||
try container.encode(strokeColor_inverted, forKey: .strokeColor_inverted)
|
||||
|
||||
@ -18,6 +18,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
||||
return ""
|
||||
}
|
||||
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var moleculeName: String?
|
||||
public var numberOfPages: Int = 0
|
||||
@ -44,6 +45,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case currentIndex
|
||||
@ -66,6 +68,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
|
||||
@ -112,6 +115,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(numberOfPages, forKey: .numberOfPages)
|
||||
|
||||
@ -18,6 +18,8 @@ public enum CheckboxPosition: String, Codable {
|
||||
@objcMembers open class CheckboxLabelModel: MoleculeModelProtocol {
|
||||
open class var identifier: String { "checkboxLabel" }
|
||||
public var moleculeName: String = CheckboxLabelModel.identifier
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var checkboxAlignment: CheckboxPosition?
|
||||
public var checkbox: CheckboxModel
|
||||
|
||||
@ -15,6 +15,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "dashLine"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var accessibilityIdentifier: String?
|
||||
public var dashColor: Color = Color(uiColor: .mvmCoolGray3)
|
||||
@ -35,6 +37,7 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
@ -56,6 +59,8 @@ import MVMCore
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let dashColor = try typeContainer.decodeIfPresent(Color.self, forKey: .dashColor) {
|
||||
self.dashColor = dashColor
|
||||
}
|
||||
@ -74,6 +79,7 @@ import MVMCore
|
||||
|
||||
public 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.encode(dashColor, forKey: .dashColor)
|
||||
try container.encode(isHidden, forKey: .isHidden)
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
open class var identifier: String { "image" }
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var moleculeName: String = ImageViewModel.identifier
|
||||
@ -26,6 +27,7 @@
|
||||
public var localBundle: Bundle?
|
||||
public var cornerRadius: CGFloat?
|
||||
public var clipsImage: Bool?
|
||||
public var allowServerParameters: Bool?
|
||||
public var shouldMaskRecordedView: Bool? = false
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -44,6 +46,7 @@
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case image
|
||||
@ -56,5 +59,6 @@
|
||||
case cornerRadius
|
||||
case clipsImage
|
||||
case shouldMaskRecordedView
|
||||
case allowServerParameters
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,6 +276,9 @@ public typealias ActionBlock = () -> ()
|
||||
guard let labelModel = model as? LabelModel else { return }
|
||||
|
||||
text = labelModel.text
|
||||
if let accessibilityTraits = labelModel.accessibilityTraits {
|
||||
self.accessibilityTraits = accessibilityTraits
|
||||
}
|
||||
|
||||
resetAttributeStyle()
|
||||
|
||||
@ -754,6 +757,37 @@ public typealias ActionBlock = () -> ()
|
||||
|
||||
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
|
||||
}
|
||||
|
||||
/**
|
||||
Provides a text container and layout manager of how the text would appear on screen.
|
||||
They are used in tandem to derive low-level TextKit results of the label.
|
||||
*/
|
||||
public func abstractTextContainer() -> (NSTextContainer, NSLayoutManager, NSTextStorage)? {
|
||||
|
||||
// Must configure the attributed string to translate what would appear on screen to accurately analyze.
|
||||
guard let attributedText = attributedText else { return nil }
|
||||
|
||||
let paragraph = NSMutableParagraphStyle()
|
||||
paragraph.alignment = textAlignment
|
||||
|
||||
let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText)
|
||||
stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count))
|
||||
|
||||
let textStorage = NSTextStorage(attributedString: stagedAttributedString)
|
||||
let layoutManager = NSLayoutManager()
|
||||
let textContainer = NSTextContainer(size: .zero)
|
||||
|
||||
layoutManager.addTextContainer(textContainer)
|
||||
textStorage.addLayoutManager(layoutManager)
|
||||
|
||||
textContainer.lineFragmentPadding = 0.0
|
||||
textContainer.lineBreakMode = lineBreakMode
|
||||
textContainer.maximumNumberOfLines = numberOfLines
|
||||
textContainer.size = bounds.size
|
||||
|
||||
return (textContainer, layoutManager, textStorage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Atomization
|
||||
|
||||
@ -7,13 +7,14 @@
|
||||
//
|
||||
|
||||
|
||||
@objcMembers open class LabelModel: MoleculeModelProtocol, Identifiable {
|
||||
@objcMembers open class LabelModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
open class var identifier: String { "label" }
|
||||
public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var text: String
|
||||
public var accessibilityText: String?
|
||||
@ -28,14 +29,15 @@
|
||||
public var makeWholeViewClickable: Bool?
|
||||
public var numberOfLines: Int?
|
||||
public var shouldMaskRecordedView: Bool? = false
|
||||
public var accessibilityTraits: UIAccessibilityTraits?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case id
|
||||
case moleculeName
|
||||
case text
|
||||
case accessibilityText
|
||||
case textColor
|
||||
@ -50,6 +52,7 @@
|
||||
case makeWholeViewClickable
|
||||
case numberOfLines
|
||||
case shouldMaskRecordedView
|
||||
case accessibilityTraits
|
||||
}
|
||||
|
||||
enum AttributeTypeKey: String, CodingKey {
|
||||
@ -60,9 +63,10 @@
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(id: String = UUID().uuidString, text: String) {
|
||||
public init(id: String = UUID().uuidString, text: String, textColor: Color? = nil) {
|
||||
self.id = id
|
||||
self.text = text
|
||||
self.textColor = textColor
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -96,6 +100,7 @@
|
||||
makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable)
|
||||
numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines)
|
||||
shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? false
|
||||
accessibilityTraits = try typeContainer.decodeIfPresent(UIAccessibilityTraits.self, forKey: .accessibilityTraits)
|
||||
|
||||
// Later make protocol based validate outside of decoding?
|
||||
if let attributes = attributes {
|
||||
@ -106,7 +111,7 @@
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(id, forKey: .id)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(text, forKey: .text)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(textColor, forKey: .textColor)
|
||||
@ -121,5 +126,6 @@
|
||||
try container.encodeIfPresent(makeWholeViewClickable, forKey: .makeWholeViewClickable)
|
||||
try container.encodeIfPresent(numberOfLines, forKey: .numberOfLines)
|
||||
try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||
try container.encodeIfPresent(accessibilityTraits, forKey: .accessibilityTraits)
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@ import UIKit
|
||||
|
||||
public static var identifier: String = "leftRightLabelView"
|
||||
public var moleculeName: String = LeftRightLabelModel.identifier
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var leftText: LabelModel
|
||||
public var rightText: LabelModel?
|
||||
|
||||
@ -53,6 +53,8 @@ import VDSColorTokens
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "line"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var type: Style = .secondary
|
||||
public var frequency: Frequency? = .allExceptTop
|
||||
|
||||
@ -120,6 +122,7 @@ import VDSColorTokens
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case type
|
||||
case backgroundColor
|
||||
@ -138,6 +141,8 @@ import VDSColorTokens
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let type = try typeContainer.decodeIfPresent(Style.self, forKey: .type) {
|
||||
self.type = type
|
||||
}
|
||||
@ -158,6 +163,7 @@ import VDSColorTokens
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(type, forKey: .type)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encodeIfPresent(frequency, forKey: .frequency)
|
||||
|
||||
@ -289,7 +289,7 @@
|
||||
if shouldLoadImage(withName: imageModel.image, width: width, height: height) {
|
||||
imageView.image = nil
|
||||
imageView.animatedImage = nil
|
||||
loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width, height: height, customFallbackImage: imageModel.fallbackImage, localBundle: imageModel.localBundle)
|
||||
loadImage(withName: imageModel.image, format: imageModel.imageFormat, width: width, height: height, customFallbackImage: imageModel.fallbackImage, allowServerParameters: imageModel.allowServerParameters ?? false, localBundle: imageModel.localBundle)
|
||||
}
|
||||
|
||||
if let contentMode = imageModel.contentMode {
|
||||
|
||||
@ -13,9 +13,10 @@ open class LoadingSpinnerModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public static var identifier: String = "loadingSpinner"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var strokeColor = Color(uiColor: .mvmBlack)
|
||||
public var lineWidth: CGFloat = 4
|
||||
public var diameter: CGFloat = 40
|
||||
@ -25,6 +26,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case strokeColor
|
||||
@ -45,6 +47,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
|
||||
if let diameter = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .diameter) {
|
||||
@ -62,6 +65,7 @@ open class LoadingSpinnerModel: MoleculeModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(diameter, forKey: .diameter)
|
||||
|
||||
@ -19,13 +19,17 @@ import Foundation
|
||||
}
|
||||
|
||||
@objcMembers public class MultiProgressBarModel: MoleculeModelProtocol {
|
||||
|
||||
public static var identifier: String = "multiProgressBar"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var progressList: [SingleProgressBarModel]
|
||||
public var backgroundColor: Color?
|
||||
public var thickness: CGFloat?
|
||||
public var roundedCorners: Bool?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case progressList
|
||||
case thickness
|
||||
@ -39,6 +43,7 @@ import Foundation
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
progressList = try typeContainer.decode([SingleProgressBarModel].self, forKey: .progressList)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness)
|
||||
@ -47,6 +52,7 @@ import Foundation
|
||||
|
||||
public 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.encode(progressList, forKey: .progressList)
|
||||
try container.encodeIfPresent(thickness, forKey: .thickness)
|
||||
|
||||
@ -10,6 +10,8 @@ import Foundation
|
||||
|
||||
@objcMembers public class ProgressBarModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "progressBar"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
@Percent public var percent: CGFloat
|
||||
public var color: Color = Color(uiColor: .mfCerulean())
|
||||
public var backgroundColor: Color? = Color(uiColor: .mfLightSilver())
|
||||
@ -17,6 +19,7 @@ import Foundation
|
||||
public var thickness: CGFloat?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case roundedCorners
|
||||
case thickness
|
||||
@ -31,6 +34,7 @@ import Foundation
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
percent = try typeContainer.decode(CGFloat.self, forKey: .percent)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
|
||||
self.color = color
|
||||
@ -44,6 +48,7 @@ import Foundation
|
||||
|
||||
public 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.encode(percent, forKey: .percent)
|
||||
try container.encode(color, forKey: .color)
|
||||
|
||||
@ -13,6 +13,8 @@ open class StarModel: MoleculeModelProtocol {
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "star"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
@Percent public var percent: CGFloat = 0
|
||||
public var borderColor: Color?
|
||||
@ -23,6 +25,7 @@ open class StarModel: MoleculeModelProtocol {
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case percent
|
||||
@ -43,6 +46,7 @@ open class StarModel: MoleculeModelProtocol {
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
if let percent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .percent) {
|
||||
self.percent = percent
|
||||
}
|
||||
@ -56,6 +60,7 @@ open class StarModel: MoleculeModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(percent, forKey: .percent)
|
||||
|
||||
@ -13,6 +13,8 @@ import MVMCore
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "stars"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var starBackgroundColor: Color?
|
||||
public var stars: [StarModel]
|
||||
@ -25,6 +27,7 @@ import MVMCore
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case starBackgroundColor
|
||||
@ -48,6 +51,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
stars = try typeContainer.decode([StarModel].self, forKey: .stars)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
starBackgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .starBackgroundColor)
|
||||
@ -63,6 +68,7 @@ import MVMCore
|
||||
|
||||
public 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.encode(stars, forKey: .stars)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -37,8 +37,11 @@ open class Tilelet: VDS.Tilelet, VDSMoleculeViewProtocol{
|
||||
padding = viewModel.padding
|
||||
aspectRatio = viewModel.aspectRatio
|
||||
width = viewModel.width
|
||||
textWidth = viewModel.textWidth
|
||||
textPercentage = viewModel.textPercentage
|
||||
if let value = viewModel.textWidth {
|
||||
textWidth = .value(value)
|
||||
} else if let percentage = viewModel.textPercentage {
|
||||
textWidth = .percentage(percentage)
|
||||
}
|
||||
titleModel = viewModel.titleModel(delegateObject: delegateObject, additionalData: additionalData)
|
||||
subTitleModel = viewModel.subTitleModel(delegateObject: delegateObject, additionalData: additionalData)
|
||||
badgeModel = viewModel.badge
|
||||
|
||||
@ -15,6 +15,7 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "tilelet"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var color: TileContainer.BackgroundColor
|
||||
public var padding: TileContainer.Padding
|
||||
@ -30,6 +31,7 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
public var action: ActionModelProtocol?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case color
|
||||
@ -47,6 +49,7 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
}
|
||||
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(TileContainer.BackgroundColor.self, forKey: .color) ?? TileContainer.BackgroundColor.black
|
||||
self.padding = try container.decodeIfPresent(TileContainer.Padding.self, forKey: .padding) ?? TileContainer.Padding.padding4X
|
||||
@ -65,9 +68,9 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
public func titleModel(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Tilelet.TitleModel? {
|
||||
guard let title else { return nil }
|
||||
let attrs = title.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData)
|
||||
let style: Tilelet.TitleModel.TextStyle? = title.fontStyle?.vdsSubsetStyle()
|
||||
if let style {
|
||||
return .init(text: title.text, textAttributes: attrs, textStyle: style)
|
||||
let style: TextStyle? = title.fontStyle?.vdsTextStyle()
|
||||
if let style, let standardStyle = Tilelet.TitleModel.StandardStyle(rawValue: style.toStandardStyle().rawValue) {
|
||||
return .init(text: title.text, textAttributes: attrs, standardStyle: standardStyle)
|
||||
} else {
|
||||
return .init(text: title.text, textAttributes: attrs)
|
||||
}
|
||||
@ -75,16 +78,18 @@ open class TileletModel: MoleculeModelProtocol {
|
||||
|
||||
public func subTitleModel(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Tilelet.SubTitleModel? {
|
||||
guard let subTitle else { return nil }
|
||||
let style: Tilelet.SubTitleModel.TextStyle? = subTitle.fontStyle?.vdsSubsetStyle()
|
||||
if let style {
|
||||
return .init(text: subTitle.text, textStyle: style)
|
||||
let attrs = subTitle.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData)
|
||||
let style: TextStyle? = subTitle.fontStyle?.vdsTextStyle()
|
||||
if let style, let standardStyle = Tilelet.SubTitleModel.StandardStyle(rawValue: style.toStandardStyle().rawValue) {
|
||||
return .init(text: subTitle.text, textAttributes: attrs, standardStyle: standardStyle)
|
||||
} else {
|
||||
return .init(text: subTitle.text)
|
||||
return .init(text: subTitle.text, textAttributes: attrs)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(color, forKey: .color)
|
||||
|
||||
@ -10,6 +10,7 @@ import Foundation
|
||||
|
||||
open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer {
|
||||
public static var identifier = "video"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var video: String
|
||||
public var showControls = false
|
||||
@ -43,6 +44,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer {
|
||||
private var resignActiveListener: Any?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case video
|
||||
case showControls
|
||||
@ -57,6 +59,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
video = try typeContainer.decode(String.self, forKey:.video)
|
||||
if let showControls = try typeContainer.decodeIfPresent(Bool.self, forKey: .showControls) {
|
||||
self.showControls = showControls
|
||||
@ -72,6 +75,7 @@ open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer {
|
||||
|
||||
open 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.encode(video, forKey: .video)
|
||||
try container.encode(showControls, forKey: .showControls)
|
||||
|
||||
@ -12,6 +12,8 @@ import MVMCore
|
||||
@objcMembers public class WebViewModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "webview"
|
||||
public var moleculeName: String = WebViewModel.identifier
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var url: URL?
|
||||
public var htmlString: String?
|
||||
@ -23,6 +25,7 @@ import MVMCore
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey{
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case url
|
||||
@ -39,6 +42,7 @@ import MVMCore
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
url = try typeContainer.decodeIfPresent(URL.self, forKey: .url)
|
||||
htmlString = try typeContainer.decodeIfPresent(String.self, forKey: .htmlString)
|
||||
@ -51,6 +55,7 @@ import MVMCore
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(url, forKey: .url)
|
||||
|
||||
@ -19,6 +19,8 @@ public enum GraphStyle: String, Codable {
|
||||
public class WheelModel: MoleculeModelProtocol {
|
||||
|
||||
public static var identifier: String = "wheel"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var style: GraphStyle = .unlimited {
|
||||
didSet {
|
||||
updateStyle()
|
||||
@ -43,6 +45,7 @@ public class WheelModel: MoleculeModelProtocol {
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case style
|
||||
case size
|
||||
case diameter
|
||||
@ -56,6 +59,8 @@ public class WheelModel: MoleculeModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
|
||||
if let style = try typeContainer.decodeIfPresent(GraphStyle.self, forKey: .style) {
|
||||
self.style = style
|
||||
}
|
||||
@ -84,6 +89,7 @@ public class WheelModel: MoleculeModelProtocol {
|
||||
|
||||
public 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.encode(style, forKey: .style)
|
||||
try container.encode(size, forKey: .size)
|
||||
|
||||
125
MVMCoreUI/Atomic/Extensions/UIAccessibilityTraits+Codable.swift
Normal file
125
MVMCoreUI/Atomic/Extensions/UIAccessibilityTraits+Codable.swift
Normal file
@ -0,0 +1,125 @@
|
||||
//
|
||||
// UIAccessibilityTraits+Codable.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 6/16/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension UIAccessibilityTraits: Codable {
|
||||
private static func trait(from string: String) throws -> UIAccessibilityTraits {
|
||||
switch string {
|
||||
case "none":
|
||||
return .none
|
||||
case "button":
|
||||
return .button
|
||||
case "link":
|
||||
return .link
|
||||
case "image":
|
||||
return .image
|
||||
case "searchField":
|
||||
return .searchField
|
||||
case "keyboardKey":
|
||||
return .keyboardKey
|
||||
case "staticText":
|
||||
return .staticText
|
||||
case "header":
|
||||
return .header
|
||||
case "tabBar":
|
||||
return .tabBar
|
||||
case "summaryElement":
|
||||
return .summaryElement
|
||||
case "selected":
|
||||
return .selected
|
||||
case "notEnabled":
|
||||
return .notEnabled
|
||||
case "adjustable":
|
||||
return .adjustable
|
||||
case "allowsDirectInteraction":
|
||||
return .allowsDirectInteraction
|
||||
case "updatesFrequently":
|
||||
return .updatesFrequently
|
||||
case "causesPageTurn":
|
||||
return .causesPageTurn
|
||||
case "playsSound":
|
||||
return .playsSound
|
||||
case "startsMediaSession":
|
||||
return .startsMediaSession
|
||||
default:
|
||||
throw ModelRegistry.Error.decoderOther(message: "Unsupported accessibility trait: \(string)")
|
||||
}
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
var container = try decoder.unkeyedContainer()
|
||||
|
||||
// Iterate and decode each.
|
||||
var accessibilityTrait: UIAccessibilityTraits = []
|
||||
while !container.isAtEnd {
|
||||
let traitString = try container.decode(String.self)
|
||||
let trait = try UIAccessibilityTraits.trait(from: traitString)
|
||||
accessibilityTrait.insert(trait)
|
||||
}
|
||||
self = accessibilityTrait
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.unkeyedContainer()
|
||||
if self.contains(.none) {
|
||||
try container.encode("none")
|
||||
}
|
||||
if self.contains(.button) {
|
||||
try container.encode("button")
|
||||
}
|
||||
if self.contains(.link) {
|
||||
try container.encode("link")
|
||||
}
|
||||
if self.contains(.image) {
|
||||
try container.encode("image")
|
||||
}
|
||||
if self.contains(.searchField) {
|
||||
try container.encode("searchField")
|
||||
}
|
||||
if self.contains(.keyboardKey) {
|
||||
try container.encode("keyboardKey")
|
||||
}
|
||||
if self.contains(.staticText) {
|
||||
try container.encode("staticText")
|
||||
}
|
||||
if self.contains(.header) {
|
||||
try container.encode("header")
|
||||
}
|
||||
if self.contains(.tabBar) {
|
||||
try container.encode("tabBar")
|
||||
}
|
||||
if self.contains(.summaryElement) {
|
||||
try container.encode("summaryElement")
|
||||
}
|
||||
if self.contains(.selected) {
|
||||
try container.encode("selected")
|
||||
}
|
||||
if self.contains(.notEnabled) {
|
||||
try container.encode("notEnabled")
|
||||
}
|
||||
if self.contains(.adjustable) {
|
||||
try container.encode("adjustable")
|
||||
}
|
||||
if self.contains(.allowsDirectInteraction) {
|
||||
try container.encode("allowsDirectInteraction")
|
||||
}
|
||||
if self.contains(.updatesFrequently) {
|
||||
try container.encode("updatesFrequently")
|
||||
}
|
||||
if self.contains(.causesPageTurn) {
|
||||
try container.encode("causesPageTurn")
|
||||
}
|
||||
if self.contains(.playsSound) {
|
||||
try container.encode("playsSound")
|
||||
}
|
||||
if self.contains(.startsMediaSession) {
|
||||
try container.encode("startsMediaSession")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,8 @@
|
||||
//
|
||||
|
||||
|
||||
public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -15,6 +16,10 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol {
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var buttons: TwoButtonViewModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody, buttons]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -25,6 +30,17 @@ public class HeadersH1ButtonModel: HeaderModel, MoleculeModelProtocol {
|
||||
super.init()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Subclass
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func setDefaults() {
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -20,6 +20,10 @@ public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol
|
||||
public var link: LinkModel
|
||||
public var buttons: TwoButtonViewModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headline, headline2, subHeadline, body, link, buttons]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -32,6 +36,17 @@ public class HeadersH1LandingPageHeaderModel: HeaderModel, MoleculeModelProtocol
|
||||
self.buttons = buttons
|
||||
super.init()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Subclass
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func setDefaults() {
|
||||
if headline.accessibilityTraits == nil {
|
||||
headline.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
|
||||
public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -16,6 +16,10 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
||||
public static var identifier: String = "headerH1"
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -25,6 +29,17 @@ public class HeadersH1NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
||||
super.init()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Subclass
|
||||
//--------------------------------------------------
|
||||
|
||||
public override func setDefaults() {
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +18,10 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol {
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var buttons: TwoButtonViewModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody, buttons]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -39,6 +43,9 @@ public class HeadersH2ButtonsModel: HeaderModel, MoleculeModelProtocol {
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = Padding.Component.VerticalMarginSpacing
|
||||
}
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -15,6 +15,10 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol {
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var caretLink: CaretLinkModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody, caretLink]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -34,6 +38,9 @@ public class HeadersH2CaretLinkModel: HeaderModel, MoleculeModelProtocol {
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = Padding.Component.VerticalMarginSpacing
|
||||
}
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -17,6 +17,10 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol {
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var link: LinkModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody, link]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -38,6 +42,9 @@ public class HeadersH2LinkModel: HeaderModel, MoleculeModelProtocol {
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = Padding.Component.VerticalMarginSpacing
|
||||
}
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -17,6 +17,10 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
||||
public static var identifier: String = "headerH2"
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -33,6 +37,9 @@ public class HeadersH2NoButtonsBodyTextModel: HeaderModel, MoleculeModelProtocol
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = Padding.Component.VerticalMarginSpacing
|
||||
}
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -21,6 +21,10 @@ public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol {
|
||||
public var body3: LabelModel
|
||||
public var subBody3: LabelModel?
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headline, body, subBody, body2, subBody2, body3, subBody3].compactMap({$0})
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -45,6 +49,9 @@ public class HeadersH2PricingTwoRowsModel: HeaderModel, MoleculeModelProtocol {
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = Padding.Component.VerticalMarginSpacing
|
||||
}
|
||||
if headline.accessibilityTraits == nil {
|
||||
headline.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
subBody?.attributes = [LabelAttributeStrikeThroughModel(0, subBody?.text.count ?? 0)]
|
||||
subBody2?.attributes = [LabelAttributeStrikeThroughModel(0, subBody2?.text.count ?? 0)]
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol {
|
||||
public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +18,10 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol {
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var button: ButtonModel
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headlineBody, button]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -39,6 +43,9 @@ public class HeadersH2TinyButtonModel: HeaderModel, MoleculeModelProtocol {
|
||||
if bottomPadding == nil {
|
||||
bottomPadding = Padding.Component.VerticalMarginSpacing
|
||||
}
|
||||
if headlineBody.headline?.accessibilityTraits == nil {
|
||||
headlineBody.headline?.accessibilityTraits = .header
|
||||
}
|
||||
super.setDefaults()
|
||||
button.style = .secondary
|
||||
button.size = .small
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
//
|
||||
// ListNotificationAuthModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Edayattu Salam, Nowfal on 13/04/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListNotificationAuthModel: ListOneColumnFullWidthTextAllTextAndLinksModel {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public class override var identifier: String { "listNotificationAuth" }
|
||||
public var enableStatus: String
|
||||
public var disableStatus: String
|
||||
public var enableAction: ActionModelProtocol?
|
||||
public var disableAction: ActionModelProtocol?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case enableStatus
|
||||
case disableStatus
|
||||
case enableAction
|
||||
case disableAction
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
enableStatus = try typeContainer.decode(String.self, forKey: .enableStatus)
|
||||
disableStatus = try typeContainer.decode(String.self, forKey: .disableStatus)
|
||||
enableAction = try typeContainer.decodeModelIfPresent(codingKey: .enableAction)
|
||||
disableAction = try typeContainer.decodeModelIfPresent(codingKey: .disableAction)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(enableStatus, forKey: .enableStatus)
|
||||
try container.encode(disableStatus, forKey: .disableStatus)
|
||||
try container.encodeModelIfPresent(enableAction, forKey: .enableAction)
|
||||
try container.encodeModelIfPresent(disableAction, forKey: .disableAction)
|
||||
}
|
||||
}
|
||||
|
||||
extension ListNotificationAuthModel: PageBehaviorProtocolRequirer {
|
||||
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||
[GetNotificationAuthStatusBehaviorModel()]
|
||||
}
|
||||
}
|
||||
|
||||
extension ListNotificationAuthModel: GetNotificationAuthStatusBehaviorConsumerProtocol {
|
||||
public func consume(notificationStatus: UNAuthorizationStatus) {
|
||||
if notificationStatus == .authorized {
|
||||
body?.text = enableStatus
|
||||
action = enableAction
|
||||
} else {
|
||||
body?.text = disableStatus
|
||||
action = disableAction
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,8 +13,7 @@ public class ListOneColumnFullWidthTextAllTextAndLinksModel: ListItemModel, Mole
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "list1CTxt"
|
||||
open class var identifier: String { "list1CTxt" }
|
||||
public var eyebrow: LabelModel?
|
||||
public var headline : LabelModel?
|
||||
public var subHeadline: LabelModel?
|
||||
|
||||
@ -13,6 +13,8 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol {
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "planNamesLockup"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var headline: LabelModel
|
||||
public var subHeadline: LabelModel
|
||||
@ -31,6 +33,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol {
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case headline
|
||||
@ -43,6 +46,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||
subHeadline = try typeContainer.decode(LabelModel.self, forKey: .subHeadline)
|
||||
@ -51,6 +55,7 @@ public class LockUpsPlanNamesModel: MoleculeModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(headline, forKey: .headline)
|
||||
|
||||
@ -14,6 +14,8 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "planLockup"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var planLabel : LabelModel
|
||||
public var headline : LabelModel
|
||||
@ -43,6 +45,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case planLabel
|
||||
@ -57,6 +60,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
planLabel = try typeContainer.decode(LabelModel.self, forKey: .planLabel)
|
||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||
@ -67,6 +71,7 @@ public class LockupsPlanSMLXLModel: MoleculeModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(planLabel, forKey: .planLabel)
|
||||
|
||||
@ -16,6 +16,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco
|
||||
|
||||
public static var identifier: String = "titleLockup"
|
||||
public var moleculeName: String = TitleLockupModel.identifier
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var eyebrow: LabelModel?
|
||||
public var title: LabelModel
|
||||
@ -130,6 +131,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case eyebrow
|
||||
@ -145,6 +147,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
title = try typeContainer.decodeMolecule(codingKey: .title)
|
||||
eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow)
|
||||
subTitle = try typeContainer.decodeMoleculeIfPresent(codingKey: .subTitle)
|
||||
@ -164,6 +167,7 @@ public class TitleLockupModel: MoleculeModelProtocol, ParentMoleculeModelProtoco
|
||||
|
||||
public 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(eyebrow, forKey: .eyebrow)
|
||||
try container.encodeModel(title, forKey: .title)
|
||||
|
||||
@ -84,5 +84,6 @@ import Foundation
|
||||
}
|
||||
|
||||
accessibilityLabel = message
|
||||
accessibilityTraits.update(with: .header)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, MoleculeModelProtocol {
|
||||
public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +18,10 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
|
||||
public var headline: LabelModel
|
||||
public var body: LabelModel?
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headline, body].compactMap({$0})
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -84,5 +84,6 @@ import Foundation
|
||||
}
|
||||
|
||||
accessibilityLabel = message
|
||||
accessibilityTraits.update(with: .header)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, MoleculeModelProtocol {
|
||||
public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +18,10 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
|
||||
public var headline: LabelModel
|
||||
public var body: LabelModel?
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headline, body].compactMap({$0})
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -84,5 +84,6 @@ import Foundation
|
||||
}
|
||||
|
||||
accessibilityLabel = message
|
||||
accessibilityTraits.update(with: .header)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, MoleculeModelProtocol {
|
||||
public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +18,10 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
|
||||
public var headline: LabelModel
|
||||
public var body: LabelModel?
|
||||
|
||||
public var children: [MoleculeModelProtocol] {
|
||||
[headline, body].compactMap({$0})
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -14,9 +14,11 @@ import Foundation
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public static var identifier: String = "doughnutChartItem"
|
||||
public var moleculeName: String = DoughnutChartItemModel.identifier
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var label: LabelModel
|
||||
@Percent public var percent: CGFloat
|
||||
public var color: Color
|
||||
|
||||
@ -14,9 +14,11 @@ import Foundation
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public static var identifier: String = "doughnutChart"
|
||||
public var moleculeName: String = DoughnutChartModel.identifier
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var title: LabelModel?
|
||||
public var subtitle: LabelModel?
|
||||
public var sections: [DoughnutChartItemModel]
|
||||
|
||||
@ -15,6 +15,8 @@ public class ImageHeadlineBodyModel: MoleculeModelProtocol {
|
||||
|
||||
public static var identifier: String = "imageHeadlineBody"
|
||||
public var moleculeName: String = ImageHeadlineBodyModel.identifier
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var image: ImageViewModel
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
@ -15,6 +15,8 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "radioButtonLabel"
|
||||
@DecodableDefault.UUIDString public var id: String
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var moleculeName: String = RadioButtonLabelModel.identifier
|
||||
public var radioButton: RadioButtonModel
|
||||
|
||||
@ -11,6 +11,8 @@ import VDSColorTokens
|
||||
|
||||
open class TabBarModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tabBar"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
open var tabs: [TabBarItemModel]
|
||||
|
||||
private var _backgroundColor: Color?
|
||||
@ -58,6 +60,7 @@ open class TabBarModel: MoleculeModelProtocol {
|
||||
open var selectedTab: Int = 0
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case tabs
|
||||
@ -73,6 +76,7 @@ open class TabBarModel: MoleculeModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
tabs = try typeContainer.decode([TabBarItemModel].self, forKey: .tabs)
|
||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
||||
backgroundColor = color
|
||||
@ -93,6 +97,7 @@ open class TabBarModel: MoleculeModelProtocol {
|
||||
|
||||
open 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.encode(tabs, forKey: .tabs)
|
||||
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -51,7 +51,7 @@ import VDSColorTokens
|
||||
public let selectionLineMovingTime: TimeInterval = 0.2
|
||||
|
||||
//-------------------------------------------------
|
||||
// MARK:- Layout Views
|
||||
// MARK: - Layout Views
|
||||
//-------------------------------------------------
|
||||
|
||||
open override func reset() {
|
||||
@ -122,8 +122,27 @@ import VDSColorTokens
|
||||
NSLayoutConstraint.constraintPinSubview(bottomLine, pinTop: false, pinBottom: true, pinLeft: true, pinRight: true)
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
// Accounts for any collection size changes
|
||||
DispatchQueue.main.async {
|
||||
self.layoutCollection()
|
||||
}
|
||||
}
|
||||
|
||||
/// Invalidates the layout and ensures we are paged to the correct cell.
|
||||
open func layoutCollection() {
|
||||
collectionView?.collectionViewLayout.invalidateLayout()
|
||||
|
||||
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView?.scrollToItem(at: IndexPath(row: self.selectedIndex, section: 0), at: .left, animated: false)
|
||||
self.collectionView?.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// MARK:- Control Methods
|
||||
// MARK: - Control Methods
|
||||
//-------------------------------------------------
|
||||
|
||||
public func selectIndex(_ index: Int, animated: Bool) {
|
||||
@ -146,7 +165,7 @@ import VDSColorTokens
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// MARK:- Molecule Setup
|
||||
// MARK: - Molecule Setup
|
||||
//-------------------------------------------------
|
||||
|
||||
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
@ -163,7 +182,7 @@ import VDSColorTokens
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// MARK:- Collection View Methods
|
||||
// MARK: - Collection View Methods
|
||||
//-------------------------------------------------
|
||||
|
||||
extension Tabs: UICollectionViewDataSource {
|
||||
@ -235,7 +254,9 @@ extension Tabs: UICollectionViewDelegateFlowLayout {
|
||||
public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
|
||||
guard let tabCell = cell as? TabItemCell else { return }
|
||||
if indexPath.row == selectedIndex {
|
||||
moveSelectionLine(toIndex: indexPath, animated: false, cell: tabCell)
|
||||
DispatchQueue.main.async {
|
||||
self.moveSelectionLine(toIndex: indexPath, animated: false, cell: tabCell)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,7 +302,7 @@ extension Tabs: UIScrollViewDelegate {
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// MARK:- Bottom Line Methods
|
||||
// MARK: - Bottom Line Methods
|
||||
//-------------------------------------------------
|
||||
extension Tabs {
|
||||
func moveSelectionLine(toIndex indexPath: IndexPath, animated: Bool, cell: TabItemCell) {
|
||||
|
||||
@ -11,6 +11,8 @@ import VDSColorTokens
|
||||
|
||||
open class TabsModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "tabs"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
open var tabs: [TabItemModel]
|
||||
|
||||
open var style: NavigationItemStyle?
|
||||
@ -71,6 +73,7 @@ open class TabsModel: MoleculeModelProtocol {
|
||||
open var selectedIndex: Int = 0
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case tabs
|
||||
case backgroundColor
|
||||
@ -87,6 +90,7 @@ open class TabsModel: MoleculeModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs)
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
_selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor)
|
||||
@ -100,6 +104,7 @@ open class TabsModel: MoleculeModelProtocol {
|
||||
|
||||
open 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.encode(tabs, forKey: .tabs)
|
||||
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
|
||||
|
||||
@ -15,6 +15,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "twoButtonView"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
public var primaryButton: ButtonModel?
|
||||
public var secondaryButton: ButtonModel?
|
||||
@ -28,6 +29,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case primaryButton
|
||||
@ -49,6 +51,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
|
||||
//set context value for 'primary' style to be set for the primaryButton in case the
|
||||
@ -66,6 +69,7 @@ public class TwoButtonViewModel: ParentMoleculeModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(primaryButton, forKey: .primaryButton)
|
||||
|
||||
@ -10,11 +10,14 @@ import Foundation
|
||||
|
||||
public class TwoLinkViewModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "twoLinkView"
|
||||
public var id: String = UUID().uuidString
|
||||
|
||||
public var backgroundColor: Color?
|
||||
public var rightLink: LinkModel?
|
||||
public var leftLink: LinkModel?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case rightLink
|
||||
@ -28,6 +31,7 @@ public class TwoLinkViewModel: MoleculeModelProtocol {
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
rightLink = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .rightLink)
|
||||
leftLink = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .leftLink)
|
||||
@ -35,6 +39,7 @@ public class TwoLinkViewModel: MoleculeModelProtocol {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(rightLink, forKey: .rightLink)
|
||||
|
||||
@ -22,7 +22,8 @@ open class CarouselItem: MoleculeCollectionViewCell, CarouselItemProtocol {
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
clipsToBounds = true
|
||||
|
||||
// Covers the card when peaking.
|
||||
peakingCover.backgroundColor = .white
|
||||
peakingCover.alpha = 0
|
||||
@ -51,6 +52,12 @@ open class CarouselItem: MoleculeCollectionViewCell, CarouselItemProtocol {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let collectionModel = model as? CarouselItemModel else { return }
|
||||
|
||||
if let cornerRadius = (model as? ContainerModel)?.cornerRadius {
|
||||
layer.cornerRadius = cornerRadius
|
||||
} else {
|
||||
layer.cornerRadius = 0
|
||||
}
|
||||
|
||||
// Handles peaking.
|
||||
allowsPeaking = collectionModel.peakingUI ?? false
|
||||
if let peakingArrowColor = collectionModel.peakingArrowColor {
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
open override class var identifier: String { "collectionItem" }
|
||||
|
||||
public var action: ActionModelProtocol?
|
||||
public var border = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -23,6 +24,7 @@
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case action
|
||||
case border
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -59,12 +61,16 @@
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
if let border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border) {
|
||||
self.border = border
|
||||
}
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try container.encodeIfPresent(border, forKey: .border)
|
||||
try super.encode(to: encoder)
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,13 @@ open class MoleculeCollectionViewCell: CollectionViewCell {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let collectionModel = model as? MoleculeCollectionItemModel else { return }
|
||||
|
||||
if collectionModel.border {
|
||||
contentView.layer.borderColor = UIColor.black.cgColor
|
||||
contentView.layer.borderWidth = 1
|
||||
} else {
|
||||
contentView.layer.borderWidth = 0
|
||||
}
|
||||
|
||||
if molecule == nil {
|
||||
if let moleculeView = ModelRegistry.createMolecule(collectionModel.molecule, delegateObject: delegateObject, additionalData: additionalData) {
|
||||
addMolecule(moleculeView)
|
||||
|
||||
@ -47,6 +47,7 @@ import UIKit
|
||||
public override func reset() {
|
||||
super.reset()
|
||||
tabs.reset()
|
||||
tabs.paddingBeforeFirstTab = false
|
||||
}
|
||||
|
||||
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 46 }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user