merging
This commit is contained in:
commit
24ed53366b
@ -236,6 +236,8 @@
|
|||||||
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */; };
|
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */; };
|
||||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
||||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
||||||
|
AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA7CD68250641F90045B959 /* HeartModel.swift */; };
|
||||||
|
AAA7CD6B250642080045B959 /* Heart.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA7CD6A250642080045B959 /* Heart.swift */; };
|
||||||
AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA905DE24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift */; };
|
AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA905DE24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift */; };
|
||||||
AAA905E124D1759A00D1EFAB /* ListThreeColumnBillHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA905E024D1759A00D1EFAB /* ListThreeColumnBillHistory.swift */; };
|
AAA905E124D1759A00D1EFAB /* ListThreeColumnBillHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA905E024D1759A00D1EFAB /* ListThreeColumnBillHistory.swift */; };
|
||||||
AAB7EDEF246ADA1600E54929 /* ListProgressBarThinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */; };
|
AAB7EDEF246ADA1600E54929 /* ListProgressBarThinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */; };
|
||||||
@ -303,8 +305,12 @@
|
|||||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||||
D20C7009250BF99B0095B21C /* TopNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C7008250BF99B0095B21C /* TopNotificationModel.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 */; };
|
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */; };
|
||||||
|
D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20F3B43252E00E4004B3F56 /* PageProtocol.swift */; };
|
||||||
|
D20F3B5E252F9B5E004B3F56 /* NavigationBarRefreshProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20F3B5D252F9B5D004B3F56 /* NavigationBarRefreshProtocol.swift */; };
|
||||||
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; };
|
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; };
|
||||||
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
||||||
|
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2169300251E51E7002A6324 /* SectionListTemplate.swift */; };
|
||||||
|
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */; };
|
||||||
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; };
|
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; };
|
||||||
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; };
|
D21B7F71243BAC1600051ABF /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */; };
|
||||||
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; };
|
D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */; };
|
||||||
@ -465,6 +471,10 @@
|
|||||||
D2CAC7CF2511052300C75681 /* CollapsableNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.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 */; };
|
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 */; };
|
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 */; };
|
||||||
|
D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D3957C252FDBCD00047B11 /* ModalSectionListTemplateModel.swift */; };
|
||||||
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
|
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */; };
|
||||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
|
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
|
||||||
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; };
|
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; };
|
||||||
@ -482,6 +492,9 @@
|
|||||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; };
|
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A99E23E07F8A000B42E6 /* PillButton.swift */; };
|
||||||
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; };
|
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */; };
|
||||||
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; };
|
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */; };
|
||||||
|
D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */; };
|
||||||
|
D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */; };
|
||||||
|
D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */; };
|
||||||
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; };
|
D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; };
|
||||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; };
|
||||||
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */; };
|
D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */; };
|
||||||
@ -729,6 +742,8 @@
|
|||||||
AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconAllTextLinks.swift; sourceTree = "<group>"; };
|
AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconAllTextLinks.swift; sourceTree = "<group>"; };
|
||||||
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
||||||
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
||||||
|
AAA7CD68250641F90045B959 /* HeartModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeartModel.swift; sourceTree = "<group>"; };
|
||||||
|
AAA7CD6A250642080045B959 /* Heart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Heart.swift; sourceTree = "<group>"; };
|
||||||
AAA905DE24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnBillHistoryModel.swift; sourceTree = "<group>"; };
|
AAA905DE24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnBillHistoryModel.swift; sourceTree = "<group>"; };
|
||||||
AAA905E024D1759A00D1EFAB /* ListThreeColumnBillHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnBillHistory.swift; sourceTree = "<group>"; };
|
AAA905E024D1759A00D1EFAB /* ListThreeColumnBillHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnBillHistory.swift; sourceTree = "<group>"; };
|
||||||
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThinModel.swift; sourceTree = "<group>"; };
|
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThinModel.swift; sourceTree = "<group>"; };
|
||||||
@ -796,8 +811,12 @@
|
|||||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.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>"; };
|
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>"; };
|
D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertView+Extension.swift"; sourceTree = "<group>"; };
|
||||||
|
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
D20F3B5D252F9B5D004B3F56 /* NavigationBarRefreshProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarRefreshProtocol.swift; sourceTree = "<group>"; };
|
||||||
D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModel.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>"; };
|
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||||
|
D2169300251E51E7002A6324 /* SectionListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionListTemplate.swift; sourceTree = "<group>"; };
|
||||||
|
D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionListTemplateModel.swift; sourceTree = "<group>"; };
|
||||||
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
|
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
|
||||||
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; };
|
D21B7F70243BAC1600051ABF /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; };
|
D21B7F72243BAC6800051ABF /* CollectionItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
@ -960,6 +979,10 @@
|
|||||||
D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationModel.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>"; };
|
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>"; };
|
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>"; };
|
||||||
|
D2D3957C252FDBCD00047B11 /* ModalSectionListTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalSectionListTemplateModel.swift; sourceTree = "<group>"; };
|
||||||
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; };
|
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scroller.swift; sourceTree = "<group>"; };
|
||||||
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
|
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
|
||||||
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = "<group>"; };
|
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = "<group>"; };
|
||||||
@ -976,6 +999,9 @@
|
|||||||
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
|
D2E2A99E23E07F8A000B42E6 /* PillButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButton.swift; sourceTree = "<group>"; };
|
||||||
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = "<group>"; };
|
D2E2A9A023E095AB000B42E6 /* ButtonModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; };
|
D2E2A9A223E096B1000B42E6 /* DisableableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableableModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeaderModel.swift; sourceTree = "<group>"; };
|
||||||
|
D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionHeader.swift; sourceTree = "<group>"; };
|
||||||
|
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderFooterView.swift; sourceTree = "<group>"; };
|
||||||
D2FA83D12513EA6900564112 /* NotificationXButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButton.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>"; };
|
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>"; };
|
D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationTopView.swift; sourceTree = "<group>"; };
|
||||||
@ -1589,6 +1615,8 @@
|
|||||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
|
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
|
||||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
|
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
|
||||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
|
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
|
||||||
|
AAA7CD68250641F90045B959 /* HeartModel.swift */,
|
||||||
|
AAA7CD6A250642080045B959 /* Heart.swift */,
|
||||||
);
|
);
|
||||||
path = Selectors;
|
path = Selectors;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1691,6 +1719,10 @@
|
|||||||
D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */,
|
D264FAA4243F66A500D98315 /* CollectionTemplateItemProtocol.swift */,
|
||||||
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */,
|
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */,
|
||||||
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */,
|
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */,
|
||||||
|
D2169302251E53D9002A6324 /* SectionListTemplateModel.swift */,
|
||||||
|
D2169300251E51E7002A6324 /* SectionListTemplate.swift */,
|
||||||
|
D2D3957C252FDBCD00047B11 /* ModalSectionListTemplateModel.swift */,
|
||||||
|
D2D39579252FDBB300047B11 /* ModalSectionListTemplate.swift */,
|
||||||
);
|
);
|
||||||
path = Templates;
|
path = Templates;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1718,6 +1750,7 @@
|
|||||||
D29DF10E21E67A77003B2FB9 /* Molecules */ = {
|
D29DF10E21E67A77003B2FB9 /* Molecules */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D2EC7BD22527A1E400F540AF /* HeadersAndFooters */,
|
||||||
D2CAC7C9251104CB00C75681 /* TopNotification */,
|
D2CAC7C9251104CB00C75681 /* TopNotification */,
|
||||||
D2509ED42472EE0B001BFB9D /* NavigationBar */,
|
D2509ED42472EE0B001BFB9D /* NavigationBar */,
|
||||||
D253BB9A24587023002DE544 /* OtherContainers */,
|
D253BB9A24587023002DE544 /* OtherContainers */,
|
||||||
@ -1726,12 +1759,6 @@
|
|||||||
D224798F2316A99F003FCCF9 /* LeftRightViews */,
|
D224798F2316A99F003FCCF9 /* LeftRightViews */,
|
||||||
D224798E2316A995003FCCF9 /* HorizontalCombinationViews */,
|
D224798E2316A995003FCCF9 /* HorizontalCombinationViews */,
|
||||||
D224798D2316A988003FCCF9 /* VerticalCombinationViews */,
|
D224798D2316A988003FCCF9 /* VerticalCombinationViews */,
|
||||||
01EB368C23609801006832FA /* HeaderModel.swift */,
|
|
||||||
D256E9922412880000360572 /* Header.swift */,
|
|
||||||
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */,
|
|
||||||
D2A514662213885800345BFB /* MoleculeHeaderView.swift */,
|
|
||||||
012A88EB238F084D00FE3DA1 /* FooterModel.swift */,
|
|
||||||
D274CA322236A78900B01B62 /* FooterView.swift */,
|
|
||||||
D260105723CF9CC500764D80 /* Doughnut */,
|
D260105723CF9CC500764D80 /* Doughnut */,
|
||||||
);
|
);
|
||||||
path = Molecules;
|
path = Molecules;
|
||||||
@ -2033,6 +2060,7 @@
|
|||||||
0A5D59C323AD488600EFD9E9 /* Protocols */,
|
0A5D59C323AD488600EFD9E9 /* Protocols */,
|
||||||
0A7918F423F5E7EA00772FF4 /* ImageView.swift */,
|
0A7918F423F5E7EA00772FF4 /* ImageView.swift */,
|
||||||
D272F5F82473163100BD1A8F /* BarButtonItem.swift */,
|
D272F5F82473163100BD1A8F /* BarButtonItem.swift */,
|
||||||
|
D2EC7BDC2527B83700F540AF /* SectionHeaderFooterView.swift */,
|
||||||
);
|
);
|
||||||
path = BaseClasses;
|
path = BaseClasses;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2077,8 +2105,10 @@
|
|||||||
children = (
|
children = (
|
||||||
012A88C7238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift */,
|
012A88C7238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift */,
|
||||||
017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */,
|
017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */,
|
||||||
|
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */,
|
||||||
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
|
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
|
||||||
D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */,
|
D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */,
|
||||||
|
D20F3B5D252F9B5D004B3F56 /* NavigationBarRefreshProtocol.swift */,
|
||||||
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
||||||
);
|
);
|
||||||
path = Protocols;
|
path = Protocols;
|
||||||
@ -2100,6 +2130,23 @@
|
|||||||
path = TopNotification;
|
path = TopNotification;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D2EC7BD22527A1E400F540AF /* HeadersAndFooters */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
01EB368C23609801006832FA /* HeaderModel.swift */,
|
||||||
|
D256E9922412880000360572 /* Header.swift */,
|
||||||
|
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */,
|
||||||
|
D2A514662213885800345BFB /* MoleculeHeaderView.swift */,
|
||||||
|
012A88EB238F084D00FE3DA1 /* FooterModel.swift */,
|
||||||
|
D274CA322236A78900B01B62 /* FooterView.swift */,
|
||||||
|
D2EC7BD42527B7A600F540AF /* MoleculeSectionHeaderModel.swift */,
|
||||||
|
D2EC7BD82527B7CF00F540AF /* MoleculeSectionHeader.swift */,
|
||||||
|
D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */,
|
||||||
|
D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */,
|
||||||
|
);
|
||||||
|
path = HeadersAndFooters;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXHeadersBuildPhase section */
|
/* Begin PBXHeadersBuildPhase section */
|
||||||
@ -2231,6 +2278,7 @@
|
|||||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */,
|
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */,
|
||||||
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
|
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
|
||||||
8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */,
|
8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */,
|
||||||
|
AAA7CD6B250642080045B959 /* Heart.swift in Sources */,
|
||||||
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
|
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
|
||||||
D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */,
|
D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */,
|
||||||
D2509ED62472EE2F001BFB9D /* NavigationImageButtonModel.swift in Sources */,
|
D2509ED62472EE2F001BFB9D /* NavigationImageButtonModel.swift in Sources */,
|
||||||
@ -2250,9 +2298,11 @@
|
|||||||
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
|
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
|
||||||
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
|
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
|
||||||
3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */,
|
3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */,
|
||||||
|
AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */,
|
||||||
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */,
|
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */,
|
||||||
D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */,
|
D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */,
|
||||||
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
|
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
|
||||||
|
D2EC7BD92527B7CF00F540AF /* MoleculeSectionHeader.swift in Sources */,
|
||||||
D28764AA2458980300CB882D /* ThreeLayerFillMiddleTemplate.swift in Sources */,
|
D28764AA2458980300CB882D /* ThreeLayerFillMiddleTemplate.swift in Sources */,
|
||||||
0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */,
|
0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */,
|
||||||
D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */,
|
D2092353244F7D630044AD09 /* MVMCoreUIViewControllerMappingObject+Extension.swift in Sources */,
|
||||||
@ -2268,6 +2318,7 @@
|
|||||||
AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */,
|
AA2AD116244EE46800BBFFE3 /* ListDeviceComplexLinkMedium.swift in Sources */,
|
||||||
AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */,
|
AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */,
|
||||||
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */,
|
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */,
|
||||||
|
D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */,
|
||||||
0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */,
|
0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */,
|
||||||
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
|
D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */,
|
||||||
01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
|
01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
|
||||||
@ -2345,6 +2396,7 @@
|
|||||||
525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */,
|
525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */,
|
||||||
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
|
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
|
||||||
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */,
|
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */,
|
||||||
|
D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */,
|
||||||
8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */,
|
8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */,
|
||||||
94C0150C2421564A005811A9 /* ActionCollapseNotificationModel.swift in Sources */,
|
94C0150C2421564A005811A9 /* ActionCollapseNotificationModel.swift in Sources */,
|
||||||
D2CAC7CB251104E100C75681 /* NotificationXButtonModel.swift in Sources */,
|
D2CAC7CB251104E100C75681 /* NotificationXButtonModel.swift in Sources */,
|
||||||
@ -2422,11 +2474,13 @@
|
|||||||
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
|
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
|
||||||
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
|
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
|
||||||
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */,
|
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */,
|
||||||
|
D2EC7BD52527B7A600F540AF /* MoleculeSectionHeaderModel.swift in Sources */,
|
||||||
AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */,
|
AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */,
|
||||||
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
|
||||||
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
|
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
|
||||||
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
|
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
|
||||||
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */,
|
0A9D09222433796500D2E6C0 /* CarouselIndicator.swift in Sources */,
|
||||||
|
D20F3B5E252F9B5E004B3F56 /* NavigationBarRefreshProtocol.swift in Sources */,
|
||||||
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */,
|
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */,
|
||||||
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
|
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
|
||||||
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
|
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
|
||||||
@ -2434,6 +2488,7 @@
|
|||||||
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
|
D2092349244A51D40044AD09 /* RadioSwatchModel.swift in Sources */,
|
||||||
0A775F2824893937009EFB58 /* ThreeHeadlineBodyLinkModel.swift in Sources */,
|
0A775F2824893937009EFB58 /* ThreeHeadlineBodyLinkModel.swift in Sources */,
|
||||||
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
|
8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */,
|
||||||
|
D2EC7BDD2527B83700F540AF /* SectionHeaderFooterView.swift in Sources */,
|
||||||
D23EA802247EBED400D60C34 /* ImageBarButtonItem.swift in Sources */,
|
D23EA802247EBED400D60C34 /* ImageBarButtonItem.swift in Sources */,
|
||||||
AA45AA0B24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift in Sources */,
|
AA45AA0B24BF0263007A6EA7 /* LockUpsPlanNamesModel.swift in Sources */,
|
||||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
|
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
|
||||||
@ -2526,6 +2581,7 @@
|
|||||||
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
|
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
|
||||||
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */,
|
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */,
|
||||||
AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */,
|
AA2AD118244EE48C00BBFFE3 /* ListDeviceComplexLinkMediumModel.swift in Sources */,
|
||||||
|
D2D3957A252FDBB300047B11 /* ModalSectionListTemplate.swift in Sources */,
|
||||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
|
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
|
||||||
D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */,
|
D28BA741248025A300B75CB8 /* TabBarModel.swift in Sources */,
|
||||||
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
|
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
|
||||||
@ -2540,6 +2596,7 @@
|
|||||||
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
|
D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */,
|
||||||
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
|
0AE14F64238315D2005417F8 /* TextField.swift in Sources */,
|
||||||
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
|
0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */,
|
||||||
|
D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */,
|
||||||
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
|
0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */,
|
||||||
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
|
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */,
|
||||||
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */,
|
D253BB9C245874F8002DE544 /* BGImageMolecule.swift in Sources */,
|
||||||
@ -2623,6 +2680,7 @@
|
|||||||
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
|
AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */,
|
||||||
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
|
||||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||||
|
D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */,
|
||||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */,
|
||||||
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */,
|
D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */,
|
||||||
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
|
||||||
@ -2636,6 +2694,7 @@
|
|||||||
D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */,
|
D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */,
|
||||||
BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */,
|
BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */,
|
||||||
C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */,
|
C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */,
|
||||||
|
D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */,
|
||||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
||||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
||||||
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
|
012A88C2238D7BCA00FE3DA1 /* CarouselItemModel.swift in Sources */,
|
||||||
@ -2665,6 +2724,7 @@
|
|||||||
AA0A257A24766CA200862F64 /* ListLeftVariableIconWithRightCaretBodyText.swift in Sources */,
|
AA0A257A24766CA200862F64 /* ListLeftVariableIconWithRightCaretBodyText.swift in Sources */,
|
||||||
011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */,
|
011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */,
|
||||||
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */,
|
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */,
|
||||||
|
D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */,
|
||||||
0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */,
|
0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */,
|
||||||
D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */,
|
D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|||||||
114
MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift
Normal file
114
MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
//
|
||||||
|
// Heart.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Lekshmi S on 07/09/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objcMembers open class Heart: Control, MFButtonProtocol {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
private var heartLayer: CAShapeLayer?
|
||||||
|
@objc public override var isSelected: Bool {
|
||||||
|
didSet {
|
||||||
|
heartModel?.isActive = isSelected
|
||||||
|
updateAccessibilityLabel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
public var heartModel: HeartModel? {
|
||||||
|
return model as? HeartModel
|
||||||
|
}
|
||||||
|
var additionalData: [AnyHashable: Any]?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Constraints
|
||||||
|
//--------------------------------------------------
|
||||||
|
public var widthConstraint: NSLayoutConstraint?
|
||||||
|
public var heightConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// MARK: - State Handling
|
||||||
|
//------------------------------------------------------
|
||||||
|
open override func draw(_ rect: CGRect) {
|
||||||
|
//Draw the heart
|
||||||
|
heartLayer?.removeFromSuperlayer()
|
||||||
|
let heart = drawHeart()
|
||||||
|
layer.addSublayer(heart)
|
||||||
|
heartLayer = heart
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawHeart() -> CAShapeLayer {
|
||||||
|
let heart = CAShapeLayer()
|
||||||
|
let rect = bounds
|
||||||
|
let leftArc = rect.width * 0.4
|
||||||
|
let rightArc = rect.height * 0.3
|
||||||
|
let arcRadius = sqrt(leftArc*leftArc + rightArc*rightArc)/2
|
||||||
|
let heartPath = UIBezierPath()
|
||||||
|
//Left Hand Curve
|
||||||
|
heartPath.addArc(withCenter: CGPoint(x: rect.width * 0.3, y: rect.height * 0.35), radius: arcRadius, startAngle: 135.degreesToRadians, endAngle: 315.degreesToRadians, clockwise: true)
|
||||||
|
//Top Centre Dip
|
||||||
|
heartPath.addLine(to: CGPoint(x: rect.width/2, y: rect.height * 0.2))
|
||||||
|
//Right Hand Curve
|
||||||
|
heartPath.addArc(withCenter: CGPoint(x: rect.width * 0.7, y: rect.height * 0.35), radius: arcRadius, startAngle: 225.degreesToRadians, endAngle: 45.degreesToRadians, clockwise: true)
|
||||||
|
//Right Bottom Line
|
||||||
|
heartPath.addLine(to: CGPoint(x: rect.width * 0.5, y: rect.height * 0.95))
|
||||||
|
//Left Bottom Line
|
||||||
|
heartPath.close()
|
||||||
|
heart.path = heartPath.cgPath
|
||||||
|
heart.fillColor = isSelected ? heartModel?.activeColor.cgColor : heartModel?.inActiveColor.cgColor
|
||||||
|
heart.opacity = 1.0
|
||||||
|
heart.lineWidth = 1
|
||||||
|
heart.strokeColor = isSelected ? UIColor.clear.cgColor : UIColor.mvmBlack.cgColor
|
||||||
|
return heart
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
//--------------------------------------------------
|
||||||
|
open override func setupView() {
|
||||||
|
super.setupView()
|
||||||
|
addTarget(self, action: #selector(tapAction), for: .touchUpInside)
|
||||||
|
widthConstraint = widthAnchor.constraint(equalToConstant: 22)
|
||||||
|
widthConstraint?.isActive = true
|
||||||
|
heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
|
||||||
|
heightConstraint?.isActive = true
|
||||||
|
isAccessibilityElement = true
|
||||||
|
accessibilityTraits = .button
|
||||||
|
updateAccessibilityLabel()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
self.delegateObject = delegateObject
|
||||||
|
self.additionalData = additionalData
|
||||||
|
guard let model = model as? HeartModel else { return }
|
||||||
|
isSelected = model.isActive
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
/// Adjust accessibility label based on selection of Heart.
|
||||||
|
func updateAccessibilityLabel() {
|
||||||
|
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_unfavorite_action_hint" : "heart_favorite_action_hint")
|
||||||
|
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_selected_state" : "heart_not_selected_state")
|
||||||
|
}
|
||||||
|
|
||||||
|
func tapAction() {
|
||||||
|
isSelected = !isSelected
|
||||||
|
if let heartModel = heartModel {
|
||||||
|
Button.performButtonAction(with: heartModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: heartModel)
|
||||||
|
}
|
||||||
|
setNeedsDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Int {
|
||||||
|
var degreesToRadians: CGFloat { return CGFloat(self) * .pi / 180 }
|
||||||
|
}
|
||||||
65
MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift
Normal file
65
MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// HeartModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Lekshmi S on 07/09/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
open class HeartModel: MoleculeModelProtocol {
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
public static var identifier: String = "heart"
|
||||||
|
public var backgroundColor: Color?
|
||||||
|
public var isActive: Bool = false
|
||||||
|
public var activeColor: Color = Color(uiColor: .mvmRed)
|
||||||
|
public var inActiveColor: Color = Color(uiColor: .clear)
|
||||||
|
public var action: ActionModelProtocol = ActionNoopModel()
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case moleculeName
|
||||||
|
case backgroundColor
|
||||||
|
case isActive
|
||||||
|
case activeColor
|
||||||
|
case inActiveColor
|
||||||
|
case action
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if let isActive = try typeContainer.decodeIfPresent(Bool.self, forKey: .isActive) {
|
||||||
|
self.isActive = isActive
|
||||||
|
}
|
||||||
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
|
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
|
||||||
|
self.activeColor = activeColor
|
||||||
|
}
|
||||||
|
if let inActiveColor = try typeContainer.decodeIfPresent(Color.self, forKey: .inActiveColor) {
|
||||||
|
self.inActiveColor = inActiveColor
|
||||||
|
}
|
||||||
|
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
|
try container.encode(isActive, forKey: .isActive)
|
||||||
|
try container.encode(activeColor, forKey: .activeColor)
|
||||||
|
try container.encode(inActiveColor, forKey: .inActiveColor)
|
||||||
|
try container.encodeModel(action, forKey: .action)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -322,8 +322,11 @@ public typealias ActionBlock = () -> ()
|
|||||||
for attribute in attributes {
|
for attribute in attributes {
|
||||||
let range = NSRange(location: attribute.location, length: attribute.length)
|
let range = NSRange(location: attribute.location, length: attribute.length)
|
||||||
switch attribute {
|
switch attribute {
|
||||||
case _ as LabelAttributeUnderlineModel:
|
case let underlineAtt as LabelAttributeUnderlineModel:
|
||||||
attributedString.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range)
|
attributedString.addAttribute(.underlineStyle, value: underlineAtt.underlineValue.rawValue, range: range)
|
||||||
|
if let underlineColor = underlineAtt.color?.uiColor {
|
||||||
|
attributedString.addAttribute(.underlineColor, value: underlineColor, range: range)
|
||||||
|
}
|
||||||
|
|
||||||
case _ as LabelAttributeStrikeThroughModel:
|
case _ as LabelAttributeStrikeThroughModel:
|
||||||
attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range)
|
attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range)
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
@objcMembers public class LabelAttributeUnderlineModel: LabelAttributeModel {
|
@objcMembers public class LabelAttributeUnderlineModel: LabelAttributeModel {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -16,15 +18,104 @@
|
|||||||
return "underline"
|
return "underline"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This returns the NSUnderlineStyle used in NSAttributedValue. If there is a pattern, it will return
|
||||||
|
/// a new NSUnderlineStyle derived from the bitmask of style | pattern.
|
||||||
|
var underlineValue: NSUnderlineStyle {
|
||||||
|
|
||||||
|
if let pattern = pattern?.value() {
|
||||||
|
return NSUnderlineStyle(rawValue: style.value() | pattern)
|
||||||
|
} else {
|
||||||
|
return NSUnderlineStyle(rawValue: style.value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var color: Color?
|
||||||
|
var style: UnderlineStyle = .single
|
||||||
|
var pattern: UnderlineStyle.Pattern?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Codec
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case color
|
||||||
|
case style
|
||||||
|
case pattern
|
||||||
|
}
|
||||||
|
|
||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) {
|
||||||
|
self.color = color
|
||||||
|
}
|
||||||
|
|
||||||
|
if let style = try typeContainer.decodeIfPresent(UnderlineStyle.self, forKey: .style) {
|
||||||
|
self.style = style
|
||||||
|
}
|
||||||
|
|
||||||
|
if let pattern = try typeContainer.decodeIfPresent(UnderlineStyle.Pattern.self, forKey: .pattern) {
|
||||||
|
self.pattern = pattern
|
||||||
|
}
|
||||||
|
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func encode(to encoder: Encoder) throws {
|
public override func encode(to encoder: Encoder) throws {
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encodeIfPresent(color, forKey: .color)
|
||||||
|
try container.encode(style, forKey: .style)
|
||||||
|
try container.encodeIfPresent(pattern, forKey: .pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum UnderlineStyle: String, Codable {
|
||||||
|
case none
|
||||||
|
case single
|
||||||
|
case thick
|
||||||
|
case double
|
||||||
|
|
||||||
|
func value() -> Int {
|
||||||
|
switch self {
|
||||||
|
case .none:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
case .single:
|
||||||
|
return NSUnderlineStyle.single.rawValue
|
||||||
|
|
||||||
|
case .thick:
|
||||||
|
return NSUnderlineStyle.thick.rawValue
|
||||||
|
|
||||||
|
case .double:
|
||||||
|
return NSUnderlineStyle.double.rawValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Pattern: String, Codable {
|
||||||
|
case dot
|
||||||
|
case dash
|
||||||
|
case dashDot
|
||||||
|
case dashDotDot
|
||||||
|
case byWord
|
||||||
|
|
||||||
|
func value() -> Int {
|
||||||
|
switch self {
|
||||||
|
case .dot:
|
||||||
|
return NSUnderlineStyle.patternDot.rawValue
|
||||||
|
|
||||||
|
case .dash:
|
||||||
|
return NSUnderlineStyle.patternDash.rawValue
|
||||||
|
|
||||||
|
case .dashDot:
|
||||||
|
return NSUnderlineStyle.patternDashDot.rawValue
|
||||||
|
|
||||||
|
case .dashDotDot:
|
||||||
|
return NSUnderlineStyle.patternDashDotDot.rawValue
|
||||||
|
|
||||||
|
case .byWord:
|
||||||
|
return NSUnderlineStyle.byWord.rawValue
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,12 +35,12 @@ import Foundation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience function for legacy classes
|
/// Convenience function for legacy classes
|
||||||
public func getMoleculeModelForJSON(_ json: [String: Any]) throws -> MoleculeModelProtocol? {
|
public func getMoleculeModelForJSON(_ json: [String: Any], delegateObject: DelegateObject? = nil) throws -> MoleculeModelProtocol? {
|
||||||
guard let moleculeName = json.optionalStringForKey(KeyMoleculeName),
|
guard let moleculeName = json.optionalStringForKey(KeyMoleculeName),
|
||||||
let type = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) else {
|
let type = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) else {
|
||||||
throw ModelRegistry.Error.decoderErrorModelNotMapped()
|
throw ModelRegistry.Error.decoderErrorModelNotMapped()
|
||||||
}
|
}
|
||||||
guard let model = try type.decode(jsonDict: json) as? MoleculeModelProtocol else {
|
guard let model = try type.decode(jsonDict: json, delegateObject: delegateObject) as? MoleculeModelProtocol else {
|
||||||
throw ModelRegistry.Error.decoderError
|
throw ModelRegistry.Error.decoderError
|
||||||
}
|
}
|
||||||
return model
|
return model
|
||||||
@ -87,7 +87,7 @@ import Foundation
|
|||||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: Tags.self, viewModelClass: TagsModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: Tags.self, viewModelClass: TagsModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: Tag.self, viewModelClass: TagModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: Tag.self, viewModelClass: TagModel.self)
|
||||||
|
MoleculeObjectMapping.shared()?.register(viewClass: Heart.self, viewModelClass: HeartModel.self)
|
||||||
|
|
||||||
|
|
||||||
// MARK:- Other Atoms
|
// MARK:- Other Atoms
|
||||||
@ -149,6 +149,9 @@ import Foundation
|
|||||||
MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: Scroller.self, viewModelClass: ScrollerModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: ModuleMolecule.self, viewModelClass: ModuleMoleculeModel.self)
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: BGImageMolecule.self, viewModelClass: BGImageMoleculeModel.self)
|
||||||
|
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeSectionHeader.self, viewModelClass: MoleculeSectionHeaderModel.self)
|
||||||
|
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeSectionFooter.self, viewModelClass: MoleculeSectionFooterModel.self)
|
||||||
|
|
||||||
|
|
||||||
// MARK:- Other Molecules
|
// MARK:- Other Molecules
|
||||||
MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self)
|
MoleculeObjectMapping.shared()?.register(viewClass: DoughnutChartView.self, viewModelClass: DoughnutChartModel.self)
|
||||||
|
|||||||
@ -77,7 +77,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 120
|
return 120
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,7 @@
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 120
|
return 120
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 120
|
return 120
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -64,7 +64,7 @@
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -90,7 +90,7 @@
|
|||||||
rightHeadlineBodyLink.body.setFontStyle(.RegularBodySmall)
|
rightHeadlineBodyLink.body.setFontStyle(.RegularBodySmall)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,7 @@
|
|||||||
rightDropDown.set(with:model.rightDropDown, delegateObject, additionalData)
|
rightDropDown.set(with:model.rightDropDown, delegateObject, additionalData)
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,7 @@
|
|||||||
rightLabel.setFontStyle(.RegularBodySmall)
|
rightLabel.setFontStyle(.RegularBodySmall)
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 15
|
return 15
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,9 +53,7 @@ import Foundation
|
|||||||
super.set(with: model, delegateObject, additionalData)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
|
||||||
guard let model = model as? ListOneColumnFullWidthTextDividerSubsectionModel else { return }
|
guard let model = model as? ListOneColumnFullWidthTextDividerSubsectionModel else { return }
|
||||||
|
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
|
||||||
headline.set(with: model.headline, delegateObject, additionalData)
|
|
||||||
body.set(with: model.body, delegateObject, additionalData)
|
|
||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,13 +16,13 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
|
|||||||
|
|
||||||
public static var identifier: String = "list1CTxtDiv3"
|
public static var identifier: String = "list1CTxtDiv3"
|
||||||
public var headline: LabelModel
|
public var headline: LabelModel
|
||||||
public var body: LabelModel
|
public var body: LabelModel?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(headline: LabelModel, body: LabelModel) {
|
public init(headline: LabelModel, body: LabelModel?) {
|
||||||
self.headline = headline
|
self.headline = headline
|
||||||
self.body = body
|
self.body = body
|
||||||
super.init()
|
super.init()
|
||||||
@ -54,7 +54,7 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||||
body = try typeContainer.decode(LabelModel.self, forKey: .body)
|
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +63,6 @@ public class ListOneColumnFullWidthTextDividerSubsectionModel: ListItemModel, Mo
|
|||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encode(headline, forKey: .headline)
|
try container.encode(headline, forKey: .headline)
|
||||||
try container.encode(body, forKey: .body)
|
try container.encodeIfPresent(body, forKey: .body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,9 +53,7 @@ import Foundation
|
|||||||
super.set(with: model, delegateObject, additionalData)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
|
||||||
guard let model = model as? ListOneColumnTextWithWhitespaceDividerShortModel else { return }
|
guard let model = model as? ListOneColumnTextWithWhitespaceDividerShortModel else { return }
|
||||||
|
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
|
||||||
headline.set(with: model.headline, delegateObject, additionalData)
|
|
||||||
body.set(with: model.body, delegateObject, additionalData)
|
|
||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,13 +16,13 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
|
|||||||
|
|
||||||
public static var identifier: String = "list1CTxtDiv1"
|
public static var identifier: String = "list1CTxtDiv1"
|
||||||
public var headline: LabelModel
|
public var headline: LabelModel
|
||||||
public var body: LabelModel
|
public var body: LabelModel?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(headline: LabelModel, body: LabelModel) {
|
public init(headline: LabelModel, body: LabelModel?) {
|
||||||
self.headline = headline
|
self.headline = headline
|
||||||
self.body = body
|
self.body = body
|
||||||
super.init()
|
super.init()
|
||||||
@ -54,7 +54,7 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||||
body = try typeContainer.decode(LabelModel.self, forKey: .body)
|
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +63,6 @@ public class ListOneColumnTextWithWhitespaceDividerShortModel: ListItemModel, Mo
|
|||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encode(headline, forKey: .headline)
|
try container.encode(headline, forKey: .headline)
|
||||||
try container.encode(body, forKey: .body)
|
try container.encodeIfPresent(body, forKey: .body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,9 +52,7 @@ import Foundation
|
|||||||
super.set(with: model, delegateObject, additionalData)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
|
||||||
guard let model = model as? ListOneColumnTextWithWhitespaceDividerTallModel else { return }
|
guard let model = model as? ListOneColumnTextWithWhitespaceDividerTallModel else { return }
|
||||||
|
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
|
||||||
headline.set(with: model.headline, delegateObject, additionalData)
|
|
||||||
body.set(with: model.body, delegateObject, additionalData)
|
|
||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,13 +16,13 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
|
|||||||
|
|
||||||
public static var identifier: String = "list1CTxtDiv2"
|
public static var identifier: String = "list1CTxtDiv2"
|
||||||
public var headline: LabelModel
|
public var headline: LabelModel
|
||||||
public var body: LabelModel
|
public var body: LabelModel?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(headline: LabelModel, body: LabelModel) {
|
public init(headline: LabelModel, body: LabelModel?) {
|
||||||
self.headline = headline
|
self.headline = headline
|
||||||
self.body = body
|
self.body = body
|
||||||
super.init()
|
super.init()
|
||||||
@ -54,7 +54,7 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
headline = try typeContainer.decode(LabelModel.self, forKey: .headline)
|
||||||
body = try typeContainer.decode(LabelModel.self, forKey: .body)
|
body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body)
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +63,6 @@ public class ListOneColumnTextWithWhitespaceDividerTallModel: ListItemModel, Mol
|
|||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encode(headline, forKey: .headline)
|
try container.encode(headline, forKey: .headline)
|
||||||
try container.encode(body, forKey: .body)
|
try container.encodeIfPresent(body, forKey: .body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,7 +62,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 120
|
return 120
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -62,7 +62,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@ import Foundation
|
|||||||
updateAccessibilityLabel()
|
updateAccessibilityLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 121
|
return 121
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// MoleculeSectionFooter.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/5/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers open class MoleculeSectionFooter: SectionHeaderFooterView {
|
||||||
|
open var molecule: MoleculeViewProtocol?
|
||||||
|
public let containerHelper = ContainerHelper()
|
||||||
|
|
||||||
|
/// Adds the molecule to the view.
|
||||||
|
open func addMolecule(_ molecule: MoleculeViewProtocol) {
|
||||||
|
contentView.addSubview(molecule)
|
||||||
|
containerHelper.constrainView(molecule)
|
||||||
|
self.molecule = molecule
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func updateView(_ size: CGFloat) {
|
||||||
|
super.updateView(size)
|
||||||
|
containerHelper.updateViewMargins(self, model: model as? MoleculeSectionFooterModel, size: size)
|
||||||
|
contentView.directionalLayoutMargins = directionalLayoutMargins
|
||||||
|
(molecule as? MVMCoreViewProtocol)?.updateView(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
guard let model = model as? MoleculeSectionFooterModel else { return }
|
||||||
|
if molecule != nil {
|
||||||
|
molecule?.set(with: model.molecule, delegateObject, additionalData)
|
||||||
|
} else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) {
|
||||||
|
addMolecule(moleculeView)
|
||||||
|
}
|
||||||
|
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
molecule?.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||||
|
return MoleculeContainer.nameForReuse(with: model, delegateObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||||
|
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
|
return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 80.0
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// MoleculeSectionFooterModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/5/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers open class MoleculeSectionFooterModel: MoleculeContainerModel, SectionListHeaderFooterModel {
|
||||||
|
public class override var identifier: String {
|
||||||
|
return "sectionFooter"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defaults to set
|
||||||
|
public override func setDefaults() {
|
||||||
|
if useHorizontalMargins == nil {
|
||||||
|
useHorizontalMargins = true
|
||||||
|
}
|
||||||
|
if useVerticalMargins == nil {
|
||||||
|
useVerticalMargins = true
|
||||||
|
}
|
||||||
|
if topPadding == nil {
|
||||||
|
topPadding = PaddingDefaultVerticalSpacing3
|
||||||
|
}
|
||||||
|
if bottomPadding == nil {
|
||||||
|
bottomPadding = PaddingDefaultVerticalSpacing3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// MoleculeSectionHeader.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/2/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers open class MoleculeSectionHeader: SectionHeaderFooterView {
|
||||||
|
open var molecule: MoleculeViewProtocol?
|
||||||
|
public let containerHelper = ContainerHelper()
|
||||||
|
public let line = Line()
|
||||||
|
|
||||||
|
/// Adds the molecule to the view.
|
||||||
|
open func addMolecule(_ molecule: MoleculeViewProtocol) {
|
||||||
|
contentView.addSubview(molecule)
|
||||||
|
containerHelper.constrainView(molecule)
|
||||||
|
self.molecule = molecule
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func setupView() {
|
||||||
|
super.setupView()
|
||||||
|
line.setStyle(.thin)
|
||||||
|
contentView.addSubview(line)
|
||||||
|
NSLayoutConstraint.pinViewBottom(toSuperview: line, useMargins: false, constant: 0).isActive = true
|
||||||
|
NSLayoutConstraint.pinViewLeft(toSuperview: line, useMargins: true, constant: 0).isActive = true
|
||||||
|
NSLayoutConstraint.pinViewRight(toSuperview: line, useMargins: true, constant: 0).isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func updateView(_ size: CGFloat) {
|
||||||
|
super.updateView(size)
|
||||||
|
containerHelper.updateViewMargins(self, model: model as? MoleculeSectionHeaderModel, size: size)
|
||||||
|
contentView.directionalLayoutMargins = directionalLayoutMargins
|
||||||
|
(molecule as? MVMCoreViewProtocol)?.updateView(size)
|
||||||
|
line.updateView(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
guard let model = model as? MoleculeSectionHeaderModel else { return }
|
||||||
|
if molecule != nil {
|
||||||
|
molecule?.set(with: model.molecule, delegateObject, additionalData)
|
||||||
|
} else if let moleculeView = MoleculeObjectMapping.shared()?.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: additionalData) {
|
||||||
|
addMolecule(moleculeView)
|
||||||
|
}
|
||||||
|
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
|
||||||
|
line.setOptional(with: model.line, delegateObject, additionalData)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
line.setStyle(.thin)
|
||||||
|
molecule?.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||||
|
return MoleculeContainer.nameForReuse(with: model, delegateObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||||
|
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
|
return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 80.0
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// MoleculeSectionHeaderModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/2/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers open class MoleculeSectionHeaderModel: MoleculeContainerModel, SectionListHeaderFooterModel {
|
||||||
|
public class override var identifier: String {
|
||||||
|
return "sectionHeader"
|
||||||
|
}
|
||||||
|
public var line: LineModel?
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case line
|
||||||
|
case backgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defaults to set
|
||||||
|
public override func setDefaults() {
|
||||||
|
if useHorizontalMargins == nil {
|
||||||
|
useHorizontalMargins = true
|
||||||
|
}
|
||||||
|
if useVerticalMargins == nil {
|
||||||
|
useVerticalMargins = true
|
||||||
|
}
|
||||||
|
if topPadding == nil {
|
||||||
|
topPadding = PaddingDefaultVerticalSpacing3
|
||||||
|
}
|
||||||
|
if bottomPadding == nil {
|
||||||
|
bottomPadding = PaddingDefaultVerticalSpacing3
|
||||||
|
}
|
||||||
|
if line == nil {
|
||||||
|
line = LineModel(type: .thin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
try super.init(from: decoder)
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func encode(to encoder: Encoder) throws {
|
||||||
|
try super.encode(to: encoder)
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(line, forKey: .line)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -34,26 +34,14 @@ open class MoleculeCollectionViewCell: CollectionViewCell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
open override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||||
guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule else { return "\(self)<>" }
|
return MoleculeContainer.nameForReuse(with: model, delegateObject)
|
||||||
let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
|
|
||||||
let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName
|
|
||||||
return "\(self)<\(moleculeName)>"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
open override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||||
guard let moleculeModel = (model as? MoleculeCollectionItemModel)?.molecule,
|
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
|
||||||
let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
|
|
||||||
else { return nil }
|
|
||||||
|
|
||||||
return theClass.requiredModules(with: moleculeModel, delegateObject, error: error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
guard let model = model as? MoleculeCollectionItemModel,
|
return MoleculeContainer.estimatedHeight(with: model, delegateObject) ?? 100
|
||||||
let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(model.molecule),
|
|
||||||
let height = classType.estimatedHeight(with: model.molecule, delegateObject)
|
|
||||||
else { return 100 }
|
|
||||||
|
|
||||||
return height + (model.topPadding ?? 0) + (model.bottomPadding ?? 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import Foundation
|
|||||||
import MVMCore
|
import MVMCore
|
||||||
|
|
||||||
|
|
||||||
@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeModelProtocol {
|
@objcMembers public class MoleculeListItemModel: ListItemModel, MoleculeContainerModelProtocol, MoleculeModelProtocol {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
case spacing
|
case spacing
|
||||||
case percent
|
case percent
|
||||||
case gone
|
case gone
|
||||||
|
case moleculeName
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -54,6 +55,7 @@
|
|||||||
public override func encode(to encoder: Encoder) throws {
|
public override func encode(to encoder: Encoder) throws {
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||||
try container.encodeIfPresent(percent, forKey: .percent)
|
try container.encodeIfPresent(percent, forKey: .percent)
|
||||||
try container.encode(gone, forKey: .gone)
|
try container.encode(gone, forKey: .gone)
|
||||||
|
|||||||
@ -30,28 +30,16 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||||
guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule else { return "\(self)<>" }
|
return MoleculeContainer.nameForReuse(with: model, delegateObject)
|
||||||
|
|
||||||
let className = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
|
|
||||||
let moleculeName = className?.nameForReuse(with: moleculeModel, delegateObject) ?? moleculeModel.moleculeName
|
|
||||||
|
|
||||||
return "\(self)<\(moleculeName)>"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
public override class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||||
guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule,
|
return MoleculeContainer.requiredModules(with: model, delegateObject, error: error)
|
||||||
let theClass = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel)
|
|
||||||
else { return nil }
|
|
||||||
|
|
||||||
return theClass.requiredModules(with: moleculeModel, delegateObject, error: error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
guard let moleculeModel = (model as? MoleculeListItemModel)?.molecule,
|
guard let height = MoleculeContainer.estimatedHeight(with: model, delegateObject)
|
||||||
let classType = MoleculeObjectMapping.shared()?.getMoleculeClass(moleculeModel),
|
|
||||||
let height = classType.estimatedHeight(with: moleculeModel, delegateObject)
|
|
||||||
else { return 80 }
|
else { return 80 }
|
||||||
|
return height
|
||||||
return max(2 * PaddingDefaultVerticalSpacing3, height)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,7 +157,7 @@ import UIKit
|
|||||||
bottomRightLabel.setFontStyle(.RegularMicro)
|
bottomRightLabel.setFontStyle(.RegularMicro)
|
||||||
}
|
}
|
||||||
|
|
||||||
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
public class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
return 34
|
return 34
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,25 +8,25 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
|
open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
|
||||||
public class var identifier: String {
|
open class var identifier: String {
|
||||||
return "navigationBar"
|
return "navigationBar"
|
||||||
}
|
}
|
||||||
|
|
||||||
public var title: String?
|
open var title: String?
|
||||||
public var hidden: Bool
|
open var hidden: Bool
|
||||||
public var backgroundColor: Color?
|
open var backgroundColor: Color?
|
||||||
public var tintColor: Color
|
open var tintColor: Color
|
||||||
public var line: LineModel?
|
open var line: LineModel?
|
||||||
public var hidesSystemBackButton = true
|
open var hidesSystemBackButton = true
|
||||||
|
|
||||||
/// If true, we add the button in the backButton property. If false we do not add the button. If nil, we add the button if the controller is not the bottom of the stack
|
/// If true, we add the button in the backButton property. If false we do not add the button. If nil, we add the button if the controller is not the bottom of the stack
|
||||||
public var alwaysShowBackButton: Bool?
|
open var alwaysShowBackButton: Bool?
|
||||||
public var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)?
|
open var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)?
|
||||||
|
|
||||||
public var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
|
open var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
|
||||||
public var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
|
open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
|
||||||
public var titleView: MoleculeModelProtocol?
|
open var titleView: MoleculeModelProtocol?
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
hidden = false
|
hidden = false
|
||||||
@ -44,8 +44,6 @@ public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProt
|
|||||||
case line
|
case line
|
||||||
case alwaysShowBackButton
|
case alwaysShowBackButton
|
||||||
case backButton
|
case backButton
|
||||||
case showLeftPanelButton
|
|
||||||
case showRightPanelButton
|
|
||||||
case additionalLeftButtons
|
case additionalLeftButtons
|
||||||
case additionalRightButtons
|
case additionalRightButtons
|
||||||
case titleView
|
case titleView
|
||||||
|
|||||||
@ -12,12 +12,11 @@ import UIKit
|
|||||||
open class MoleculeContainer: Container {
|
open class MoleculeContainer: Container {
|
||||||
|
|
||||||
/// Can be overriden to change how the molecule is added to the hierarchy.
|
/// Can be overriden to change how the molecule is added to the hierarchy.
|
||||||
public func addMolecule(_ molecule: UIView) {
|
open func addMolecule(_ molecule: UIView) {
|
||||||
addAndContain(molecule)
|
addAndContain(molecule)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
|
||||||
if let casteModel = model as? MoleculeContainerModelProtocol {
|
if let casteModel = model as? MoleculeContainerModelProtocol {
|
||||||
if view != nil {
|
if view != nil {
|
||||||
(view as? MoleculeViewProtocol)?.set(with: casteModel.molecule, delegateObject, additionalData)
|
(view as? MoleculeViewProtocol)?.set(with: casteModel.molecule, delegateObject, additionalData)
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol {
|
open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtocol, MoleculeModelProtocol {
|
||||||
public class var identifier: String {
|
open class var identifier: String {
|
||||||
return "container"
|
return "container"
|
||||||
}
|
}
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
@ -41,7 +41,7 @@ open class MoleculeContainerModel: ContainerModel, MoleculeContainerModelProtoco
|
|||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func encode(to encoder: Encoder) throws {
|
open override func encode(to encoder: Encoder) throws {
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class CollapsableNotificationModel: NotificationModel {
|
open class CollapsableNotificationModel: NotificationModel {
|
||||||
public class override var identifier: String {
|
public class override var identifier: String {
|
||||||
return "collapsableNotification"
|
return "collapsableNotification"
|
||||||
}
|
}
|
||||||
@ -19,12 +19,12 @@ public class CollapsableNotificationModel: NotificationModel {
|
|||||||
public var initiallyCollapsed = false
|
public var initiallyCollapsed = false
|
||||||
public var pages: [String]?
|
public var pages: [String]?
|
||||||
|
|
||||||
init(with topLabel: LabelModel, headline: LabelModel) {
|
public init(with topLabel: LabelModel, headline: LabelModel) {
|
||||||
self.topLabel = topLabel
|
self.topLabel = topLabel
|
||||||
super.init(with: headline)
|
super.init(with: headline)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func setDefault() {
|
open override func setDefault() {
|
||||||
super.setDefault()
|
super.setDefault()
|
||||||
if topLabel.textColor == nil {
|
if topLabel.textColor == nil {
|
||||||
topLabel.textColor = Color(uiColor: .white)
|
topLabel.textColor = Color(uiColor: .white)
|
||||||
@ -61,7 +61,7 @@ public class CollapsableNotificationModel: NotificationModel {
|
|||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func encode(to encoder: Encoder) throws {
|
open override func encode(to encoder: Encoder) throws {
|
||||||
try super.encode(to: encoder)
|
try super.encode(to: encoder)
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class NotificationModel: MoleculeModelProtocol {
|
open class NotificationModel: MoleculeModelProtocol {
|
||||||
public class var identifier: String {
|
public class var identifier: String {
|
||||||
return "notification"
|
return "notification"
|
||||||
}
|
}
|
||||||
@ -18,11 +18,11 @@ public class NotificationModel: MoleculeModelProtocol {
|
|||||||
public var button: ButtonModel?
|
public var button: ButtonModel?
|
||||||
public var closeButton: NotificationXButtonModel?
|
public var closeButton: NotificationXButtonModel?
|
||||||
|
|
||||||
init(with headline: LabelModel) {
|
public init(with headline: LabelModel) {
|
||||||
self.headline = headline
|
self.headline = headline
|
||||||
}
|
}
|
||||||
|
|
||||||
func setDefault() {
|
open func setDefault() {
|
||||||
if backgroundColor == nil {
|
if backgroundColor == nil {
|
||||||
backgroundColor = Color(uiColor: .mvmGreen())
|
backgroundColor = Color(uiColor: .mvmGreen())
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ public class NotificationModel: MoleculeModelProtocol {
|
|||||||
setDefault()
|
setDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
open func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
headlineBody.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
headlineBody.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
||||||
headlineBody.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
|
headlineBody.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
|
||||||
|
rightAnchor.constraint(greaterThanOrEqualTo: headlineBody.rightAnchor).isActive = true
|
||||||
var constraint = rightAnchor.constraint(equalTo: headlineBody.rightAnchor)
|
var constraint = rightAnchor.constraint(equalTo: headlineBody.rightAnchor)
|
||||||
constraint.priority = .defaultHigh
|
constraint.priority = .defaultHigh
|
||||||
constraint.isActive = true
|
constraint.isActive = true
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// NavigationBarRefreshProtocol.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/8/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// A protocol to inform that we should refresh the navigation bar ui.
|
||||||
|
@objc public protocol NavigationBarRefreshProtocol {
|
||||||
|
@objc func refreshNavigationUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UIViewController: NavigationBarRefreshProtocol {
|
||||||
|
|
||||||
|
/// Convenience function to refresh the navigation bar ui. A separate function for others to use.
|
||||||
|
@objc public static func refreshNavigationUI(for viewController: UIViewController) {
|
||||||
|
guard let model = (viewController as? PageProtocol)?.pageModel?.navigationBar else { return }
|
||||||
|
if let navigationController = viewController.navigationController {
|
||||||
|
NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: model, viewController: viewController)
|
||||||
|
MVMCoreUISplitViewController.setNavigationBarUI(for: viewController, navigationController: navigationController, navigationItemModel: model)
|
||||||
|
}
|
||||||
|
if let manager = ((viewController as? MVMCoreViewManagerViewControllerProtocol)?.manager as? NavigationBarRefreshProtocol) {
|
||||||
|
// Refresh the manager if possible.
|
||||||
|
manager.refreshNavigationUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func refreshNavigationUI() {
|
||||||
|
UIViewController.refreshNavigationUI(for: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
MVMCoreUI/Atomic/Protocols/PageProtocol.swift
Normal file
13
MVMCoreUI/Atomic/Protocols/PageProtocol.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// PageProtocol.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/7/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public protocol PageProtocol {
|
||||||
|
var pageModel: PageModelProtocol? { get set }
|
||||||
|
}
|
||||||
@ -23,7 +23,7 @@ public extension TemplateProtocol where Self: ViewController {
|
|||||||
let decoder = JSONDecoder()
|
let decoder = JSONDecoder()
|
||||||
try decoder.add(delegateObject: delegateObjectIVar)
|
try decoder.add(delegateObject: delegateObjectIVar)
|
||||||
self.templateModel = try decodeTemplate(using: decoder, from: data)
|
self.templateModel = try decodeTemplate(using: decoder, from: data)
|
||||||
self.pageModel = templateModel as? MVMControllerModelProtocol
|
self.model = templateModel as? MVMControllerModelProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {
|
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {
|
||||||
|
|||||||
@ -18,6 +18,15 @@ import Foundation
|
|||||||
}
|
}
|
||||||
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||||
public var line: LineModel?
|
public var line: LineModel?
|
||||||
|
|
||||||
|
/// This template requires content.
|
||||||
|
func validateModelHasContent() throws {
|
||||||
|
if header == nil,
|
||||||
|
molecules?.count ?? 0 == 0,
|
||||||
|
footer == nil {
|
||||||
|
throw ModelRegistry.Error.decoderOther(message: "List template requires atleast one of the following: header, footer, molecules")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializer
|
// MARK: - Initializer
|
||||||
@ -47,6 +56,7 @@ import Foundation
|
|||||||
molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules)
|
molecules = try typeContainer.decodeModelsIfPresent(codingKey: .molecules)
|
||||||
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
||||||
try super.init(from: decoder)
|
try super.init(from: decoder)
|
||||||
|
try validateModelHasContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func encode(to encoder: Encoder) throws {
|
open override func encode(to encoder: Encoder) throws {
|
||||||
|
|||||||
30
MVMCoreUI/Atomic/Templates/ModalSectionListTemplate.swift
Normal file
30
MVMCoreUI/Atomic/Templates/ModalSectionListTemplate.swift
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// ModalSectionListTemplate.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/8/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
open class ModalSectionListTemplate: SectionListTemplate {
|
||||||
|
|
||||||
|
// For subclassing the model.
|
||||||
|
open override func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ModalSectionListTemplateModel {
|
||||||
|
return try decoder.decode(ModalSectionListTemplateModel.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override open func handleNewData() {
|
||||||
|
super.handleNewData()
|
||||||
|
_ = MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: {[weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let model = self.templateModel as? ModalSectionListTemplateModel,
|
||||||
|
let actionMap = model.closeAction else {
|
||||||
|
MVMCoreActionHandler.shared()?.handleAction(with: ActionBackModel().toJSON(), additionalData: nil, delegateObject: self.delegateObjectIVar)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
MVMCoreActionHandler.shared()?.handleAction(with: actionMap.toJSON(), additionalData: nil, delegateObject: self.delegateObjectIVar)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// ModalSectionListTemplateModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/8/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers public class ModalSectionListTemplateModel: SectionListTemplateModel {
|
||||||
|
public override class var identifier: String {
|
||||||
|
return "modalSectionList"
|
||||||
|
}
|
||||||
|
public var closeAction: ActionModelProtocol?
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case closeAction
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
closeAction = try typeContainer.decodeModelIfPresent(codingKey: .closeAction)
|
||||||
|
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.encodeModelIfPresent(closeAction, forKey: .closeAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,24 +14,15 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
// MARK: - Stored Properties
|
// MARK: - Stored Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]?
|
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)]?
|
||||||
|
|
||||||
var observer: NSKeyValueObservation?
|
var observer: NSKeyValueObservation?
|
||||||
|
|
||||||
public var templateModel: ListPageTemplateModel?
|
public var templateModel: ListPageTemplateModel?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Computed Properties
|
// MARK: - Computed Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
open override func parsePageJSON() throws {
|
|
||||||
try parseTemplate(json: loadObject?.pageJSON)
|
|
||||||
try super.parsePageJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// For subclassing the model.
|
|
||||||
open func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ListPageTemplateModel {
|
|
||||||
return try decoder.decode(ListPageTemplateModel.self, from: data)
|
|
||||||
}
|
|
||||||
|
|
||||||
open override var loadObject: MVMCoreLoadObject? {
|
open override var loadObject: MVMCoreLoadObject? {
|
||||||
didSet {
|
didSet {
|
||||||
@ -50,6 +41,16 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Methods
|
// MARK: - Methods
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override func parsePageJSON() throws {
|
||||||
|
try parseTemplate(json: loadObject?.pageJSON)
|
||||||
|
try super.parsePageJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// For subclassing the model.
|
||||||
|
open func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> ListPageTemplateModel {
|
||||||
|
return try decoder.decode(ListPageTemplateModel.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
open override func viewForTop() -> UIView {
|
open override func viewForTop() -> UIView {
|
||||||
guard let headerModel = templateModel?.header,
|
guard let headerModel = templateModel?.header,
|
||||||
@ -72,21 +73,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
return molecule
|
return molecule
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
|
|
||||||
|
|
||||||
guard super.shouldFinishProcessingLoad(loadObject, error: error) else { return false }
|
|
||||||
|
|
||||||
// This template requires atleast one of the three layers.
|
|
||||||
if templateModel?.header == nil,
|
|
||||||
templateModel?.molecules?.count ?? 0 == 0,
|
|
||||||
templateModel?.footer == nil,
|
|
||||||
let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), messageToLog: "List template requires atleast one of the following: header, footer, molecules", code: CoreUIErrorCode.ErrorCodeListMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) {
|
|
||||||
error.pointee = errorObject
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func handleNewData() {
|
open override func handleNewData() {
|
||||||
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
|
topViewOutsideOfScrollArea = templateModel?.anchorHeader ?? false
|
||||||
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
|
bottomViewOutsideOfScrollArea = templateModel?.anchorFooter ?? false
|
||||||
@ -109,7 +95,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
guard let moleculeInfo = moleculesInfo?[indexPath.row],
|
guard let moleculeInfo = getMoleculeInfo(for: indexPath),
|
||||||
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
|
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
|
||||||
else { return 0 }
|
else { return 0 }
|
||||||
|
|
||||||
@ -122,7 +108,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
|
|
||||||
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
|
||||||
guard let moleculeInfo = moleculesInfo?[indexPath.row],
|
guard let moleculeInfo = getMoleculeInfo(for: indexPath),
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier)
|
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier)
|
||||||
else { return UITableViewCell() }
|
else { return UITableViewCell() }
|
||||||
|
|
||||||
@ -175,7 +161,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
var indexPaths: [IndexPath] = []
|
var indexPaths: [IndexPath] = []
|
||||||
|
|
||||||
for molecule in molecules {
|
for molecule in molecules {
|
||||||
if let info = self.getMoleculeInfo(with: molecule) {
|
if let info = self.createMoleculeInfo(with: molecule) {
|
||||||
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
||||||
let index = indexPath.row + 1 + indexPaths.count
|
let index = indexPath.row + 1 + indexPaths.count
|
||||||
self.moleculesInfo?.insert(info, at: index)
|
self.moleculesInfo?.insert(info, at: index)
|
||||||
@ -211,8 +197,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
// MARK: - Convenience
|
// MARK: - Convenience
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
/// Returns the (identifier, class) of the molecule for the given map.
|
/// Returns the (identifier, class) of the molecule for the given model.
|
||||||
func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? {
|
func createMoleculeInfo(with listItem: MoleculeModelProtocol?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
|
||||||
|
|
||||||
guard let listItem = listItem,
|
guard let listItem = listItem,
|
||||||
let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem)
|
let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem)
|
||||||
@ -223,14 +209,19 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
return (moleculeName, moleculeClass, listItem)
|
return (moleculeName, moleculeClass, listItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the (identifier, class) of the molecule for the indexPath.
|
||||||
|
func getMoleculeInfo(for indexPath: IndexPath) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
|
||||||
|
return moleculesInfo?[indexPath.row]
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets up the molecule list and ensures no errors loading all content.
|
/// Sets up the molecule list and ensures no errors loading all content.
|
||||||
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? {
|
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)]? {
|
||||||
|
|
||||||
var moleculeList: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)] = []
|
var moleculeList: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)] = []
|
||||||
|
|
||||||
if let molecules = templateModel?.molecules {
|
if let molecules = templateModel?.molecules {
|
||||||
for molecule in molecules {
|
for molecule in molecules {
|
||||||
if let info = getMoleculeInfo(with: molecule) {
|
if let info = createMoleculeInfo(with: molecule) {
|
||||||
moleculeList.append(info)
|
moleculeList.append(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
137
MVMCoreUI/Atomic/Templates/SectionListTemplate.swift
Normal file
137
MVMCoreUI/Atomic/Templates/SectionListTemplate.swift
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
//
|
||||||
|
// SectionListTemplate.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 9/25/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
open class SectionListTemplate: MoleculeListTemplate {
|
||||||
|
|
||||||
|
public var sectionMoleculesInfo: [(header: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, footer: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)])]?
|
||||||
|
|
||||||
|
open override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
tableView.sectionHeaderHeight = UITableView.automaticDimension
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setup() {
|
||||||
|
// Create quick reference
|
||||||
|
var sectionList: [(header: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, footer: (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)?, rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)])] = []
|
||||||
|
|
||||||
|
if let sections = (templateModel as? SectionListTemplateModel)?.sections {
|
||||||
|
for section in sections {
|
||||||
|
let header = createMoleculeInfo(with: section.header)
|
||||||
|
let footer = createMoleculeInfo(with: section.footer)
|
||||||
|
var rows: [(identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)] = []
|
||||||
|
for row in section.rows {
|
||||||
|
if let rowInfo = createMoleculeInfo(with: row) {
|
||||||
|
rows.append(rowInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sectionList.append((header: header, footer: footer, rows: rows))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionMoleculesInfo = sectionList.count > 0 ? sectionList : nil
|
||||||
|
}
|
||||||
|
|
||||||
|
override func getMoleculeInfo(for indexPath: IndexPath) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
|
||||||
|
return sectionMoleculesInfo?[indexPath.section].rows[indexPath.row]
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func createTableView() -> TableView {
|
||||||
|
let tableView = TableView(frame: .zero, style: .plain)
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
|
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
|
||||||
|
tableView.delegate = self
|
||||||
|
tableView.dataSource = self
|
||||||
|
tableView.insetsContentViewsToSafeArea = false
|
||||||
|
return tableView
|
||||||
|
}
|
||||||
|
|
||||||
|
// For subclassing the model.
|
||||||
|
open override func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> SectionListTemplateModel {
|
||||||
|
return try decoder.decode(SectionListTemplateModel.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func registerWithTable() {
|
||||||
|
super.registerWithTable()
|
||||||
|
guard let sections = sectionMoleculesInfo else { return }
|
||||||
|
for section in sections {
|
||||||
|
if let header = section.header {
|
||||||
|
tableView.register(header.class, forHeaderFooterViewReuseIdentifier: header.identifier)
|
||||||
|
}
|
||||||
|
if let footer = section.footer {
|
||||||
|
tableView.register(footer.class, forHeaderFooterViewReuseIdentifier: footer.identifier)
|
||||||
|
}
|
||||||
|
for row in section.rows {
|
||||||
|
tableView.register(row.class, forCellReuseIdentifier: row.identifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
|
||||||
|
guard let moleculeInfo = sectionMoleculesInfo?[section].header else {
|
||||||
|
return CGFloat.leastNormalMagnitude
|
||||||
|
}
|
||||||
|
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
|
||||||
|
return estimatedHeight ?? 80
|
||||||
|
}
|
||||||
|
|
||||||
|
public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||||
|
guard (sectionMoleculesInfo?[section].header) != nil else {
|
||||||
|
return CGFloat.leastNormalMagnitude
|
||||||
|
}
|
||||||
|
return UITableView.automaticDimension
|
||||||
|
}
|
||||||
|
|
||||||
|
public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
|
||||||
|
guard let moleculeInfo = sectionMoleculesInfo?[section].footer else {
|
||||||
|
return CGFloat.leastNormalMagnitude
|
||||||
|
}
|
||||||
|
let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
|
||||||
|
return estimatedHeight ?? 80
|
||||||
|
}
|
||||||
|
|
||||||
|
public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
||||||
|
guard (sectionMoleculesInfo?[section].footer) != nil else {
|
||||||
|
return CGFloat.leastNormalMagnitude
|
||||||
|
}
|
||||||
|
return UITableView.automaticDimension
|
||||||
|
}
|
||||||
|
|
||||||
|
public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||||
|
guard let sectionInfo = sectionMoleculesInfo?[section],
|
||||||
|
let headerInfo = sectionInfo.header else { return nil }
|
||||||
|
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerInfo.identifier)
|
||||||
|
(header as? MoleculeViewProtocol)?.reset()
|
||||||
|
(header as? MoleculeViewProtocol)?.set(with: headerInfo.molecule, delegateObjectIVar, nil)
|
||||||
|
(header as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
|
||||||
|
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
|
||||||
|
header?.layoutIfNeeded()
|
||||||
|
return header
|
||||||
|
}
|
||||||
|
|
||||||
|
public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||||
|
guard let sectionInfo = sectionMoleculesInfo?[section],
|
||||||
|
let footerInfo = sectionInfo.footer else { return nil }
|
||||||
|
let footer = tableView.dequeueReusableHeaderFooterView(withIdentifier: footerInfo.identifier)
|
||||||
|
(footer as? MoleculeViewProtocol)?.reset()
|
||||||
|
(footer as? MoleculeViewProtocol)?.set(with: footerInfo.molecule, delegateObjectIVar, nil)
|
||||||
|
(footer as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
|
||||||
|
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
|
||||||
|
footer?.layoutIfNeeded()
|
||||||
|
return footer
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func getNumberOfSections() -> Int {
|
||||||
|
return sectionMoleculesInfo?.count ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return sectionMoleculesInfo?[section].rows.count ?? 0
|
||||||
|
}
|
||||||
|
}
|
||||||
91
MVMCoreUI/Atomic/Templates/SectionListTemplateModel.swift
Normal file
91
MVMCoreUI/Atomic/Templates/SectionListTemplateModel.swift
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// SectionListTemplateModel.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 9/25/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public protocol SectionListHeaderFooterModel {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@objcMembers open class SectionModel: Codable {
|
||||||
|
public var header: (SectionListHeaderFooterModel & MoleculeModelProtocol)?
|
||||||
|
public var footer: (SectionListHeaderFooterModel & MoleculeModelProtocol)?
|
||||||
|
public var rows: [ListItemModelProtocol & MoleculeModelProtocol]
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case header
|
||||||
|
case footer
|
||||||
|
case rows
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
|
||||||
|
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
|
||||||
|
rows = try typeContainer.decodeModels(codingKey: .rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
open func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encodeModelIfPresent(header, forKey: .header)
|
||||||
|
try container.encodeModelIfPresent(footer, forKey: .footer)
|
||||||
|
try container.encodeModels(rows, forKey: .rows)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objcMembers open class SectionListTemplateModel: ListPageTemplateModel {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override class var identifier: String {
|
||||||
|
return "sectionList"
|
||||||
|
}
|
||||||
|
|
||||||
|
public var sections: [SectionModel]
|
||||||
|
|
||||||
|
override func validateModelHasContent() throws {
|
||||||
|
if header == nil,
|
||||||
|
sections.count == 0,
|
||||||
|
footer == nil {
|
||||||
|
throw ModelRegistry.Error.decoderOther(message: "Section List template requires atleast one of the following: header, footer, sections")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Keys
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case sections
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Codec
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
required public init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
sections = try typeContainer.decode([SectionModel].self, forKey: .sections)
|
||||||
|
try super.init(from: decoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func encode(to encoder: Encoder) throws {
|
||||||
|
try super.encode(to: encoder)
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
try container.encode(sections, forKey: .sections)
|
||||||
|
}
|
||||||
|
}
|
||||||
85
MVMCoreUI/BaseClasses/SectionHeaderFooterView.swift
Normal file
85
MVMCoreUI/BaseClasses/SectionHeaderFooterView.swift
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// SectionHeaderFooterView.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 10/2/20.
|
||||||
|
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objcMembers open class SectionHeaderFooterView: UITableViewHeaderFooterView, MoleculeViewProtocol {
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open var model: MoleculeModelProtocol?
|
||||||
|
|
||||||
|
private var initialSetupPerformed = false
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initialization
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public override init(reuseIdentifier: String?) {
|
||||||
|
super.init(reuseIdentifier: reuseIdentifier)
|
||||||
|
initialSetup()
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
initialSetup()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func initialSetup() {
|
||||||
|
if !initialSetupPerformed {
|
||||||
|
initialSetupPerformed = true
|
||||||
|
setupView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - MoleculeViewProtocol
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
self.model = model
|
||||||
|
if let backgroundColor = model.backgroundColor {
|
||||||
|
contentView.backgroundColor = backgroundColor.uiColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open func reset() {
|
||||||
|
contentView.backgroundColor = .white
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Overridables
|
||||||
|
// Base classes need to implement these functions otherwise swift won't respect the subclass functions and use the ones in the protocol extension instead.
|
||||||
|
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||||
|
return model.moleculeName
|
||||||
|
}
|
||||||
|
|
||||||
|
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
open class func requiredModules(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK:- MVMCoreViewProtocol
|
||||||
|
extension SectionHeaderFooterView: MVMCoreViewProtocol {
|
||||||
|
|
||||||
|
open func updateView(_ size: CGFloat) { }
|
||||||
|
|
||||||
|
/// Will be called only once.
|
||||||
|
open func setupView() {
|
||||||
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
insetsLayoutMarginsFromSafeArea = false
|
||||||
|
preservesSuperviewLayoutMargins = false
|
||||||
|
contentView.insetsLayoutMarginsFromSafeArea = false
|
||||||
|
contentView.preservesSuperviewLayoutMargins = false
|
||||||
|
MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -63,6 +63,16 @@ open class ScrollingViewController: ViewController {
|
|||||||
registerForKeyboardNotifications()
|
registerForKeyboardNotifications()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override func handleNewData() {
|
||||||
|
super.handleNewData()
|
||||||
|
// will change scrollView indicatorStyle automatically on the basis of backgroundColor
|
||||||
|
var greyScale: CGFloat = 0
|
||||||
|
if view.backgroundColor?.getWhite(&greyScale, alpha: nil) ?? false {
|
||||||
|
scrollView.indicatorStyle = greyScale > 0.5 ? .black : .white
|
||||||
|
}
|
||||||
|
scrollView.flashScrollIndicators()
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keyboard Handling
|
// MARK: - Keyboard Handling
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|||||||
@ -8,15 +8,23 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol, PageProtocol {
|
||||||
@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol {
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
@objc public var pageType: String?
|
@objc public var pageType: String?
|
||||||
@objc public var loadObject: MVMCoreLoadObject?
|
@objc public var loadObject: MVMCoreLoadObject?
|
||||||
public var pageModel: MVMControllerModelProtocol?
|
public var model: MVMControllerModelProtocol?
|
||||||
|
public var pageModel: PageModelProtocol? {
|
||||||
|
get {
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
model = newValue as? MVMControllerModelProtocol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set if this page is containted in a manager.
|
/// Set if this page is containted in a manager.
|
||||||
public var manager: (UIViewController & MVMCoreViewManagerProtocol)?
|
public var manager: (UIViewController & MVMCoreViewManagerProtocol)?
|
||||||
@ -111,9 +119,15 @@ import UIKit
|
|||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||||
self.handleNewDataAndUpdateUI()
|
self.handleNewDataAndUpdateUI()
|
||||||
|
|
||||||
// Update navigation bar if showing.
|
|
||||||
if MVMCoreUIUtility.getCurrentVisibleController() == self {
|
if MVMCoreUIUtility.getCurrentVisibleController() == self {
|
||||||
|
// Update navigation bar if showing.
|
||||||
self.setNavigationBar()
|
self.setNavigationBar()
|
||||||
|
self.manager?.refreshNavigationUI()
|
||||||
|
}
|
||||||
|
// Update splitview properties
|
||||||
|
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
|
||||||
|
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(self.bottomProgress() ?? 0)
|
||||||
|
self.updateTabBar()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch {
|
} catch {
|
||||||
@ -127,7 +141,7 @@ import UIKit
|
|||||||
pageType = loadObject.pageType
|
pageType = loadObject.pageType
|
||||||
self.loadObject = loadObject
|
self.loadObject = loadObject
|
||||||
|
|
||||||
// Verifies all modules needed are loaded. TODO: change to ViewController
|
// Verifies all modules needed are loaded.
|
||||||
guard ViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) else { return false }
|
guard ViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) else { return false }
|
||||||
|
|
||||||
// Parse the model for the page.
|
// Parse the model for the page.
|
||||||
@ -214,18 +228,18 @@ import UIKit
|
|||||||
/// Creates a legacy navigation model.
|
/// Creates a legacy navigation model.
|
||||||
open func createDefaultLegacyNavigationModel() -> NavigationItemModel {
|
open func createDefaultLegacyNavigationModel() -> NavigationItemModel {
|
||||||
let navigationModel = NavigationItemModel()
|
let navigationModel = NavigationItemModel()
|
||||||
navigationModel.title = pageModel?.screenHeading
|
navigationModel.title = model?.screenHeading
|
||||||
return navigationModel
|
return navigationModel
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Processes any new data. Called after the page is loaded the first time and on response updates for this page,
|
/// Processes any new data. Called after the page is loaded the first time and on response updates for this page,
|
||||||
open func handleNewData() {
|
open func handleNewData() {
|
||||||
if formValidator == nil {
|
if formValidator == nil {
|
||||||
let rules = pageModel?.formRules
|
let rules = model?.formRules
|
||||||
formValidator = FormValidator(rules)
|
formValidator = FormValidator(rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let backgroundColor = pageModel?.backgroundColor {
|
if let backgroundColor = model?.backgroundColor {
|
||||||
view.backgroundColor = backgroundColor.uiColor
|
view.backgroundColor = backgroundColor.uiColor
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,16 +248,16 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Navigation Item (Move to model base)
|
// MARK: - Navigation Item
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open func getNavigationModel() -> NavigationItemModelProtocol? {
|
open func getNavigationModel() -> NavigationItemModelProtocol? {
|
||||||
// TODO: remove legacy. Temporary, convert legacy to navigation model.
|
// TODO: remove legacy. Temporary, convert legacy to navigation model.
|
||||||
if pageModel?.navigationBar == nil {
|
if model?.navigationBar == nil {
|
||||||
let navigationItem = createDefaultLegacyNavigationModel()
|
let navigationItem = createDefaultLegacyNavigationModel()
|
||||||
pageModel?.navigationBar = navigationItem
|
model?.navigationBar = navigationItem
|
||||||
}
|
}
|
||||||
return pageModel?.navigationBar
|
return model?.navigationBar
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the navigation item for this view controller.
|
/// Sets the navigation item for this view controller.
|
||||||
@ -252,70 +266,22 @@ import UIKit
|
|||||||
let navigationController = navigationController
|
let navigationController = navigationController
|
||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
// We additionally want our left items
|
|
||||||
navigationItem.leftItemsSupplementBackButton = true
|
|
||||||
|
|
||||||
// Utilize helper function to set the navigation item state.
|
// Utilize helper function to set the navigation item state.
|
||||||
NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: self)
|
NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the appearance of the navigation bar based on the model.
|
/// Sets the appearance of the navigation bar based on the model.
|
||||||
open func setNavigationBar() {
|
open func setNavigationBar() {
|
||||||
let viewController = manager ?? self
|
|
||||||
guard let navigationItemModel = getNavigationModel(),
|
guard let navigationItemModel = getNavigationModel(),
|
||||||
let navigationController = viewController.navigationController else {
|
let navigationController = navigationController else {
|
||||||
MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate()
|
MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utilize helper function to set the split view and navigation item state.
|
// Utilize helper function to set the split view and navigation item state.
|
||||||
MVMCoreUISplitViewController.setNavigationBarUI(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel, leftPanelAccessible: isMasterInitiallyAccessible(), rightPanelAccessible: isSupportInitiallyAccessible(), progress: bottomProgress() ?? 0)
|
MVMCoreUISplitViewController.setNavigationBarUI(for: self, navigationController: navigationController, navigationItemModel: navigationItemModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eventually will be moved to server
|
|
||||||
open func isMasterInitiallyAccessible() -> Bool {
|
|
||||||
if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eventually will be moved to server
|
|
||||||
open func isSupportInitiallyAccessible() -> Bool {
|
|
||||||
if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return (MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false) || showRightPanelForScreenBeforeLaunchApp()
|
|
||||||
}
|
|
||||||
|
|
||||||
open func showRightPanelForScreenBeforeLaunchApp() -> Bool {
|
|
||||||
return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eventually will be moved to separate button in navigation item model
|
|
||||||
open func isOverridingRightButton() -> Bool {
|
|
||||||
guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink")
|
|
||||||
else { return false }
|
|
||||||
MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eventually will be moved to separate button in navigation item model
|
|
||||||
open func isOverridingLeftButton() -> Bool {
|
|
||||||
guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink")
|
|
||||||
else { return false }
|
|
||||||
MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eventually will be moved to Model
|
|
||||||
open func bottomProgress() -> Float? {
|
|
||||||
guard let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent),
|
|
||||||
let progress = Float(progressString)
|
|
||||||
else { return nil }
|
|
||||||
|
|
||||||
return progress / Float(100)
|
|
||||||
}
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - TabBar
|
// MARK: - TabBar
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -324,7 +290,7 @@ import UIKit
|
|||||||
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self else { return }
|
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self else { return }
|
||||||
MVMCoreUISplitViewController.main()?.tabBar?.delegateObject = delegateObjectIVar
|
MVMCoreUISplitViewController.main()?.tabBar?.delegateObject = delegateObjectIVar
|
||||||
|
|
||||||
if let index = (pageModel as? TabPageModelProtocol)?.tabBarIndex {
|
if let index = (model as? TabPageModelProtocol)?.tabBarIndex {
|
||||||
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
|
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
|
||||||
} else if let index = loadObject?.requestParameters?.actionMap?["tabBarIndex"] as? Int {
|
} else if let index = loadObject?.requestParameters?.actionMap?["tabBarIndex"] as? Int {
|
||||||
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
|
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
|
||||||
@ -335,7 +301,7 @@ import UIKit
|
|||||||
self.tabBarIndex = index
|
self.tabBarIndex = index
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hidden = (pageModel as? TabPageModelProtocol)?.tabBarHidden {
|
if let hidden = (model as? TabPageModelProtocol)?.tabBarHidden {
|
||||||
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
|
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
|
||||||
} else if let hidden = loadObject?.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
|
} else if let hidden = loadObject?.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
|
||||||
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
|
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
|
||||||
@ -398,14 +364,15 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
open func pageShown() {
|
open func pageShown() {
|
||||||
// Update the navigation bar ui when view is appearing.
|
// Update split view properties if this is the current detail controller.
|
||||||
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
|
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
|
||||||
MVMCoreUISplitViewController.main()?.setupPanels()
|
MVMCoreUISplitViewController.main()?.setupPanels()
|
||||||
|
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
|
||||||
|
updateTabBar()
|
||||||
}
|
}
|
||||||
setNavigationBar()
|
|
||||||
|
|
||||||
// Update tab if needed.
|
// Update the navigation bar ui when view is appearing.
|
||||||
updateTabBar()
|
setNavigationBar()
|
||||||
|
|
||||||
// Track.
|
// Track.
|
||||||
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
||||||
@ -472,13 +439,17 @@ import UIKit
|
|||||||
MVMCoreUISession.sharedGlobal()?.splitViewController?.showRightPanel(animated: true)
|
MVMCoreUISession.sharedGlobal()?.splitViewController?.showRightPanel(animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Override this method to avoid adding form params.
|
||||||
|
open func addFormParams(_ requestParameters: MVMCoreRequestParameters) {
|
||||||
|
formValidator?.addFormParams(requestParameters: requestParameters)
|
||||||
|
}
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - MVMCoreActionDelegateProtocol
|
// MARK: - MVMCoreActionDelegateProtocol
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
|
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
|
||||||
formValidator?.addFormParams(requestParameters: requestParameters)
|
addFormParams(requestParameters)
|
||||||
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
|
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
|
||||||
MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: delegateObject())
|
MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: delegateObject())
|
||||||
}
|
}
|
||||||
@ -526,6 +497,51 @@ import UIKit
|
|||||||
setNavigationBar()
|
setNavigationBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isLeftPanelAccessible() -> Bool {
|
||||||
|
// TODO: Remove when hamburger menu is fully phased out.
|
||||||
|
if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isRightPanelAccessible() -> Bool {
|
||||||
|
// TODO: Remove when FAB is 100%.
|
||||||
|
if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return (MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false) || showRightPanelForScreenBeforeLaunchApp()
|
||||||
|
}
|
||||||
|
|
||||||
|
open func showRightPanelForScreenBeforeLaunchApp() -> Bool {
|
||||||
|
return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make molecular
|
||||||
|
open func isOverridingRightButton() -> Bool {
|
||||||
|
guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink")
|
||||||
|
else { return false }
|
||||||
|
MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make molecular
|
||||||
|
open func isOverridingLeftButton() -> Bool {
|
||||||
|
guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink")
|
||||||
|
else { return false }
|
||||||
|
MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eventually will be moved to Model
|
||||||
|
open func bottomProgress() -> Float? {
|
||||||
|
guard let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent),
|
||||||
|
let progress = Float(progressString)
|
||||||
|
else { return nil }
|
||||||
|
|
||||||
|
return progress / Float(100)
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - UITextFieldDelegate
|
// MARK: - UITextFieldDelegate
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -594,6 +610,6 @@ import UIKit
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
func executeBehaviors<T>(_ behaviorBlock:(_ behavior:T)->Void) {
|
func executeBehaviors<T>(_ behaviorBlock:(_ behavior:T)->Void) {
|
||||||
pageModel?.behaviors?.compactMap({ $0 as? T }).forEach { behaviorBlock($0) }
|
model?.behaviors?.compactMap({ $0 as? T }).forEach { behaviorBlock($0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,7 @@ import UIKit
|
|||||||
viewController.navigationItem.title = navigationItemModel.title
|
viewController.navigationItem.title = navigationItemModel.title
|
||||||
viewController.navigationItem.accessibilityLabel = navigationItemModel.title
|
viewController.navigationItem.accessibilityLabel = navigationItemModel.title
|
||||||
viewController.navigationItem.hidesBackButton = navigationItemModel.hidesSystemBackButton
|
viewController.navigationItem.hidesBackButton = navigationItemModel.hidesSystemBackButton
|
||||||
|
viewController.navigationItem.leftItemsSupplementBackButton = !navigationItemModel.hidesSystemBackButton
|
||||||
setNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
setNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||||
setNavigationTitleView(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
setNavigationTitleView(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||||
}
|
}
|
||||||
@ -58,7 +59,7 @@ import UIKit
|
|||||||
var leftItems: [UIBarButtonItem] = []
|
var leftItems: [UIBarButtonItem] = []
|
||||||
if navigationItemModel.alwaysShowBackButton != false {
|
if navigationItemModel.alwaysShowBackButton != false {
|
||||||
if let backButtonModel = navigationItemModel.backButton,
|
if let backButtonModel = navigationItemModel.backButton,
|
||||||
navigationController.viewControllers.count > 1 || navigationItemModel.alwaysShowBackButton ?? false {
|
MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 0 > 1 || navigationItemModel.alwaysShowBackButton ?? false {
|
||||||
leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||||
}
|
}
|
||||||
if let leftItemModels = navigationItemModel.additionalLeftButtons {
|
if let leftItemModels = navigationItemModel.additionalLeftButtons {
|
||||||
@ -94,23 +95,7 @@ import UIKit
|
|||||||
navigationController.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none
|
navigationController.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience setter for legacy files
|
|
||||||
public static func setNavigationItem(navigationController: UINavigationController, navigationJSON: [String: Any], viewController: UIViewController) throws {
|
|
||||||
guard let barModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
|
|
||||||
throw ModelRegistry.Error.decoderOther(message: "Model not a bar model")
|
|
||||||
}
|
|
||||||
setNavigationItem(navigationController: navigationController, navigationItemModel: barModel, viewController: viewController)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience setter for legacy files
|
|
||||||
public static func setNavigationBarUI(navigationController: UINavigationController, navigationJSON: [String: Any], viewController: UIViewController) throws {
|
|
||||||
guard let barModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
|
|
||||||
throw ModelRegistry.Error.decoderOther(message: "Model not a bar model")
|
|
||||||
}
|
|
||||||
setNavigationBarUI(navigationController: navigationController, navigationItemModel: barModel, viewController: viewController)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convenience function for setting the navigation titleView.
|
/// Convenience function for setting the navigation titleView.
|
||||||
public static func setNavigationTitleView(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) {
|
public static func setNavigationTitleView(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) {
|
||||||
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
|
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
|
||||||
|
|||||||
@ -15,6 +15,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@optional
|
@optional
|
||||||
|
|
||||||
|
/// Returns if the left panel should be accessible.
|
||||||
|
- (BOOL)isLeftPanelAccessible;
|
||||||
|
|
||||||
|
/// Returns if the right panel should be accessible.
|
||||||
|
- (BOOL)isRightPanelAccessible;
|
||||||
|
|
||||||
- (void)panelWillAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel;
|
- (void)panelWillAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel;
|
||||||
- (void)panelWillAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel overtakingDetail:(BOOL)willOvertake;
|
- (void)panelWillAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel overtakingDetail:(BOOL)willOvertake;
|
||||||
- (void)panelDidAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel;
|
- (void)panelDidAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel;
|
||||||
|
|||||||
@ -10,32 +10,29 @@ import Foundation
|
|||||||
|
|
||||||
public extension MVMCoreUISplitViewController {
|
public extension MVMCoreUISplitViewController {
|
||||||
|
|
||||||
/// Convenience function. Sets the navigation and split view properties for the view controller. Optional parameters use current value if not set.
|
/// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol.
|
||||||
static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, leftPanelAccessible: Bool? = nil, rightPanelAccessible: Bool? = nil, progress: Float? = nil) {
|
static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
|
||||||
guard let splitView = MVMCoreUISplitViewController.main(),
|
guard let splitView = MVMCoreUISplitViewController.main(),
|
||||||
navigationController == splitView.navigationController,
|
navigationController == splitView.navigationController,
|
||||||
navigationController.topViewController == viewController else {
|
navigationController.topViewController == viewController else {
|
||||||
NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
/// Not the split view navigation controller, skip split functions.
|
||||||
return
|
NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel, leftPanelAccessible: leftPanelAccessible, rightPanelAccessible: rightPanelAccessible, progress: progress)
|
splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the navigation item for the view controller based on the model and splitview controller
|
/// Sets the navigation item for the view controller based on the model and splitview controller
|
||||||
private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, leftPanelAccessible: Bool? = nil, rightPanelAccessible: Bool? = nil, progress: Float? = nil) {
|
private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
|
||||||
NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||||
|
|
||||||
setLeftPanelIsAccessible(leftPanelAccessible ?? leftPanelIsAccessible, for: viewController, updateNavigationButtons: false)
|
setLeftPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
|
||||||
setRightPanelIsAccessible(rightPanelAccessible ?? rightPanelIsAccessible, for: viewController, updateNavigationButtons: false)
|
setRightPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
|
||||||
|
|
||||||
setLeftNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
setLeftNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||||
setRightNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
setRightNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||||
|
|
||||||
setNavigationIconColor(navigationItemModel.tintColor.uiColor)
|
setNavigationIconColor(navigationItemModel.tintColor.uiColor)
|
||||||
|
|
||||||
if let progress = progress {
|
|
||||||
setBottomProgressBarProgress(progress)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the left navigation items for the view controller based on model and splitview.
|
/// Sets the left navigation items for the view controller based on model and splitview.
|
||||||
@ -48,7 +45,7 @@ public extension MVMCoreUISplitViewController {
|
|||||||
if let forceBackButton = navigationItemModel?.alwaysShowBackButton {
|
if let forceBackButton = navigationItemModel?.alwaysShowBackButton {
|
||||||
showBackButton = forceBackButton
|
showBackButton = forceBackButton
|
||||||
} else {
|
} else {
|
||||||
showBackButton = navigationController.viewControllers.count > 1
|
showBackButton = MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 0 > 1
|
||||||
}
|
}
|
||||||
if showBackButton {
|
if showBackButton {
|
||||||
if let backButtonModel = navigationItemModel?.backButton {
|
if let backButtonModel = navigationItemModel?.backButton {
|
||||||
@ -107,20 +104,4 @@ public extension MVMCoreUISplitViewController {
|
|||||||
|
|
||||||
viewController.navigationItem.setRightBarButtonItems(rightItems.count > 0 ? rightItems : nil, animated: !DisableAnimations.boolValue)
|
viewController.navigationItem.setRightBarButtonItems(rightItems.count > 0 ? rightItems : nil, animated: !DisableAnimations.boolValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Legacy Functions
|
|
||||||
/// Convenience setter for legacy files. Sets the navigation item for the view controller based on the json and splitview controller
|
|
||||||
@objc static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationJSON: [String: Any], leftPanelAccessible: Bool, rightPanelAccessible: Bool, progress: NSNumber?) throws {
|
|
||||||
guard let navigationItemModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
|
|
||||||
throw ModelRegistry.Error.decoderOther(message: "Model not a bar model")
|
|
||||||
}
|
|
||||||
guard let splitView = MVMCoreUISplitViewController.main(),
|
|
||||||
navigationController == splitView.navigationController,
|
|
||||||
navigationController.topViewController == viewController else {
|
|
||||||
NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let progress = progress?.floatValue
|
|
||||||
splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel, leftPanelAccessible: leftPanelAccessible, rightPanelAccessible: rightPanelAccessible, progress: progress)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -241,7 +241,7 @@ CGFloat const PanelAnimationDuration = 0.2;
|
|||||||
|
|
||||||
- (void)setLeftNavigationItemForViewController:(UIViewController * _Nonnull)viewController accessible:(BOOL)accessible extended:(BOOL)extended {
|
- (void)setLeftNavigationItemForViewController:(UIViewController * _Nonnull)viewController accessible:(BOOL)accessible extended:(BOOL)extended {
|
||||||
NSMutableArray *leftBarButtonItems = [NSMutableArray array];
|
NSMutableArray *leftBarButtonItems = [NSMutableArray array];
|
||||||
if ([viewController.navigationController.viewControllers count] > 1) {
|
if (viewController.navigationController && [MVMCoreNavigationHandler.sharedNavigationHandler getViewControllersForNavigationController:viewController.navigationController].count > 1) {
|
||||||
[leftBarButtonItems addObject:self.backButton];
|
[leftBarButtonItems addObject:self.backButton];
|
||||||
}
|
}
|
||||||
if ((accessible && !extended) && self.leftPanelButton) {
|
if ((accessible && !extended) && self.leftPanelButton) {
|
||||||
|
|||||||
@ -20,6 +20,8 @@ public extension MVMCoreUIViewControllerMappingObject {
|
|||||||
|
|
||||||
register(template: MoleculeListTemplate.self)
|
register(template: MoleculeListTemplate.self)
|
||||||
add(toTemplateViewControllerMapping: ["modalList": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeListTemplate.self)!])
|
add(toTemplateViewControllerMapping: ["modalList": MVMCoreViewControllerProgrammaticMappingObject(with: ModalMoleculeListTemplate.self)!])
|
||||||
|
add(toTemplateViewControllerMapping: [SectionListTemplateModel.identifier: MVMCoreViewControllerProgrammaticMappingObject(with: SectionListTemplate.self)!])
|
||||||
|
add(toTemplateViewControllerMapping: [ModalSectionListTemplateModel.identifier: MVMCoreViewControllerProgrammaticMappingObject(with: ModalSectionListTemplate.self)!])
|
||||||
|
|
||||||
register(template: ThreeLayerTemplate.self)
|
register(template: ThreeLayerTemplate.self)
|
||||||
register(template: ThreeLayerCenterTemplate.self)
|
register(template: ThreeLayerCenterTemplate.self)
|
||||||
|
|||||||
@ -67,6 +67,11 @@
|
|||||||
"AccOff" = "off";
|
"AccOff" = "off";
|
||||||
"AccToggleHint" = "double tap to toggle";
|
"AccToggleHint" = "double tap to toggle";
|
||||||
|
|
||||||
|
// MARK: Heart
|
||||||
|
"heart_favorite_action_hint" = "Double tap to favorite";
|
||||||
|
"heart_unfavorite_action_hint" = "Double tap to unfavorite";
|
||||||
|
"heart_selected_state" = "Favorited";
|
||||||
|
"heart_not_selected_state" = "Un-favorited";
|
||||||
|
|
||||||
// MARK: Carousel
|
// MARK: Carousel
|
||||||
"MVMCoreUIPageControl_currentpage_index" = "page %@ of %d";
|
"MVMCoreUIPageControl_currentpage_index" = "page %@ of %d";
|
||||||
|
|||||||
@ -49,6 +49,11 @@
|
|||||||
"AccOn" = "encendido";
|
"AccOn" = "encendido";
|
||||||
"AccOff" = "apagado";
|
"AccOff" = "apagado";
|
||||||
"AccToggleHint" = "toca dos veces para alternar";
|
"AccToggleHint" = "toca dos veces para alternar";
|
||||||
|
// Heart
|
||||||
|
"heart_favorite_action_hint" = "Toca dos veces en favorito";
|
||||||
|
"heart_unfavorite_action_hint" = "Toca dos veces para dejar de marcar como favorito";
|
||||||
|
"heart_selected_state" = "Favoritos";
|
||||||
|
"heart_not_selected_state" = "No favorito";
|
||||||
// Carousel
|
// Carousel
|
||||||
"MVMCoreUIPageControl_currentpage_index" = "página %@ de %d";
|
"MVMCoreUIPageControl_currentpage_index" = "página %@ de %d";
|
||||||
"MVMCoreUIPageControlslides_currentpage_index" = "diapositiva %@ of %d";
|
"MVMCoreUIPageControlslides_currentpage_index" = "diapositiva %@ of %d";
|
||||||
|
|||||||
@ -51,6 +51,13 @@
|
|||||||
"AccOn" = "encendido";
|
"AccOn" = "encendido";
|
||||||
"AccOff" = "apagado";
|
"AccOff" = "apagado";
|
||||||
"AccToggleHint" = "toca dos veces para alternar";
|
"AccToggleHint" = "toca dos veces para alternar";
|
||||||
|
|
||||||
|
// Heart
|
||||||
|
"heart_favorite_action_hint" = "Toca dos veces en favorito";
|
||||||
|
"heart_unfavorite_action_hint" = "Toca dos veces para dejar de marcar como favorito";
|
||||||
|
"heart_selected_state" = "Favoritos";
|
||||||
|
"heart_not_selected_state" = "No favorito";
|
||||||
|
|
||||||
// Carousel
|
// Carousel
|
||||||
"MVMCoreUIPageControl_currentpage_index" = "página %@ de %d";
|
"MVMCoreUIPageControl_currentpage_index" = "página %@ de %d";
|
||||||
"MVMCoreUIPageControlslides_currentpage_index" = "diapositiva %@ of %d";
|
"MVMCoreUIPageControlslides_currentpage_index" = "diapositiva %@ of %d";
|
||||||
|
|||||||
@ -21,14 +21,17 @@ public extension MVMCoreUITopAlertView {
|
|||||||
NotificationCenter.default.addObserver(self, selector: #selector(viewControllerChanged(notification:)), name: NSNotification.Name(rawValue: MVMCoreNotificationViewControllerChanged), object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(viewControllerChanged(notification:)), name: NSNotification.Name(rawValue: MVMCoreNotificationViewControllerChanged), object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func getDelegateObject() -> MVMCoreUIDelegateObject {
|
||||||
|
// TODO: Top alert view is current delegate. Should move to current view controller eventually?
|
||||||
|
return MVMCoreUIDelegateObject.create(withDelegateForAll: self)
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks for new top alert json
|
/// Checks for new top alert json
|
||||||
@objc func responseJSONUpdated(notification: Notification) {
|
@objc func responseJSONUpdated(notification: Notification) {
|
||||||
guard let responseJSON = (notification.userInfo?[String(describing: MVMCoreLoadObject.self)] as? MVMCoreLoadObject)?.responseJSON,
|
guard let responseJSON = (notification.userInfo?[String(describing: MVMCoreLoadObject.self)] as? MVMCoreLoadObject)?.responseJSON,
|
||||||
let json = responseJSON.optionalDictionaryForKey("TopNotification") else { return }
|
let json = responseJSON.optionalDictionaryForKey("TopNotification"),
|
||||||
|
let model = decodeTopNotification(with: json, delegateObject: getDelegateObject()) else { return }
|
||||||
// TODO: Top alert view is current delegate. Should move to current view controller eventually?
|
showTopAlert(with: model)
|
||||||
let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
|
|
||||||
showTopAlert(with: json, delegateObject: delegateObject)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When a detail page changes, check top alerts.
|
/// When a detail page changes, check top alerts.
|
||||||
@ -37,24 +40,55 @@ public extension MVMCoreUITopAlertView {
|
|||||||
MVMCoreAlertHandler.shared()?.checkPagesDependency(for: controller.pageType)
|
MVMCoreAlertHandler.shared()?.checkPagesDependency(for: controller.pageType)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shows the top alert with the json payload.
|
/// Decodes the json into a TopNotificationModel
|
||||||
func showTopAlert(with json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) {
|
func decodeTopNotification(with json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) -> TopNotificationModel? {
|
||||||
do {
|
do {
|
||||||
let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject)
|
return try TopNotificationModel.decode(json: json, delegateObject: delegateObject)
|
||||||
showTopAlert(with: model, delegateObject: delegateObject)
|
|
||||||
} catch {
|
} catch {
|
||||||
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") {
|
if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") {
|
||||||
MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject)
|
MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shows the top alert with the model.
|
/// Shows the top alert with the model.
|
||||||
func showTopAlert(with model: TopNotificationModel, delegateObject: MVMCoreUIDelegateObject?) {
|
func showTopAlert(with model: TopNotificationModel) {
|
||||||
let object = model.createTopAlertObject()
|
let object = model.createTopAlertObject()
|
||||||
MVMCoreAlertHandler.shared()?.showTopAlert(with: object)
|
MVMCoreAlertHandler.shared()?.showTopAlert(with: object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the current top alert molecule with the new object
|
||||||
|
@objc func updateMolecule(with topAlertObject: MVMCoreTopAlertObject) {
|
||||||
|
guard topAlertObject.type == self.topAlertObject?.type else { return }
|
||||||
|
let delegateObject = getDelegateObject()
|
||||||
|
guard let newJson = topAlertObject.json,
|
||||||
|
let newModel = decodeTopNotification(with: newJson, delegateObject: delegateObject),
|
||||||
|
let newModelName = MoleculeObjectMapping.shared()?.getMoleculeClass(newModel.molecule)?.nameForReuse(with: newModel.molecule, delegateObject),
|
||||||
|
let currentJson = self.topAlertObject?.json,
|
||||||
|
let currentModel = decodeTopNotification(with: currentJson, delegateObject: delegateObject),
|
||||||
|
let currentModelName = MoleculeObjectMapping.shared()?.getMoleculeClass(currentModel.molecule)?.nameForReuse(with: currentModel.molecule, delegateObject),
|
||||||
|
newModelName == currentModelName,
|
||||||
|
let molecule = currentAlert as? MoleculeViewProtocol else {
|
||||||
|
// Log that we couldn't update.
|
||||||
|
if let errorObject = MVMCoreErrorObject(title: nil, message: nil, messageToLog: nil, code: ErrorCode.parsingJSON.rawValue, domain: ErrorDomainNative, location: "TopNotification update \(String(describing: topAlertObject.type))") {
|
||||||
|
MVMCoreUILoggingHandler.shared()?.addError(toLog: errorObject)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||||
|
// Update molecule
|
||||||
|
molecule.reset()
|
||||||
|
molecule.set(with: newModel.molecule, delegateObject, nil)
|
||||||
|
(molecule as? MVMCoreViewProtocol)?.updateView(self.bounds.width)
|
||||||
|
|
||||||
|
// Update status bar.
|
||||||
|
guard let statusBarDelegate = molecule as? StatusBarUI else { return }
|
||||||
|
let statusBarUI = statusBarDelegate.getStatusBarUI()
|
||||||
|
self.setStatusBarColor(statusBarUI.color, statusBarStyle: statusBarUI.style)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the top alert molecule to use and status bar color legacy style.
|
/// Returns the top alert molecule to use and status bar color legacy style.
|
||||||
@objc func molecule(for topAlertObject: MVMCoreTopAlertObject, statusBarColor: AutoreleasingUnsafeMutablePointer<UIColor?>?, statusBarStyle: UnsafeMutablePointer<UIStatusBarStyle>?) -> UIView? {
|
@objc func molecule(for topAlertObject: MVMCoreTopAlertObject, statusBarColor: AutoreleasingUnsafeMutablePointer<UIColor?>?, statusBarStyle: UnsafeMutablePointer<UIStatusBarStyle>?) -> UIView? {
|
||||||
do {
|
do {
|
||||||
|
|||||||
@ -27,6 +27,9 @@
|
|||||||
// Current top alert object
|
// Current top alert object
|
||||||
@property (strong, nullable, nonatomic) MVMCoreTopAlertObject *topAlertObject;
|
@property (strong, nullable, nonatomic) MVMCoreTopAlertObject *topAlertObject;
|
||||||
|
|
||||||
|
/// Current top alert view.
|
||||||
|
@property (weak, nullable, nonatomic, readonly) UIView *currentAlert;
|
||||||
|
|
||||||
// Returns the top alert view
|
// Returns the top alert view
|
||||||
+ (nullable instancetype)sharedGlobal;
|
+ (nullable instancetype)sharedGlobal;
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
@property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint;
|
@property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint;
|
||||||
|
|
||||||
@property (weak, nonatomic) UIView *alertView;
|
@property (weak, nonatomic) UIView *alertView;
|
||||||
@property (weak, nonatomic) UIView *currentAlert;
|
@property (weak, nullable, nonatomic, readwrite) UIView *currentAlert;
|
||||||
@property (strong, nonatomic) NSLayoutConstraint *height;
|
@property (strong, nonatomic) NSLayoutConstraint *height;
|
||||||
|
|
||||||
@property (weak, nonatomic) MVMCoreUITopAlertExpandableView *topAlertClearspotView;
|
@property (weak, nonatomic) MVMCoreUITopAlertExpandableView *topAlertClearspotView;
|
||||||
@ -181,6 +181,10 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)updateTopAlertWith:(MVMCoreTopAlertObject *)topAlertObject {
|
||||||
|
[self updateMoleculeWith:topAlertObject];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style {
|
- (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style {
|
||||||
self.statusBarView.backgroundColor = statusBarColor;
|
self.statusBarView.backgroundColor = statusBarColor;
|
||||||
self.statusBarStyle = style;
|
self.statusBarStyle = style;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user