Merge branch 'feature/swift_controllers' into 'develop'
Feature/swift controllers See merge request BPHV_MIPS/mvm_core_ui!324
This commit is contained in:
commit
18f86575e6
@ -15,7 +15,7 @@
|
||||
011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; };
|
||||
011D958524042432000E3791 /* RulesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958424042432000E3791 /* RulesProtocol.swift */; };
|
||||
011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958624042492000E3791 /* FormFieldProtocol.swift */; };
|
||||
011D95892404249B000E3791 /* FormProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95882404249B000E3791 /* FormProtocol.swift */; };
|
||||
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95882404249B000E3791 /* FormHolderModelProtocol.swift */; };
|
||||
011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959A240451E3000E3791 /* RuleRequiredModel.swift */; };
|
||||
011D959D2404536F000E3791 /* RuleAnyValueChangedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */; };
|
||||
011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */; };
|
||||
@ -197,6 +197,7 @@
|
||||
C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012023E8303200396FBD /* ListRVWheel.swift */; };
|
||||
C7F8012323E846C300396FBD /* ListRVWheelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F8012223E846C300396FBD /* ListRVWheelModel.swift */; };
|
||||
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */; };
|
||||
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
|
||||
D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */; };
|
||||
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479892314445E003FCCF9 /* LabelToggle.swift */; };
|
||||
@ -212,9 +213,11 @@
|
||||
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */; };
|
||||
D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; };
|
||||
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; };
|
||||
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
|
||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; };
|
||||
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; };
|
||||
D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */; };
|
||||
D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; };
|
||||
D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; };
|
||||
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; };
|
||||
@ -263,6 +266,7 @@
|
||||
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */; };
|
||||
D29770FD21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */; };
|
||||
D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */; };
|
||||
D29DF0D121E404D4003B2FB9 /* MVMCoreUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */; };
|
||||
D29DF11521E6805F003B2FB9 /* UIColor+MFConvenience.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11121E6805F003B2FB9 /* UIColor+MFConvenience.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -307,11 +311,11 @@
|
||||
D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF28B21E7AC2B003B2FB9 /* ViewConstrainingView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */; };
|
||||
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */; };
|
||||
D29DF29521E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28D21E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m */; };
|
||||
D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */; };
|
||||
D29DF29721E7ADB8003B2FB9 /* MFScrollingViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF29821E7ADB8003B2FB9 /* MFScrollingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */; };
|
||||
D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF29921E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF29A21E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */; };
|
||||
@ -364,6 +368,9 @@
|
||||
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; };
|
||||
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; };
|
||||
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; };
|
||||
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */; };
|
||||
D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */; };
|
||||
D2A92886241ACD99004E01C6 /* ProgrammaticTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A92885241ACD99004E01C6 /* ProgrammaticTableViewController.swift */; };
|
||||
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B7E2360913400A9AEDC /* Control.swift */; };
|
||||
D2B18B812360945C00A9AEDC /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B802360945C00A9AEDC /* View.swift */; };
|
||||
D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */; };
|
||||
@ -409,7 +416,7 @@
|
||||
011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownListItemModel.swift; sourceTree = "<group>"; };
|
||||
011D958424042432000E3791 /* RulesProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RulesProtocol.swift; sourceTree = "<group>"; };
|
||||
011D958624042492000E3791 /* FormFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormFieldProtocol.swift; sourceTree = "<group>"; };
|
||||
011D95882404249B000E3791 /* FormProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormProtocol.swift; sourceTree = "<group>"; };
|
||||
011D95882404249B000E3791 /* FormHolderModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormHolderModelProtocol.swift; sourceTree = "<group>"; };
|
||||
011D959A240451E3000E3791 /* RuleRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRequiredModel.swift; sourceTree = "<group>"; };
|
||||
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyValueChangedModel.swift; sourceTree = "<group>"; };
|
||||
011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAllValueChangedModel.swift; sourceTree = "<group>"; };
|
||||
@ -581,6 +588,7 @@
|
||||
C7F8012023E8303200396FBD /* ListRVWheel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListRVWheel.swift; sourceTree = "<group>"; };
|
||||
C7F8012223E846C300396FBD /* ListRVWheelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRVWheelModel.swift; sourceTree = "<group>"; };
|
||||
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
|
||||
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
|
||||
D21EE53B23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraintAxis+Extension.swift"; sourceTree = "<group>"; };
|
||||
D22479892314445E003FCCF9 /* LabelToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggle.swift; sourceTree = "<group>"; };
|
||||
@ -596,9 +604,11 @@
|
||||
D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISwitch.m; sourceTree = "<group>"; };
|
||||
D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = "<group>"; };
|
||||
D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = "<group>"; };
|
||||
D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = "<group>"; };
|
||||
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = "<group>"; };
|
||||
D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = "<group>"; };
|
||||
D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = "<group>"; };
|
||||
D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
|
||||
D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = "<group>"; };
|
||||
D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = "<group>"; };
|
||||
@ -646,6 +656,7 @@
|
||||
D29770FA21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITextFieldView.m; sourceTree = "<group>"; };
|
||||
D29770FB21F7C77400B2F0D0 /* MVMCoreUITextFieldView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITextFieldView.h; sourceTree = "<group>"; };
|
||||
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleMolecule.swift; sourceTree = "<group>"; };
|
||||
D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUICommonViewsUtility+Extension.swift"; sourceTree = "<group>"; };
|
||||
D29DF0CC21E404D4003B2FB9 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D29DF0CF21E404D4003B2FB9 /* MVMCoreUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUI.h; sourceTree = "<group>"; };
|
||||
D29DF0D021E404D4003B2FB9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@ -711,11 +722,11 @@
|
||||
D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUICommonViewsUtility.h; sourceTree = "<group>"; };
|
||||
D29DF28721E7AC2B003B2FB9 /* ViewConstrainingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewConstrainingView.h; sourceTree = "<group>"; };
|
||||
D29DF28821E7AC2B003B2FB9 /* ViewConstrainingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewConstrainingView.m; sourceTree = "<group>"; };
|
||||
D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgrammaticScrollViewController.m; sourceTree = "<group>"; };
|
||||
D29DF28D21E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFProgrammaticScrollViewController.m; sourceTree = "<group>"; };
|
||||
D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StackableViewController.m; sourceTree = "<group>"; };
|
||||
D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFScrollingViewController.h; sourceTree = "<group>"; };
|
||||
D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFScrollingViewController.m; sourceTree = "<group>"; };
|
||||
D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgrammaticScrollViewController.h; sourceTree = "<group>"; };
|
||||
D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFProgrammaticScrollViewController.h; sourceTree = "<group>"; };
|
||||
D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFProgrammaticTableViewController.h; sourceTree = "<group>"; };
|
||||
D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackableViewController.h; sourceTree = "<group>"; };
|
||||
D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFProgrammaticTableViewController.m; sourceTree = "<group>"; };
|
||||
@ -762,6 +773,9 @@
|
||||
D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = "<group>"; };
|
||||
D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = "<group>"; };
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollingViewController.swift; sourceTree = "<group>"; };
|
||||
D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgrammaticScrollViewController.swift; sourceTree = "<group>"; };
|
||||
D2A92885241ACD99004E01C6 /* ProgrammaticTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgrammaticTableViewController.swift; sourceTree = "<group>"; };
|
||||
D2B18B7E2360913400A9AEDC /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = "<group>"; };
|
||||
D2B18B802360945C00A9AEDC /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
|
||||
D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIObject.swift; sourceTree = "<group>"; };
|
||||
@ -860,7 +874,7 @@
|
||||
01C74D87224298E2009C25A3 /* FormUIHelpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
011D95882404249B000E3791 /* FormProtocol.swift */,
|
||||
011D95882404249B000E3791 /* FormHolderModelProtocol.swift */,
|
||||
011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */,
|
||||
011D95AA2405C553000E3791 /* FormItemProtocol.swift */,
|
||||
011D958624042492000E3791 /* FormFieldProtocol.swift */,
|
||||
@ -1010,8 +1024,20 @@
|
||||
D213347423842FE3008E41B3 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D29DF16021E69996003B2FB9 /* MFViewController.h */,
|
||||
D29DF15F21E69996003B2FB9 /* MFViewController.m */,
|
||||
017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */,
|
||||
011D9627240EFA1E000E3791 /* MFViewController+Form.swift */,
|
||||
D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */,
|
||||
D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */,
|
||||
D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */,
|
||||
D29DF28D21E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m */,
|
||||
D29DF29321E7ADB8003B2FB9 /* StackableViewController.h */,
|
||||
D29DF28E21E7ADB8003B2FB9 /* StackableViewController.m */,
|
||||
D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */,
|
||||
D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */,
|
||||
D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */,
|
||||
D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */,
|
||||
D29770F021F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h */,
|
||||
D29770F121F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m */,
|
||||
D29770EF21F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.h */,
|
||||
@ -1312,6 +1338,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
|
||||
D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
|
||||
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
|
||||
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
|
||||
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */,
|
||||
@ -1370,6 +1397,7 @@
|
||||
017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */,
|
||||
017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */,
|
||||
D260105723CF9CC500764D80 /* Doughnut */,
|
||||
D20FB164241A5D75004AFC3A /* NavigationItemModelProtocol.swift */,
|
||||
);
|
||||
path = Molecules;
|
||||
sourceTree = "<group>";
|
||||
@ -1377,23 +1405,15 @@
|
||||
D29DF10F21E67A7D003B2FB9 /* BaseControllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D29DF16021E69996003B2FB9 /* MFViewController.h */,
|
||||
D29DF15F21E69996003B2FB9 /* MFViewController.m */,
|
||||
017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */,
|
||||
011D9627240EFA1E000E3791 /* MFViewController+Form.swift */,
|
||||
D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */,
|
||||
D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */,
|
||||
D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */,
|
||||
D29DF28D21E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m */,
|
||||
D29DF29221E7ADB8003B2FB9 /* MFProgrammaticTableViewController.h */,
|
||||
D29DF29421E7ADB8003B2FB9 /* MFProgrammaticTableViewController.m */,
|
||||
D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */,
|
||||
D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */,
|
||||
D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */,
|
||||
D29DF2CC21E7C104003B2FB9 /* MFLoadingViewController.h */,
|
||||
D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */,
|
||||
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */,
|
||||
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */,
|
||||
D2C521A823EDE79E00CA2634 /* ViewController.swift */,
|
||||
D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */,
|
||||
D2A92883241ACB25004E01C6 /* ProgrammaticScrollViewController.swift */,
|
||||
D2A92885241ACD99004E01C6 /* ProgrammaticTableViewController.swift */,
|
||||
);
|
||||
path = BaseControllers;
|
||||
sourceTree = "<group>";
|
||||
@ -1456,6 +1476,7 @@
|
||||
D29DF13B21E6870B003B2FB9 /* Sizing */,
|
||||
D29DF28221E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h */,
|
||||
D29DF28121E7AB23003B2FB9 /* MVMCoreUICommonViewsUtility.m */,
|
||||
D29C94D4242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift */,
|
||||
D29DF14D21E693AD003B2FB9 /* MFFonts.h */,
|
||||
D29DF14C21E693AD003B2FB9 /* MFFonts.m */,
|
||||
9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */,
|
||||
@ -1720,7 +1741,7 @@
|
||||
D29DF2A921E7B2F9003B2FB9 /* MVMCoreUIConstants.h in Headers */,
|
||||
0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */,
|
||||
D22D1F1A220341F60077CEC0 /* MVMCoreUICheckBox.h in Headers */,
|
||||
D29DF29921E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h in Headers */,
|
||||
D29DF29921E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h in Headers */,
|
||||
D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */,
|
||||
D29DF29B21E7ADB9003B2FB9 /* StackableViewController.h in Headers */,
|
||||
D29770F421F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.h in Headers */,
|
||||
@ -1898,6 +1919,7 @@
|
||||
01004F3022721C3800991ECC /* RadioButton.swift in Sources */,
|
||||
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */,
|
||||
017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */,
|
||||
D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */,
|
||||
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */,
|
||||
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
|
||||
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */,
|
||||
@ -1928,6 +1950,7 @@
|
||||
D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */,
|
||||
D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */,
|
||||
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
|
||||
D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */,
|
||||
0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */,
|
||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */,
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
||||
@ -1987,6 +2010,7 @@
|
||||
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */,
|
||||
011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */,
|
||||
526A265C240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift in Sources */,
|
||||
D2A92886241ACD99004E01C6 /* ProgrammaticTableViewController.swift in Sources */,
|
||||
01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */,
|
||||
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
|
||||
D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */,
|
||||
@ -2005,6 +2029,7 @@
|
||||
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */,
|
||||
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
|
||||
94FB966323D797DA003D482B /* MFTextButton.m in Sources */,
|
||||
D29C94D5242901C9003813BA /* MVMCoreUICommonViewsUtility+Extension.swift in Sources */,
|
||||
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
|
||||
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
|
||||
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */,
|
||||
@ -2061,7 +2086,7 @@
|
||||
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */,
|
||||
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
||||
C7F8012123E8303200396FBD /* ListRVWheel.swift in Sources */,
|
||||
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */,
|
||||
D29DF29521E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.m in Sources */,
|
||||
D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */,
|
||||
BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */,
|
||||
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */,
|
||||
@ -2074,9 +2099,11 @@
|
||||
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
|
||||
525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */,
|
||||
0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */,
|
||||
D20FB165241A5D75004AFC3A /* NavigationItemModelProtocol.swift in Sources */,
|
||||
DB06250B2293456500B72DD3 /* LeftRightLabelView.swift in Sources */,
|
||||
0A21DB89235E06EF00C160A2 /* MFMdnTextField.m in Sources */,
|
||||
D224798A2314445E003FCCF9 /* LabelToggle.swift in Sources */,
|
||||
D2A92882241AAB67004E01C6 /* ScrollingViewController.swift in Sources */,
|
||||
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */,
|
||||
C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */,
|
||||
0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */,
|
||||
@ -2119,7 +2146,7 @@
|
||||
943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */,
|
||||
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
|
||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||
011D95892404249B000E3791 /* FormProtocol.swift in Sources */,
|
||||
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */,
|
||||
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */,
|
||||
013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */,
|
||||
525239C22407BD1000454969 /* ListTwoColumnPriceDetails.swift in Sources */,
|
||||
@ -2131,6 +2158,7 @@
|
||||
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */,
|
||||
D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */,
|
||||
012A88F123985E0100FE3DA1 /* Color.swift in Sources */,
|
||||
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */,
|
||||
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
|
||||
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */,
|
||||
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,
|
||||
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
|
||||
@objcMembers public class ActionCollapseNotificationModel: ActionModelProtocol {
|
||||
public static var identifier: String = "collapseNotification"
|
||||
public var actionType: String?
|
||||
public var actionType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
public var title: String?
|
||||
|
||||
@ -18,7 +18,7 @@ public class ActionOpenPanelModel: ActionModelProtocol {
|
||||
}
|
||||
|
||||
public static var identifier: String = "openPanel"
|
||||
public var actionType: String?
|
||||
public var actionType: String = ActionOpenPanelModel.identifier
|
||||
public var panel: Panel
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
@objcMembers public class ActionTopAlertModel: ActionModelProtocol {
|
||||
public static var identifier: String = "topAlert"
|
||||
public var actionType: String?
|
||||
public var actionType: String = ActionTopAlertModel.identifier
|
||||
public var pageType: String
|
||||
public var extraParameters: JSONValueDictionary?
|
||||
public var analyticsData: JSONValueDictionary?
|
||||
|
||||
@ -130,7 +130,7 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol {
|
||||
self?.enableField(model.enabled)
|
||||
}
|
||||
|
||||
FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate)
|
||||
FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
@ -338,7 +338,7 @@ import UIKit
|
||||
setAsSecureTextEntry(model.secureEntry)
|
||||
|
||||
for digitBox in digitBoxes {
|
||||
MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate)
|
||||
digitBox.digitField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: delegateObject?.observingTextFieldDelegate ?? self)
|
||||
}
|
||||
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
@ -19,7 +19,7 @@ import UIKit
|
||||
}
|
||||
|
||||
|
||||
@objcMembers open class TextEntryField: EntryField, UITextFieldDelegate {
|
||||
@objcMembers open class TextEntryField: EntryField, UITextFieldDelegate, ObservingTextFieldDelegate {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
@ -311,7 +311,7 @@ import UIKit
|
||||
|
||||
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate)
|
||||
textField.inputAccessoryView = MVMCoreUICommonViewsUtility.getToolbarWithDoneButton(delegate: observingTextFieldDelegate ?? self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import UIKit
|
||||
|
||||
public static var identifier: String = "textField"
|
||||
public var backgroundColor: Color?
|
||||
public var moleculeName: String? = TextFieldModel.identifier
|
||||
public var moleculeName: String = TextFieldModel.identifier
|
||||
public var editable: Bool?
|
||||
public var disabled: Bool?
|
||||
public var errorMsg: String?
|
||||
|
||||
@ -11,7 +11,7 @@ import Foundation
|
||||
@objcMembers public class ImageViewModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "image"
|
||||
public var backgroundColor: Color?
|
||||
public var moleculeName: String? = ImageViewModel.identifier
|
||||
public var moleculeName: String = ImageViewModel.identifier
|
||||
public var image: String
|
||||
public var accessibilityText: String?
|
||||
public var fallbackImage: String?
|
||||
|
||||
@ -14,7 +14,7 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "leftRightLabelView"
|
||||
public var moleculeName: String? = LeftRightLabelModel.identifier
|
||||
public var moleculeName: String = LeftRightLabelModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var leftText: LabelModel
|
||||
public var rightText: LabelModel?
|
||||
|
||||
13
MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift
Normal file
13
MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// MVMControllerModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/16/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol {
|
||||
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
//
|
||||
// ProgrammaticScrollViewController.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/12/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class ProgrammaticScrollViewController: ScrollingViewController {
|
||||
public var topConstraint: NSLayoutConstraint?
|
||||
public var bottomConstraint: NSLayoutConstraint?
|
||||
|
||||
public override init(with scrollView: UIScrollView) {
|
||||
super.init(with: scrollView)
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
open override func loadView() {
|
||||
|
||||
let view = UIView()
|
||||
view.backgroundColor = .white
|
||||
|
||||
let scrollView = UIScrollView()
|
||||
scrollView.backgroundColor = .clear
|
||||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(scrollView)
|
||||
|
||||
// Sets the constraints for the scroll view
|
||||
let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: scrollView)
|
||||
topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint
|
||||
bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint
|
||||
|
||||
let contentView = MVMCoreUICommonViewsUtility.commonView()
|
||||
scrollView.addSubview(contentView)
|
||||
|
||||
// Sets the constraints for the content view
|
||||
NSLayoutConstraint.constraintPinSubview(toSuperview: contentView)
|
||||
|
||||
// Super will set later.
|
||||
contentWidthConstraint = contentView.widthAnchor.constraint(equalToConstant: 320.0)
|
||||
contentWidthConstraint?.isActive = true
|
||||
|
||||
self.contentView = contentView
|
||||
self.scrollView = scrollView
|
||||
self.view = view
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
//
|
||||
// ProgrammaticTableViewController.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/12/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class ProgrammaticTableViewController: ProgrammaticScrollViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
@IBOutlet public var tableView: UITableView!
|
||||
|
||||
public init(with tableView: UITableView) {
|
||||
self.tableView = tableView
|
||||
super.init(with: tableView)
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
open override func loadView() {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .white
|
||||
|
||||
let tableView = createTableView()
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(tableView)
|
||||
|
||||
// Sets the constraints for the scroll view
|
||||
let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: tableView)
|
||||
topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint
|
||||
bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint
|
||||
|
||||
self.tableView = tableView
|
||||
scrollView = tableView
|
||||
self.view = view
|
||||
}
|
||||
|
||||
/// This class should create the table view that will be used here. Subclass this for different table styles.
|
||||
open func createTableView() -> UITableView {
|
||||
let tableView = UITableView(frame: .zero, style: .grouped)
|
||||
tableView.backgroundColor = .clear
|
||||
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
tableView.insetsContentViewsToSafeArea = false
|
||||
return tableView
|
||||
}
|
||||
|
||||
// Registers classes and nibs. Can subclass for different nibs. Can call super and then add new ones after as well.
|
||||
open func registerWithTable() {}
|
||||
|
||||
/// Sets the table to have no section headers or footers.
|
||||
open func setNoSectionHeadersFooters() {
|
||||
tableView.sectionHeaderHeight = CGFloat.leastNormalMagnitude
|
||||
tableView.sectionFooterHeight = CGFloat.leastNormalMagnitude
|
||||
}
|
||||
|
||||
/// For subclassing, returns the number of sections for table. This function calls numberOfSectionsForTableview aftre ensuring the table is setup properly.
|
||||
open func getNumberOfSections() -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
open func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return tableView.bounds.width > 1 ? getNumberOfSections() : 0
|
||||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
return UITableViewCell()
|
||||
}
|
||||
}
|
||||
109
MVMCoreUI/BaseControllers/ScrollingViewController.swift
Normal file
109
MVMCoreUI/BaseControllers/ScrollingViewController.swift
Normal file
@ -0,0 +1,109 @@
|
||||
//
|
||||
// ScrollingViewController.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/12/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class ScrollingViewController: ViewController {
|
||||
public var dismissKeyboardTapGesture: UITapGestureRecognizer?
|
||||
@IBOutlet public var scrollView: UIScrollView!
|
||||
public var contentView: UIView?
|
||||
public var contentWidthConstraint: NSLayoutConstraint?
|
||||
|
||||
private var keyboardNotificationsAdded = false
|
||||
private var keyboardIsShowing = false
|
||||
private var preKeyboardContentInset: UIEdgeInsets?
|
||||
|
||||
public init(with scrollView: UIScrollView) {
|
||||
self.scrollView = scrollView
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
|
||||
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
||||
}
|
||||
|
||||
// MARK: - View Life Cycle
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Adds the tap gesture to dismiss the keyboard.
|
||||
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput(sender:)))
|
||||
view.addGestureRecognizer(dismissKeyboardTapGesture!)
|
||||
dismissKeyboardTapGesture?.isEnabled = false
|
||||
scrollView.alwaysBounceVertical = false
|
||||
scrollView.delegate = self
|
||||
}
|
||||
|
||||
open override func updateViewConstraints() {
|
||||
super.updateViewConstraints()
|
||||
// Sets the width of the content to the width of the screen.
|
||||
contentWidthConstraint?.constant = view.bounds.width - scrollView.contentInset.left - scrollView.contentInset.right
|
||||
}
|
||||
|
||||
open override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
view.setNeedsUpdateConstraints()
|
||||
view.layoutSubviews()
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
registerForKeyboardNotifications()
|
||||
}
|
||||
|
||||
// MARK: - Keyboard Handling
|
||||
open func registerForKeyboardNotifications() {
|
||||
if !keyboardNotificationsAdded {
|
||||
keyboardNotificationsAdded = true
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
open func unregisterForKeyboardNotifications() {
|
||||
if keyboardNotificationsAdded {
|
||||
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
|
||||
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||
keyboardNotificationsAdded = false
|
||||
}
|
||||
}
|
||||
|
||||
@objc open func keyboardWillShow(notification: Notification) {
|
||||
// Stores the current scroll insets if the keyboard was hidden.
|
||||
if !keyboardIsShowing {
|
||||
preKeyboardContentInset = scrollView.contentInset
|
||||
}
|
||||
keyboardIsShowing = true
|
||||
|
||||
// Enables the tap gesture.
|
||||
dismissKeyboardTapGesture?.isEnabled = true
|
||||
|
||||
MVMCoreUIUtility.setScrollViewInsetForKeyboardShow(notification, scrollView: scrollView, viewController: self) { [weak self] () -> CGRect in
|
||||
return self?.rectToScrollToWhenKeyboardPopsUp() ?? .zero
|
||||
}
|
||||
}
|
||||
|
||||
@objc open func keyboardWillBeHidden(notification: Notification) {
|
||||
keyboardIsShowing = false
|
||||
|
||||
// Disables the tap gesture.
|
||||
dismissKeyboardTapGesture?.isEnabled = false
|
||||
|
||||
MVMCoreUIUtility.setScrollViewInsetForKeyboardHide(notification, scrollView: scrollView, viewController: self, contentInset: preKeyboardContentInset ?? scrollView.contentInset)
|
||||
}
|
||||
|
||||
open func rectToScrollToWhenKeyboardPopsUp() -> CGRect? {
|
||||
guard let field = selectedField,
|
||||
let parent = selectedField?.superview else { return nil }
|
||||
return scrollView.convert(field.frame, from: parent)
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import MVMAnimationFramework
|
||||
|
||||
open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||
open class ThreeLayerTableViewController: ProgrammaticTableViewController {
|
||||
// The three main views
|
||||
private var topView: UIView?
|
||||
private var bottomView: UIView?
|
||||
@ -36,8 +36,8 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||
self.tableView?.reloadData()
|
||||
}
|
||||
|
||||
open override func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
open override func handleNewData() {
|
||||
super.handleNewData()
|
||||
createViewForTableHeader()
|
||||
createViewForTableFooter()
|
||||
tableView?.reloadData()
|
||||
@ -45,8 +45,8 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||
|
||||
override open func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setToHaveNoSectionHeadersFooters()
|
||||
// Do any additional setup after loading the view.
|
||||
setNoSectionHeadersFooters()
|
||||
}
|
||||
|
||||
//MARK: - Spacing
|
||||
@ -227,26 +227,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||
return view
|
||||
}
|
||||
|
||||
//MARK: - Scrollview
|
||||
open override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
// To stop handscroll animation if animating after scroll
|
||||
stopHandScrollAnimation(true)
|
||||
}
|
||||
|
||||
deinit {
|
||||
tableView?.delegate = nil
|
||||
}
|
||||
|
||||
//MARK: - Animation
|
||||
open override func setupIntroAnimations() {
|
||||
if let topView = topView, topView.subviews.count > 0 {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView))
|
||||
}
|
||||
if let tableView = tableView {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.animateTableViewFadeInCells(tableView: tableView))
|
||||
}
|
||||
if let bottomView = bottomView, bottomView.subviews.count > 0 {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: bottomView))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,21 +61,25 @@ open class ThreeLayerViewController: ProgrammaticScrollViewController {
|
||||
}
|
||||
}
|
||||
|
||||
open override func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
|
||||
open override func handleNewData() {
|
||||
// Removes the views
|
||||
topView?.removeFromSuperview()
|
||||
middleView?.removeFromSuperview()
|
||||
bottomView?.removeFromSuperview()
|
||||
safeAreaView?.removeFromSuperview()
|
||||
MVMCoreUIStackableViewController.remove(contentView?.subviews)
|
||||
if let subViews = contentView?.subviews {
|
||||
for view in subViews {
|
||||
view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
// Reset constraints
|
||||
bottomConstraint?.isActive = true
|
||||
heightConstraint?.isActive = false
|
||||
|
||||
setupLayers()
|
||||
|
||||
super.handleNewData()
|
||||
}
|
||||
|
||||
//MARK:-Functions to subclass
|
||||
@ -241,18 +245,3 @@ extension ThreeLayerViewController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK:-Animation
|
||||
extension ThreeLayerViewController {
|
||||
open override func setupIntroAnimations() {
|
||||
if let topView = topView, topView.subviews.count > 0 {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: topView))
|
||||
}
|
||||
if let middleView = middleView, middleView.subviews.count > 0 {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: middleView))
|
||||
}
|
||||
if let bottomView = bottomView, bottomView.subviews.count > 0 {
|
||||
introAnimationManager?.addAnimation(animation: MVMAnimations.fadeUpAnimation(view: bottomView))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,19 +8,119 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class ViewController: UIViewController, MVMCoreViewControllerProtocol {
|
||||
public var pageType: String?
|
||||
public var loadObject: MVMCoreLoadObject?
|
||||
public var pageModel: PageModelProtocol?
|
||||
@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate {
|
||||
@objc public var pageType: String?
|
||||
@objc public var loadObject: MVMCoreLoadObject?
|
||||
public var pageModel: MVMControllerModelProtocol?
|
||||
|
||||
/// Set if this page is containted in a manager.
|
||||
public var manager: (UIViewController & MVMCoreViewManagerProtocol)?
|
||||
|
||||
// TODO: Change this logic once we convert the MVMCoreViewControllerProtocol to swift
|
||||
public var selfDelegateObject: MVMCoreUIDelegateObject?
|
||||
public func delegateObject() -> DelegateObject? {
|
||||
if selfDelegateObject == nil {
|
||||
selfDelegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self)
|
||||
}
|
||||
return selfDelegateObject
|
||||
}
|
||||
|
||||
public var formValidator: FormValidator?
|
||||
|
||||
public var needsUpdateUI = true
|
||||
private var observingForResponses = false
|
||||
private var initialLoadFinished = false
|
||||
private var previousScreenSize = CGSize.zero
|
||||
|
||||
public var selectedField: UIView?
|
||||
|
||||
// MARK: Response handling
|
||||
public func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
|
||||
/// Checks if the screen width has changed
|
||||
open func screenSizeChanged() -> Bool {
|
||||
return MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1)
|
||||
}
|
||||
|
||||
// MARK: - Response handling
|
||||
open func observeForResponseJSONUpdates() {
|
||||
guard !observingForResponses,
|
||||
(pagesToListenFor()?.count ?? 0 > 0 || modulesToListenFor()?.count ?? 0 > 0) else { return }
|
||||
observingForResponses = true
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(responseJSONUpdated(notification:)), name: NSNotification.Name(rawValue: NotificationResponseLoaded), object: nil)
|
||||
}
|
||||
|
||||
open func stopObservingForResponseJSONUpdates() {
|
||||
guard observingForResponses else { return }
|
||||
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NotificationResponseLoaded), object: nil)
|
||||
observingForResponses = false
|
||||
}
|
||||
|
||||
open func pagesToListenFor() -> [String]? {
|
||||
guard let pageType = loadObject?.pageType else { return nil }
|
||||
return [pageType]
|
||||
}
|
||||
|
||||
open func modulesToListenFor() -> [String]? {
|
||||
return loadObject?.requestParameters?.modules as? [String]
|
||||
}
|
||||
|
||||
@objc open func responseJSONUpdated(notification: Notification) {
|
||||
// Checks for a page we are listening for.
|
||||
var newData = false
|
||||
if let pagesLoaded = notification.userInfo?.optionalDictionaryForKey(KeyPageMap),
|
||||
let pageType = pagesToListenFor()?.first(where: { (pageTypeListened) -> Bool in
|
||||
guard let page = pagesLoaded.optionalDictionaryForKey(pageTypeListened),
|
||||
let pageType = page.optionalStringForKey(KeyPageType),
|
||||
pageType == pageTypeListened else { return false }
|
||||
return true
|
||||
}) {
|
||||
newData = true
|
||||
loadObject?.pageJSON = pagesLoaded.optionalDictionaryForKey(pageType)
|
||||
}
|
||||
|
||||
// Checks for modules we are listening for.
|
||||
if let modulesLoaded = notification.userInfo?.optionalDictionaryForKey(KeyModuleMap),
|
||||
let modulesListened = modulesToListenFor() {
|
||||
for moduleName in modulesListened {
|
||||
if let module = modulesLoaded.optionalDictionaryForKey(moduleName) {
|
||||
newData = true
|
||||
var currentModules = loadObject?.modulesJSON ?? [:]
|
||||
currentModules.updateValue(module, forKey: moduleName)
|
||||
loadObject?.modulesJSON = currentModules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard newData else { return }
|
||||
do {
|
||||
try parsePageJSON()
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
self.handleNewDataAndUpdateUI()
|
||||
// If the screen is showing, can update the navigation controller.
|
||||
if let navigationController = self.manager?.navigationController,
|
||||
self.manager!.getCurrentViewController() == self {
|
||||
self.set(navigationController: navigationController)
|
||||
} else if let navigationController = self.navigationController,
|
||||
self == MVMCoreUIUtility.getCurrentVisibleController() {
|
||||
self.set(navigationController: navigationController)
|
||||
}
|
||||
})
|
||||
} catch {
|
||||
if let coreError = MVMCoreErrorObject.createErrorObject(for: error, location: "updateJSON for pageType: \(String(describing: pageType))") {
|
||||
MVMCoreLoggingHandler.shared()?.addError(toLog: coreError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
|
||||
pageType = loadObject.pageType
|
||||
self.loadObject = loadObject
|
||||
|
||||
// Verifies all modules needed are loaded. TODO: change to ViewController
|
||||
guard MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) else { return false }
|
||||
|
||||
// Parse the model for the page.
|
||||
do {
|
||||
try parsePageJSON()
|
||||
return true
|
||||
} catch let parsingError {
|
||||
// Log all parsing errors and fail load.
|
||||
if let errorObject = MVMCoreErrorObject.createErrorObject(for: parsingError, location: MVMCoreLoadHandler.sharedGlobal()?.errorLocation(forRequest: loadObject)) {
|
||||
@ -29,15 +129,12 @@ import UIKit
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Verifies all modules needed are loaded.
|
||||
return MFViewController.verifyRequiredModulesLoaded(for: loadObject, error: error)
|
||||
}
|
||||
|
||||
@objc func parsePageJSON() throws {
|
||||
open func parsePageJSON() throws {
|
||||
}
|
||||
|
||||
public class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool {
|
||||
open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool {
|
||||
guard let pageType = loadObject?.pageType, var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType) else { return true }
|
||||
|
||||
guard let loadedModules = loadObject?.modulesJSON else { return false }
|
||||
@ -58,25 +155,268 @@ import UIKit
|
||||
return true
|
||||
}
|
||||
|
||||
open func setNavigationItem() {
|
||||
navigationItem.title = pageModel?.screenHeading
|
||||
navigationItem.accessibilityLabel = pageModel?.screenHeading
|
||||
/// Calls processNewData and then sets the ui to update with updateView
|
||||
open func handleNewDataAndUpdateUI() {
|
||||
handleNewData()
|
||||
self.needsUpdateUI = true
|
||||
self.view.setNeedsLayout()
|
||||
}
|
||||
|
||||
open func newDataBuildScreen() {
|
||||
// TODO atomize the navigation item
|
||||
setNavigationItem()
|
||||
/// Processes any new data. Called after the page is loaded the first time and on response updates for this page,
|
||||
open func handleNewData() {
|
||||
// TODO: remove legacy. Temporary, convert legacy to navigation model.
|
||||
var navigationModel = pageModel?.navigationItem ?? NavigationItemModel()
|
||||
navigationModel.title = pageModel?.screenHeading
|
||||
navigationModel.showLeftPanelButton = isMasterInitiallyAccessible()
|
||||
navigationModel.showRightPanelButton = isSupportInitiallyAccessible()
|
||||
if /*(self as? MVMCoreUITabBarPageControlViewController) != nil ||*/ manager != nil || loadObject?.requestParameters?.tabWasPressed ?? false == true {
|
||||
navigationModel.line = LineModel(type: .none)
|
||||
}
|
||||
pageModel?.navigationItem = navigationModel
|
||||
if self.formValidator == nil {
|
||||
let rules = pageModel?.formRules
|
||||
self.formValidator = FormValidator(rules)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Navigation Item (Move to model base)
|
||||
open func set(navigationController: UINavigationController?) {
|
||||
guard let navigationItemModel = pageModel?.navigationItem,
|
||||
let navigationController = navigationController else {
|
||||
MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate()
|
||||
return
|
||||
}
|
||||
if navigationController == MVMCoreUISplitViewController.main()?.navigationController,
|
||||
navigationController.topViewController == self {
|
||||
MVMCoreUISession.sharedGlobal()?.splitViewController?.setupPanels()
|
||||
showBottomProgressBar()
|
||||
}
|
||||
NavigationController.set(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: self)
|
||||
}
|
||||
|
||||
// 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 showBottomProgressBar() {
|
||||
if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self,
|
||||
let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent),
|
||||
let progress = Float(progressString) {
|
||||
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(progress / Float(100))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - View lifecycle
|
||||
open func initialLoad() {
|
||||
observeForResponseJSONUpdates()
|
||||
}
|
||||
|
||||
open func updateViews() {
|
||||
formValidator?.validate()
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "View Controller Loaded : \(self)")
|
||||
|
||||
// We use our own margins.
|
||||
viewRespectsSystemMinimumLayoutMargins = false
|
||||
|
||||
// Presents from the bottom.
|
||||
modalPresentationStyle = MVMCoreGetterUtility.isOnIPad() ? UIModalPresentationStyle.formSheet : UIModalPresentationStyle.overCurrentContext
|
||||
|
||||
// Do some initial loading.
|
||||
if !initialLoadFinished {
|
||||
initialLoadFinished = true
|
||||
initialLoad()
|
||||
}
|
||||
|
||||
// Handle data on load
|
||||
handleNewData()
|
||||
|
||||
view.setNeedsLayout()
|
||||
}
|
||||
|
||||
open override func viewDidLayoutSubviews() {
|
||||
// Add to fix a constraint bug where the width is zero and things get messed up.
|
||||
guard isViewLoaded,
|
||||
view.bounds.width > 1 else {
|
||||
super.viewDidLayoutSubviews()
|
||||
return
|
||||
}
|
||||
if needsUpdateUI || screenSizeChanged() {
|
||||
updateViews()
|
||||
needsUpdateUI = false
|
||||
}
|
||||
previousScreenSize = view.bounds.size;
|
||||
|
||||
super.viewDidLayoutSubviews()
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
// Update the navigation bar ui when view is appearing unless in a manager. The manager is expected to handle.
|
||||
if manager == nil {
|
||||
set(navigationController: navigationController)
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if manager == nil {
|
||||
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
||||
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopObservingForResponseJSONUpdates()
|
||||
MVMCoreLoggingHandler.logDebugMessage(withDelegate: "View Controller Deallocated : \(self)")
|
||||
}
|
||||
|
||||
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
return MVMCoreGetterUtility.isOnIPad() ? UIInterfaceOrientationMask.all : UIInterfaceOrientationMask.portrait
|
||||
}
|
||||
|
||||
open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
// Updates the detail view width
|
||||
coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
|
||||
}) { (UIViewControllerTransitionCoordinatorContext) in
|
||||
self.view.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||
open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||
if initialLoadFinished {
|
||||
set(navigationController: manager.navigationController)
|
||||
}
|
||||
// Janky way to track current page.
|
||||
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
||||
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreActionDelegateProtocol
|
||||
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) {
|
||||
formValidator?.addFormParams(requestParameters: requestParameters)
|
||||
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
|
||||
MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: selfDelegateObject)
|
||||
}
|
||||
|
||||
open func logAction(withActionInformation actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) {
|
||||
MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData)
|
||||
}
|
||||
|
||||
// MARK: - MoleculeDelegateProtocol
|
||||
open func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? {
|
||||
guard let name = name else { return nil }
|
||||
return loadObject?.modulesJSON?.optionalDictionaryForKey(name)
|
||||
}
|
||||
|
||||
open func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
|
||||
guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName),
|
||||
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
|
||||
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
|
||||
else { return nil }
|
||||
do {
|
||||
return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol
|
||||
} catch {
|
||||
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Needed otherwise when subclassed, the extension gets called.
|
||||
open func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {}
|
||||
open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { return nil }
|
||||
open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {}
|
||||
open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {}
|
||||
|
||||
// MARK: - UITextFieldDelegate (Check if this is still needed)
|
||||
// To Remove TextFields Bug: Keyboard is not dismissing after reaching textfield max length limit
|
||||
open func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
textField.resignFirstResponder()
|
||||
return true
|
||||
}
|
||||
|
||||
open func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
selectedField = textField
|
||||
|
||||
// TODO: Make this into a protocol
|
||||
if UIAccessibility.isVoiceOverRunning {
|
||||
if let toolBar = textField.inputAccessoryView as? UIToolbar, let _ = toolBar.items?.last, let pickerView = textField.inputView as? UIPickerView {
|
||||
view.accessibilityElements = [pickerView, toolBar]
|
||||
}
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField.inputView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
|
||||
if textField === selectedField {
|
||||
if UIAccessibility.isVoiceOverRunning {
|
||||
view.accessibilityElements = nil
|
||||
UIAccessibility.post(notification: UIAccessibility.Notification.layoutChanged, argument: textField)
|
||||
}
|
||||
selectedField = nil
|
||||
}
|
||||
}
|
||||
|
||||
@objc open func dismissFieldInput(sender: Any?) {
|
||||
selectedField?.resignFirstResponder()
|
||||
}
|
||||
|
||||
// MARK: - UITextViewDelegate (Check if this is still needed)
|
||||
open func textViewDidBeginEditing(_ textView: UITextView) {
|
||||
selectedField = textView
|
||||
}
|
||||
|
||||
open func textViewDidEndEditing(_ textView: UITextView) {
|
||||
if textView === selectedField {
|
||||
selectedField = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,4 +39,34 @@ import UIKit
|
||||
MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController)
|
||||
return navigationController
|
||||
}
|
||||
|
||||
public static func set(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: (UIViewController & MVMCoreViewControllerProtocol)) {
|
||||
viewController.navigationItem.title = navigationItemModel.title
|
||||
viewController.navigationItem.accessibilityLabel = navigationItemModel.title
|
||||
viewController.navigationItem.hidesBackButton = !navigationItemModel.systemBackButton
|
||||
|
||||
navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true)
|
||||
UIColor.setBackgroundColor(navigationItemModel.backgroundColor?.uiColor ?? .white, for: navigationController.navigationBar, isTransparent: navigationItemModel.transparent)
|
||||
|
||||
let tint = navigationItemModel.tintColor.uiColor
|
||||
navigationController.navigationBar.tintColor = tint
|
||||
|
||||
// Have the navigation title match the tint color
|
||||
navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor)
|
||||
|
||||
// Update icons if main navigation controller.
|
||||
if navigationController == MVMCoreUISession.sharedGlobal()?.navigationController,
|
||||
navigationController.topViewController == viewController {
|
||||
// Update line.
|
||||
MVMCoreUISession.sharedGlobal()?.navigationController?.separatorView?.set(with: navigationItemModel.line ?? LineModel(type: .standard), viewController.delegateObject?() as? MVMCoreUIDelegateObject, nil)
|
||||
}
|
||||
|
||||
if navigationController == MVMCoreUISplitViewController.main()?.navigationController,
|
||||
navigationController.topViewController == viewController {
|
||||
// Update Panels
|
||||
MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton ?? false, for: viewController)
|
||||
MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton ?? false, for: viewController)
|
||||
MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@
|
||||
self.selectedIndex = i;
|
||||
[tabbar selectIndex:self.selectedIndex animated:NO];
|
||||
|
||||
if ([self.viewController respondsToSelector:@selector(shouldCacheInManager)] && [((UIViewController <MVMCoreViewManagerViewControllerProtocol> *)self.viewController) shouldCacheInManager]) {
|
||||
if (![self.viewController respondsToSelector:@selector(shouldCacheInManager)] || [((UIViewController <MVMCoreViewManagerViewControllerProtocol> *)self.viewController) shouldCacheInManager]) {
|
||||
[viewControllers addObject:self.viewController];
|
||||
} else {
|
||||
[viewControllers addObject:[NSNull null]];
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
//
|
||||
// Validatable.swift
|
||||
// FormHolderModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 2/5/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// A protocol for the model of the delegate object that holds the form validator. The rules are stored in the model.
|
||||
|
||||
import Foundation
|
||||
|
||||
//Protocol for Validation
|
||||
public protocol FormProtocol: class {
|
||||
public protocol FormHolderModelProtocol {
|
||||
var formRules: [FormGroupRule]? { get set }
|
||||
var formValidator: FormValidator? { get set }
|
||||
}
|
||||
@ -5,13 +5,10 @@
|
||||
// Created by Suresh, Kamlesh on 2/26/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// A delegate object that holds the form validator.
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
//Protocol for Validation
|
||||
public protocol FormHolderProtocol: NSObjectProtocol {
|
||||
var formValidator: FormValidator? { get set }
|
||||
/// Should call formValidator's validate method
|
||||
func validate()
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ import MVMCore
|
||||
static var defaultGroupName: String = "default"
|
||||
var extraValidationBlock: (() -> Bool)?
|
||||
var formRules: [FormGroupRule]?
|
||||
var delegate: FormHolderProtocol?
|
||||
weak var delegate: FormHolderProtocol?
|
||||
var fieldMolecules: [String: FormFieldProtocol] = [:]
|
||||
var formActionMolecules: [FormActionFieldProtocol] = []
|
||||
var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:]
|
||||
|
||||
14
MVMCoreUI/FormUIHelpers/Rules/FormHolderModelProtocol.swift
Normal file
14
MVMCoreUI/FormUIHelpers/Rules/FormHolderModelProtocol.swift
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// FormHolderModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 2/5/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
// A protocol for the model of the delegate object that holds the form validator. The rules are stored in the model.
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol FormHolderModelProtocol {
|
||||
var formRules: [FormGroupRule]? { get set }
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// ProgrammaticScrollViewController.h
|
||||
// MFProgrammaticScrollViewController.h
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 1/26/16.
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#import <MVMCoreUI/MFScrollingViewController.h>
|
||||
|
||||
@interface ProgrammaticScrollViewController : MFScrollingViewController
|
||||
@interface MFProgrammaticScrollViewController : MFScrollingViewController
|
||||
|
||||
|
||||
@end
|
||||
@ -1,21 +1,21 @@
|
||||
//
|
||||
// ProgrammaticScrollViewController.m
|
||||
// MFProgrammaticScrollViewController.m
|
||||
// myverizon
|
||||
//
|
||||
// Created by Scott Pfeil on 1/26/16.
|
||||
// Copyright © 2016 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ProgrammaticScrollViewController.h"
|
||||
#import "MFProgrammaticScrollViewController.h"
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
#import "NSLayoutConstraint+MFConvenience.h"
|
||||
#import "MVMCoreUICommonViewsUtility.h"
|
||||
|
||||
@interface ProgrammaticScrollViewController ()
|
||||
@interface MFProgrammaticScrollViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation ProgrammaticScrollViewController
|
||||
@implementation MFProgrammaticScrollViewController
|
||||
|
||||
- (void)loadView {
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
#import <MVMCoreUI/ProgrammaticScrollViewController.h>
|
||||
#import <MVMCoreUI/MFProgrammaticScrollViewController.h>
|
||||
|
||||
@interface MVMCoreUIStackableViewController : ProgrammaticScrollViewController
|
||||
@interface MVMCoreUIStackableViewController : MFProgrammaticScrollViewController
|
||||
|
||||
// An array of ui elements that will be spaced out on the screen top to bottom from index 0 to formUIArray.count.
|
||||
@property (nullable, strong, nonatomic) NSArray *formUIArray;
|
||||
@ -48,7 +48,7 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[];
|
||||
#pragma mark - BaseControllers
|
||||
#import <MVMCoreUI/MFViewController.h>
|
||||
#import <MVMCoreUI/MFScrollingViewController.h>
|
||||
#import <MVMCoreUI/ProgrammaticScrollViewController.h>
|
||||
#import <MVMCoreUI/MFProgrammaticScrollViewController.h>
|
||||
#import <MVMCoreUI/MFProgrammaticTableViewController.h>
|
||||
#import <MVMCoreUI/MVMCoreUIStackableViewController.h>
|
||||
#import <MVMCoreUI/StackableViewController.h>
|
||||
|
||||
@ -2,13 +2,13 @@ import Foundation
|
||||
|
||||
|
||||
public protocol MoleculeModelProtocol: ModelProtocol {
|
||||
var moleculeName: String? { get }
|
||||
var moleculeName: String { get }
|
||||
var backgroundColor: Color? { get set }
|
||||
}
|
||||
|
||||
public extension MoleculeModelProtocol {
|
||||
|
||||
var moleculeName: String? {
|
||||
var moleculeName: String {
|
||||
get { return Self.identifier }
|
||||
}
|
||||
|
||||
|
||||
@ -13,4 +13,5 @@ public protocol PageModelProtocol {
|
||||
var pageType: String { get set }
|
||||
var screenHeading: String? { get set }
|
||||
var isAtomicTabs: Bool? { get set }
|
||||
var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set }
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormProtocol {
|
||||
public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol {
|
||||
var template: String { get }
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import Foundation
|
||||
@objcMembers public class DoughnutChartModel: MoleculeModelProtocol {
|
||||
public var backgroundColor: Color?
|
||||
public static var identifier: String = "doughnutChart"
|
||||
public var moleculeName: String? = DoughnutChartModel.identifier
|
||||
public var moleculeName: String = DoughnutChartModel.identifier
|
||||
public var title: LabelModel?
|
||||
public var subtitle: LabelModel?
|
||||
public var sections: [DoughnutChartItemModel]
|
||||
@ -25,7 +25,7 @@ import Foundation
|
||||
@objcMembers public class DoughnutChartItemModel: MoleculeModelProtocol {
|
||||
public var backgroundColor: Color?
|
||||
public static var identifier: String = "doughnutChartItem"
|
||||
public var moleculeName: String? = DoughnutChartItemModel.identifier
|
||||
public var moleculeName: String = DoughnutChartItemModel.identifier
|
||||
public var label: LabelModel
|
||||
@Percent public var percent: CGFloat
|
||||
public var color: Color
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
public struct ImageHeadlineBodyModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "imageHeadlineBody"
|
||||
public var moleculeName: String? = ImageHeadlineBodyModel.identifier
|
||||
public var moleculeName: String = ImageHeadlineBodyModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var image: ImageViewModel
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
@ -32,18 +32,14 @@ import UIKit
|
||||
override public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
accordionButton.isSelected = !accordionButton.isSelected
|
||||
accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal)
|
||||
guard let model = accordionListItemModel else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let json = model.toJSON(),
|
||||
let molecules = json.optionalArrayForKey("molecules") as? [[AnyHashable: Any]]
|
||||
else { return }
|
||||
guard let model = accordionListItemModel else { return }
|
||||
|
||||
if accordionButton.isSelected {
|
||||
delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: .automatic)
|
||||
if let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) {
|
||||
delegateObject?.moleculeDelegate?.addMolecules(model.molecules, indexPath: indexPath, animation: .automatic)
|
||||
}
|
||||
} else {
|
||||
delegateObject?.moleculeDelegate?.removeMolecules(molecules, sender: self, animation: .automatic)
|
||||
delegateObject?.moleculeDelegate?.removeMolecules(model.molecules, animation: .automatic)
|
||||
}
|
||||
|
||||
if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) {
|
||||
|
||||
@ -29,16 +29,16 @@ import UIKit
|
||||
guard newValue != oldValue,
|
||||
let self = self,
|
||||
let index = self.dropDown.pickerData.firstIndex(of: newValue),
|
||||
let dropListItemJSON = (self.listItemModel as? DropDownListItemModel).toJSON(),
|
||||
let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]],
|
||||
!json2d.isEmpty && !(json2d.first?.isEmpty ?? false)
|
||||
let model = self.listItemModel as? DropDownListItemModel
|
||||
else { return }
|
||||
|
||||
if self.previousIndex != NSNotFound {
|
||||
self.delegateObject?.moleculeDelegate?.removeMolecules(json2d[self.previousIndex], sender: self, animation: .fade)
|
||||
self.delegateObject?.moleculeDelegate?.removeMolecules(model.molecules[self.previousIndex], animation: .fade)
|
||||
}
|
||||
|
||||
self.delegateObject?.moleculeDelegate?.addMolecules(json2d[index], sender: self, animation: .fade)
|
||||
if let indexPath = self.delegateObject?.moleculeDelegate?.getIndexPath(for: model) {
|
||||
self.delegateObject?.moleculeDelegate?.addMolecules(model.molecules[index], indexPath: indexPath, animation: .fade)
|
||||
}
|
||||
self.previousIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,11 +116,10 @@ open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeVi
|
||||
|
||||
public class func nameForReuse(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let molecule = (model as? CarouselItemModel)?.molecule,
|
||||
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) as? ModelMoleculeViewProtocol.Type,
|
||||
let name = moleculeClass.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName else {
|
||||
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) as? ModelMoleculeViewProtocol.Type else {
|
||||
return nil
|
||||
}
|
||||
return name
|
||||
return moleculeClass.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
@objcMembers public class StackItemModel: ContainerModel, StackItemModelProtocol, MoleculeModelProtocol {
|
||||
public static var identifier: String = "simpleStackItem"
|
||||
public var moleculeName: String? = StackItemModel.identifier
|
||||
public var moleculeName: String = StackItemModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var spacing: CGFloat?
|
||||
public var percent: Int?
|
||||
|
||||
@ -54,23 +54,19 @@ import UIKit
|
||||
|
||||
extension TabsTableViewCell: TopTabbarDelegate {
|
||||
public func shouldSelectItem(at index: Int, topTabbar: TopTabbar) -> Bool {
|
||||
if let model = tabsListItemModel,
|
||||
let json = model.toJSON(),
|
||||
let json2d = json.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] {
|
||||
let molecules = json2d[topTabbar.selectedIndex]
|
||||
delegateObject?.moleculeDelegate?.removeMolecules(molecules, sender: self, animation: index < tabs.selectedIndex ? .right : .left)
|
||||
if let model = tabsListItemModel {
|
||||
let molecules = model.molecules[topTabbar.selectedIndex]
|
||||
delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: index < tabs.selectedIndex ? .right : .left)
|
||||
}
|
||||
previousTabIndex = tabs.selectedIndex
|
||||
return true
|
||||
}
|
||||
|
||||
public func topTabbar(_ topTabbar: TopTabbar, didSelectItemAt index: Int) {
|
||||
if let model = tabsListItemModel,
|
||||
let json = model.toJSON(),
|
||||
let json2d = json.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] {
|
||||
let molecules = json2d[index]
|
||||
delegateObject?.moleculeDelegate?.addMolecules(molecules, sender: self, animation: index < previousTabIndex ? .left : .right)
|
||||
}
|
||||
guard let model = tabsListItemModel,
|
||||
let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) else { return }
|
||||
let molecules = model.molecules[index]
|
||||
delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: indexPath, animation: index < previousTabIndex ? .left : .right)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
public struct ActionDetailWithImageModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "actionDetailWithImage"
|
||||
public var moleculeName: String? = ActionDetailWithImageModel.identifier
|
||||
public var moleculeName: String = ActionDetailWithImageModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var headlineBodyButton: HeadlineBodyButtonModel
|
||||
public var image: ImageViewModel
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
public struct HeadlineBodyLinkToggleModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "headlineBodyLinkToggle"
|
||||
public var moleculeName: String? = HeadlineBodyLinkToggleModel.identifier
|
||||
public var moleculeName: String = HeadlineBodyLinkToggleModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var headlineBodyLink: HeadlineBodyLinkModel
|
||||
public var toggle: ToggleModel
|
||||
|
||||
@ -11,7 +11,7 @@ import Foundation
|
||||
|
||||
open class HeadlineBodyToggleModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "headlineBodyToggle"
|
||||
public var moleculeName: String? = HeadlineBodyToggleModel.identifier
|
||||
public var moleculeName: String = HeadlineBodyToggleModel.identifier
|
||||
open var backgroundColor: Color?
|
||||
open var headlineBody: HeadlineBodyModel
|
||||
open var toggle: ToggleModel
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
public class LabelToggleModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "labelToggle"
|
||||
public var moleculeName: String? = LabelToggleModel.identifier
|
||||
public var moleculeName: String = LabelToggleModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var label: LabelModel
|
||||
public var toggle: ToggleModel
|
||||
|
||||
125
MVMCoreUI/Molecules/NavigationItemModelProtocol.swift
Normal file
125
MVMCoreUI/Molecules/NavigationItemModelProtocol.swift
Normal file
@ -0,0 +1,125 @@
|
||||
//
|
||||
// NavigationItemModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/12/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol NavigationItemModelProtocol {
|
||||
var title: String? { get set }
|
||||
var titleView: MoleculeModelProtocol? { get set }
|
||||
var hidden: Bool { get set }
|
||||
var backgroundColor: Color? { get set }
|
||||
var transparent: Bool { get set }
|
||||
var tintColor: Color { get set }
|
||||
var line: LineModel? { get set }
|
||||
var systemBackButton: Bool { get set }
|
||||
var showLeftPanelButton: Bool? { get set }
|
||||
var showRightPanelButton: Bool? { get set }
|
||||
var additionalLeftItems: [NavigationItemButtonModel]? { get set }
|
||||
var additionalRightItems: [NavigationItemButtonModel]? { get set }
|
||||
}
|
||||
|
||||
public class NavigationItemButtonModel: Codable {
|
||||
var imageName: String
|
||||
var action: ActionModelProtocol
|
||||
|
||||
public init(with imageName: String, action: ActionModelProtocol) {
|
||||
self.imageName = imageName
|
||||
self.action = action
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case imageName
|
||||
case action
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
imageName = try typeContainer.decode(String.self, forKey: .imageName)
|
||||
action = try typeContainer.decodeModel(codingKey: .action)
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(imageName, forKey: .imageName)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
}
|
||||
}
|
||||
|
||||
public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
|
||||
public class var identifier: String {
|
||||
return "navigationItem"
|
||||
}
|
||||
|
||||
public var title: String?
|
||||
public var titleView: MoleculeModelProtocol?
|
||||
public var hidden: Bool
|
||||
public var backgroundColor: Color?
|
||||
public var transparent: Bool
|
||||
public var tintColor: Color
|
||||
public var line: LineModel?
|
||||
public var systemBackButton = false
|
||||
public var showLeftPanelButton: Bool?
|
||||
public var showRightPanelButton: Bool?
|
||||
public var additionalLeftItems: [NavigationItemButtonModel]?
|
||||
public var additionalRightItems: [NavigationItemButtonModel]?
|
||||
|
||||
init() {
|
||||
hidden = false
|
||||
transparent = false
|
||||
backgroundColor = Color(uiColor: .white)
|
||||
tintColor = Color(uiColor: .black)
|
||||
line = LineModel(type: .standard)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case title
|
||||
case titleView
|
||||
case hidden
|
||||
case backgroundColor
|
||||
case transparent
|
||||
case tintColor
|
||||
case line
|
||||
case systemBackButton
|
||||
case showLeftPanelButton
|
||||
case showRightPanelButton
|
||||
case additionalLeftItems
|
||||
case additionalRightItems
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
|
||||
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
|
||||
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white)
|
||||
transparent = try typeContainer.decodeIfPresent(Bool.self, forKey: .transparent) ?? false
|
||||
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black)
|
||||
line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line)
|
||||
systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false
|
||||
showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton)
|
||||
showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton)
|
||||
additionalLeftItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftItems)
|
||||
additionalRightItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightItems)
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(title, forKey: .title)
|
||||
try container.encodeModelIfPresent(titleView, forKey: .titleView)
|
||||
try container.encode(hidden, forKey: .hidden)
|
||||
try container.encode(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(transparent, forKey: .transparent)
|
||||
try container.encode(tintColor, forKey: .tintColor)
|
||||
try container.encodeIfPresent(line, forKey: .line)
|
||||
try container.encode(systemBackButton, forKey: .systemBackButton)
|
||||
try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton)
|
||||
try container.encode(showRightPanelButton, forKey: .showRightPanelButton)
|
||||
try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems)
|
||||
try container.encodeIfPresent(additionalRightItems, forKey: .additionalRightItems)
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,6 @@ import UIKit
|
||||
|
||||
public class ScrollerModel: MoleculeContainerModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "scroller"
|
||||
public var moleculeName: String? = ScrollerModel.identifier
|
||||
public var moleculeName: String = ScrollerModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "eyebrowHeadlineBodyLink"
|
||||
public var moleculeName: String? = EyebrowHeadlineBodyLinkModel.identifier
|
||||
public var moleculeName: String = EyebrowHeadlineBodyLinkModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var eyebrow: LabelModel?
|
||||
public var headline: LabelModel?
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
public struct HeadlineBodyButtonModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "headlineBodyButton"
|
||||
public var moleculeName: String? = HeadlineBodyButtonModel.identifier
|
||||
public var moleculeName: String = HeadlineBodyButtonModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
public struct HeadlineBodyLinkModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "headlineBodyLink"
|
||||
public var moleculeName: String? = HeadlineBodyLinkModel.identifier
|
||||
public var moleculeName: String = HeadlineBodyLinkModel.identifier
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
public var link: LinkModel
|
||||
public var backgroundColor: Color?
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
@objcMembers open class HeadlineBodyModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "headlineBody"
|
||||
public var moleculeName: String? = HeadlineBodyModel.identifier
|
||||
public var moleculeName: String = HeadlineBodyModel.identifier
|
||||
public var headline: LabelModel?
|
||||
public var body: LabelModel?
|
||||
public var style: String?
|
||||
|
||||
@ -14,8 +14,7 @@ open class StringAndMoleculeStack: MoleculeStackView {
|
||||
guard let model = stackModel else { return }
|
||||
for stackItemModel in model.molecules {
|
||||
guard let stringAndMoleculeModel = stackItemModel.molecule as? StringAndMoleculeModel,
|
||||
let moleculeName = stringAndMoleculeModel.molecule.moleculeName,
|
||||
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forName: moleculeName) as? (UIView & ModelMoleculeViewProtocol) else {
|
||||
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forName: stringAndMoleculeModel.molecule.moleculeName) as? (UIView & ModelMoleculeViewProtocol) else {
|
||||
// Throw error
|
||||
return
|
||||
}
|
||||
|
||||
@ -158,11 +158,10 @@ open class Carousel: View {
|
||||
// MARK: - Convenience
|
||||
/// Returns the (identifier, class) of the molecule for the given map.
|
||||
func getMoleculeInfo(with molecule: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
|
||||
guard let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) ,
|
||||
let moleculeName = (className as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName else {
|
||||
guard let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule) else {
|
||||
return nil
|
||||
}
|
||||
return (moleculeName, className, molecule)
|
||||
return ((className as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: molecule, delegateObject) ?? molecule.moleculeName, className, molecule)
|
||||
}
|
||||
|
||||
/// Sets the alignment from the string.
|
||||
|
||||
@ -162,13 +162,11 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
}
|
||||
var name = "stack<"
|
||||
for case let item in model.molecules {
|
||||
if let moleculeName = item.moleculeName {
|
||||
if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[moleculeName] as? ModelMoleculeViewProtocol.Type,
|
||||
let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) {
|
||||
name.append(nameForReuse + ",")
|
||||
} else {
|
||||
name.append(moleculeName + ",")
|
||||
}
|
||||
if let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping[item.moleculeName] as? ModelMoleculeViewProtocol.Type,
|
||||
let nameForReuse = moleculeClass.nameForReuse(with: item, delegateObject) {
|
||||
name.append(nameForReuse + ",")
|
||||
} else {
|
||||
name.append(item.moleculeName + ",")
|
||||
}
|
||||
}
|
||||
name.append(">")
|
||||
|
||||
@ -13,7 +13,7 @@ open class MVMCoreUIDelegateObject: DelegateObject {
|
||||
public weak var buttonDelegate: ButtonDelegateProtocol?
|
||||
public weak var uiTextFieldDelegate: UITextFieldDelegate?
|
||||
public weak var observingTextFieldDelegate: ObservingTextFieldDelegate?
|
||||
public var moleculeDelegate: MoleculeDelegateProtocol?
|
||||
public weak var moleculeDelegate: MoleculeDelegateProtocol?
|
||||
|
||||
open override func setAll(withDelegate delegate: Any) {
|
||||
super.setAll(withDelegate: delegate)
|
||||
|
||||
@ -14,11 +14,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@interface MVMCoreUILoggingHandler : MVMCoreLoggingHandler
|
||||
|
||||
// Page State Logging
|
||||
- (void)defaultLogPageStateForController:(nonnull MFViewController *)controller;
|
||||
- (void)defaultLogPageStateForController:(nonnull id <MVMCoreViewControllerProtocol>)controller;
|
||||
|
||||
// Action Logging
|
||||
- (void)defaultLogActionForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;
|
||||
- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;
|
||||
- (void)defaultLogActionForController:(nonnull id <MVMCoreViewControllerProtocol>)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;
|
||||
- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull id <MVMCoreViewControllerProtocol>)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -10,13 +10,13 @@
|
||||
|
||||
@implementation MVMCoreUILoggingHandler
|
||||
|
||||
- (void)defaultLogPageStateForController:(nonnull MFViewController *)controller {
|
||||
- (void)defaultLogPageStateForController:(nonnull id <MVMCoreViewControllerProtocol>)controller {
|
||||
}
|
||||
|
||||
- (void)defaultLogActionForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
|
||||
- (void)defaultLogActionForController:(nonnull id <MVMCoreViewControllerProtocol>)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
|
||||
}
|
||||
|
||||
- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull MFViewController *)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
|
||||
- (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nonnull id <MVMCoreViewControllerProtocol>)controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData {
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
@ -16,10 +16,7 @@ public extension MVMCoreUIMoleculeMappingObject {
|
||||
}
|
||||
|
||||
func getMoleculeClass(_ model: MoleculeModelProtocol) -> AnyClass? {
|
||||
if let moleculeName = model.moleculeName {
|
||||
return moleculeMapping.object(forKey: moleculeName) as? AnyClass
|
||||
}
|
||||
return nil
|
||||
return moleculeMapping.object(forKey: model.moleculeName) as? AnyClass
|
||||
}
|
||||
|
||||
func createMolecule(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> (UIView & MVMCoreUIMoleculeViewProtocol)? {
|
||||
@ -27,8 +24,7 @@ public extension MVMCoreUIMoleculeMappingObject {
|
||||
}
|
||||
|
||||
func createMolecule(_ model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ constrainIfNeeded: Bool) -> (UIView & MVMCoreUIMoleculeViewProtocol)? {
|
||||
guard let moleculeName = model.moleculeName,
|
||||
let molecule = createMolecule(forName: moleculeName) else {
|
||||
guard let molecule = createMolecule(forName: model.moleculeName) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol MoleculeDelegateProtocol {
|
||||
public protocol MoleculeDelegateProtocol: AnyObject {
|
||||
|
||||
/// returns a module for the corresponding module name.
|
||||
func getModuleWithName(_ name: String?) -> [AnyHashable : Any]?
|
||||
@ -18,39 +18,16 @@ public protocol MoleculeDelegateProtocol {
|
||||
func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) //optional
|
||||
|
||||
/// Asks the delegate to add or remove molecules.
|
||||
//optional
|
||||
func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation)
|
||||
func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation)
|
||||
|
||||
func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation)
|
||||
|
||||
//optional
|
||||
func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation)
|
||||
func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation)
|
||||
func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath?
|
||||
func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation)
|
||||
func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation)
|
||||
}
|
||||
|
||||
extension MoleculeDelegateProtocol {
|
||||
public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
public func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {}
|
||||
|
||||
public func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
public func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { return nil }
|
||||
public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {}
|
||||
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class ListPageTemplateModel: TemplateModelProtocol {
|
||||
@objcMembers public class ListPageTemplateModel: MVMControllerModelProtocol {
|
||||
|
||||
public var formRules: [FormGroupRule]?
|
||||
public var formValidator: FormValidator?
|
||||
@ -22,6 +22,7 @@ import Foundation
|
||||
public var pageType: String
|
||||
public var screenHeading: String?
|
||||
public var isAtomicTabs: Bool?
|
||||
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
|
||||
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||
|
||||
@ -12,10 +12,10 @@ open class ModalMoleculeListTemplate: MoleculeListTemplate {
|
||||
|
||||
public var closeButton: MFCustomButton?
|
||||
|
||||
override open func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
override open func handleNewData() {
|
||||
super.handleNewData()
|
||||
closeButton = MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: { [weak self] _ in
|
||||
self?.dismiss()
|
||||
MVMCoreNavigationHandler.shared()?.removeCurrentViewController()
|
||||
}, verticalCentered: false)
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,10 +10,12 @@ import UIKit
|
||||
|
||||
open class ModalMoleculeStackTemplate: MoleculeStackTemplate {
|
||||
|
||||
override open func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
override open func handleNewData() {
|
||||
super.handleNewData()
|
||||
MVMCoreUICommonViewsUtility.addCloseButton(to: view, action: {[weak self] _ in
|
||||
self?.dismiss()
|
||||
if let _ = self {
|
||||
MVMCoreNavigationHandler.shared()?.removeCurrentViewController()
|
||||
}
|
||||
}, verticalCentered: false)
|
||||
}
|
||||
|
||||
|
||||
@ -12,12 +12,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
//--------------------------------------------------
|
||||
// MARK: - Stored Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public var formValidator: FormValidator?
|
||||
public func validate() {
|
||||
// Can override
|
||||
}
|
||||
|
||||
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]?
|
||||
|
||||
var observer: NSKeyValueObservation?
|
||||
@ -27,13 +21,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func parsePageJSON(_ error: NSErrorPointer) {
|
||||
do {
|
||||
try parseTemplateJSON()
|
||||
} catch let parseError {
|
||||
error?.pointee = parseError as NSError
|
||||
}
|
||||
open override func parsePageJSON() throws {
|
||||
try parseTemplate(json: loadObject?.pageJSON)
|
||||
try super.parsePageJSON()
|
||||
}
|
||||
|
||||
open override var loadObject: MVMCoreLoadObject? {
|
||||
@ -90,8 +80,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
return true
|
||||
}
|
||||
|
||||
open override func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
open override func handleNewData() {
|
||||
super.handleNewData()
|
||||
setup()
|
||||
registerWithTable()
|
||||
}
|
||||
@ -109,7 +99,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
open override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
guard let moleculeInfo = moleculesInfo?[indexPath.row],
|
||||
let estimatedHeight = (moleculeInfo.class as? ModelMoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject)
|
||||
else { return 0 }
|
||||
@ -127,47 +117,34 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier)
|
||||
else { return UITableViewCell() }
|
||||
|
||||
let delegate = delegateObject() as? MVMCoreUIDelegateObject
|
||||
let moleculeCell = cell as? MVMCoreUIMoleculeViewProtocol
|
||||
moleculeCell?.reset?()
|
||||
|
||||
if let protocolCell = cell as? MoleculeListCellProtocol {
|
||||
protocolCell.setLines(with: templateModel?.line, delegateObject: delegate, additionalData: nil, indexPath: indexPath)
|
||||
protocolCell.setLines(with: templateModel?.line, delegateObject: selfDelegateObject, additionalData: nil, indexPath: indexPath)
|
||||
}
|
||||
|
||||
(moleculeCell as? ModelMoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegate, nil)
|
||||
(moleculeCell as? ModelMoleculeViewProtocol)?.set(with: moleculeInfo.molecule, selfDelegateObject, nil)
|
||||
moleculeCell?.updateView(tableView.bounds.width)
|
||||
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
|
||||
cell.layoutIfNeeded()
|
||||
return cell
|
||||
}
|
||||
|
||||
open override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
|
||||
if let protocolCell = cell as? MoleculeListCellProtocol {
|
||||
protocolCell.willDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
||||
if let cell = tableView.cellForRow(at: indexPath) as? MoleculeListCellProtocol {
|
||||
cell.didSelectCell(at: indexPath, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Cache Handling
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func pageTypesToListenFor() -> [Any]? {
|
||||
guard let pageType = self.pageType else { return super.pageTypesToListenFor() }
|
||||
return [pageType]
|
||||
}
|
||||
|
||||
open override func modulesToListenFor() -> [Any]? {
|
||||
return loadObject?.requestParameters?.modules
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - MoleculeDelegateProtocol
|
||||
//--------------------------------------------------
|
||||
@ -183,76 +160,18 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
open override func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]()
|
||||
|
||||
molecules.forEach { molecule in
|
||||
if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(MoleculeListItemModel.self, from: data) {
|
||||
tmpMolecules.append(listItemModel)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
var indexPaths: [IndexPath] = []
|
||||
|
||||
for molecule in tmpMolecules {
|
||||
if let info = self.getMoleculeInfo(with: molecule) {
|
||||
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
||||
let index = indexPath.row + 1 + indexPaths.count
|
||||
self.moleculesInfo?.insert(info, at: index)
|
||||
indexPaths.append(IndexPath(row: index, section: 0))
|
||||
}
|
||||
}
|
||||
|
||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||
self.updateViewConstraints()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
open override func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||
//TODO: check for molecule protocola eqaulity
|
||||
let json = moleculeInfo.molecule.toJSON()
|
||||
return json == molecule.toJSON()
|
||||
}) else { return nil }
|
||||
return IndexPath(row: index, section: 0)
|
||||
}
|
||||
|
||||
open override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let indexPath = self?.tableView?.indexPath(for: sender) else { return }
|
||||
DispatchQueue.global().async {
|
||||
self?.addMolecules(molecules, indexPath: indexPath, animation: animation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]()
|
||||
|
||||
molecules.forEach { molecule in
|
||||
if let data = try? JSONSerialization.data(withJSONObject: molecule),
|
||||
let listItemModel = try? JSONDecoder().decode(MoleculeListItemModel.self, from: data) {
|
||||
tmpMolecules.append(listItemModel)
|
||||
}
|
||||
}
|
||||
|
||||
var indexPaths: [IndexPath] = []
|
||||
|
||||
//TODO: cehck for molecule protocola eqality
|
||||
|
||||
for molecule in tmpMolecules {
|
||||
if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
|
||||
|
||||
moleculesInfo?.remove(at: removeIndex)
|
||||
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
|
||||
}
|
||||
}
|
||||
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
updateViewConstraints()
|
||||
view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
open override func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
|
||||
DispatchQueue.main.async {
|
||||
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
|
||||
var indexPaths: [IndexPath] = []
|
||||
|
||||
for molecule in molecules {
|
||||
@ -264,16 +183,16 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
guard indexPaths.count > 0 else { return }
|
||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||
self.updateViewConstraints()
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {
|
||||
var indexPaths: [IndexPath] = []
|
||||
//TODO: cehck for molecule protocola eqality
|
||||
//TODO: check for molecule protocola equality
|
||||
|
||||
for molecule in molecules {
|
||||
if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
|
||||
@ -282,6 +201,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
guard indexPaths.count > 0 else { return }
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
updateViewConstraints()
|
||||
view.layoutIfNeeded()
|
||||
@ -295,10 +215,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
func getMoleculeInfo(with listItem: (ListItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: ListItemModelProtocol & MoleculeModelProtocol)? {
|
||||
|
||||
guard let listItem = listItem,
|
||||
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem),
|
||||
let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName
|
||||
else { return nil }
|
||||
|
||||
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem) else { return nil }
|
||||
let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName
|
||||
return (moleculeName, moleculeClass, listItem)
|
||||
}
|
||||
|
||||
|
||||
@ -9,20 +9,12 @@
|
||||
import UIKit
|
||||
|
||||
open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
public func validate() {
|
||||
|
||||
}
|
||||
|
||||
public var formValidator: FormValidator?
|
||||
|
||||
var observer: NSKeyValueObservation?
|
||||
public var templateModel: StackPageTemplateModel?
|
||||
open override func parsePageJSON(_ error: NSErrorPointer) {
|
||||
do {
|
||||
try parseTemplateJSON()
|
||||
} catch let parseError {
|
||||
error?.pointee = parseError as NSError
|
||||
}
|
||||
|
||||
open override func parsePageJSON() throws {
|
||||
try parseTemplate(json: loadObject?.pageJSON)
|
||||
try super.parsePageJSON()
|
||||
}
|
||||
|
||||
open override var loadObject: MVMCoreLoadObject? {
|
||||
@ -73,17 +65,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
}
|
||||
|
||||
// MARK: - cache handling
|
||||
open override func pageTypesToListenFor() -> [Any]? {
|
||||
guard let pageType = self.pageType else {
|
||||
return super.pageTypesToListenFor()
|
||||
}
|
||||
return [pageType]
|
||||
}
|
||||
|
||||
open override func modulesToListenFor() -> [Any]? {
|
||||
return loadObject?.requestParameters?.modules
|
||||
}
|
||||
|
||||
|
||||
/// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map.
|
||||
open func updateRequiredModules() {
|
||||
if let requiredModules = requiredModules(), let pageType = pageType {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class StackCenteredPageTemplateModel: TemplateModelProtocol {
|
||||
@objcMembers public class StackCenteredPageTemplateModel: MVMControllerModelProtocol {
|
||||
|
||||
public var formRules: [FormGroupRule]?
|
||||
public var formValidator: FormValidator?
|
||||
@ -17,6 +17,7 @@ import Foundation
|
||||
public var pageType: String
|
||||
public var screenHeading: String?
|
||||
public var isAtomicTabs: Bool?
|
||||
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
|
||||
|
||||
public init(pageType: String) {
|
||||
self.pageType = pageType
|
||||
|
||||
@ -9,23 +9,18 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class StackPageTemplateModel: TemplateModelProtocol {
|
||||
public var formRules: [FormGroupRule]?
|
||||
public var formValidator: FormValidator?
|
||||
|
||||
public static var identifier: String = "stack"
|
||||
|
||||
public var pageType: String
|
||||
public var screenHeading: String?
|
||||
public var isAtomicTabs: Bool?
|
||||
@objcMembers public class StackPageTemplateModel: TemplateModel {
|
||||
public override class var identifier: String {
|
||||
return "stack"
|
||||
}
|
||||
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var moleculeStack: MoleculeStackModel
|
||||
public var footer: MoleculeModelProtocol?
|
||||
|
||||
public init(pageType: String, moleculeStack: MoleculeStackModel) {
|
||||
self.pageType = pageType
|
||||
self.moleculeStack = moleculeStack
|
||||
super.init(pageType: pageType)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
@ -35,30 +30,23 @@ import Foundation
|
||||
case header
|
||||
case footer
|
||||
case stack
|
||||
case isAtomicTabs
|
||||
case formRules
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
pageType = try typeContainer.decode(String.self, forKey: .pageType)
|
||||
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack)
|
||||
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
|
||||
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
|
||||
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
|
||||
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
|
||||
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(pageType, forKey: .pageType)
|
||||
try container.encode(template, forKey: .template)
|
||||
try container.encode(moleculeStack, forKey: .stack)
|
||||
try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
|
||||
try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs)
|
||||
try container.encodeModelIfPresent(header, forKey: .header)
|
||||
try container.encodeModelIfPresent(footer, forKey: .footer)
|
||||
try container.encodeIfPresent(formRules, forKey: .formRules)
|
||||
}
|
||||
}
|
||||
|
||||
50
MVMCoreUI/Templates/TemplateModel.swift
Normal file
50
MVMCoreUI/Templates/TemplateModel.swift
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// TemplateModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/13/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class TemplateModel: MVMControllerModelProtocol {
|
||||
public class var identifier: String {
|
||||
return ""
|
||||
}
|
||||
public var pageType: String
|
||||
public var screenHeading: String?
|
||||
public var isAtomicTabs: Bool?
|
||||
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
|
||||
public var formRules: [FormGroupRule]?
|
||||
|
||||
public init(pageType: String) {
|
||||
self.pageType = pageType
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case pageType
|
||||
case screenHeading
|
||||
case isAtomicTabs
|
||||
case formRules
|
||||
case navigationItem
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
pageType = try typeContainer.decode(String.self, forKey: .pageType)
|
||||
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
|
||||
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
|
||||
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
|
||||
navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(pageType, forKey: .pageType)
|
||||
try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
|
||||
try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs)
|
||||
try container.encodeIfPresent(formRules, forKey: .formRules)
|
||||
try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem)
|
||||
}
|
||||
}
|
||||
@ -9,22 +9,18 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public protocol TemplateProtocol: FormHolderProtocol {
|
||||
public protocol TemplateProtocol: class {
|
||||
associatedtype TemplateModel: TemplateModelProtocol
|
||||
var templateModel: TemplateModel? { get set }
|
||||
}
|
||||
|
||||
public extension TemplateProtocol where Self: MFViewController {
|
||||
func parseTemplateJSON() throws {
|
||||
guard let pageJSON = self.loadObject?.pageJSON else { return }
|
||||
public extension TemplateProtocol where Self: ViewController {
|
||||
func parseTemplate(json: [AnyHashable: Any]?) throws {
|
||||
guard let pageJSON = json else { return }
|
||||
let data = try JSONSerialization.data(withJSONObject: pageJSON)
|
||||
let decoder = JSONDecoder()
|
||||
let templateModel = try decoder.decode(TemplateModel.self, from: data)
|
||||
|
||||
if self.formValidator == nil {
|
||||
let rules = templateModel.formRules
|
||||
self.formValidator = FormValidator(rules)
|
||||
}
|
||||
self.templateModel = templateModel
|
||||
self.pageModel = templateModel as? MVMControllerModelProtocol
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class ThreeLayerPageTemplateModel: TemplateModelProtocol {
|
||||
@objcMembers public class ThreeLayerPageTemplateModel: MVMControllerModelProtocol {
|
||||
|
||||
public var formRules: [FormGroupRule]?
|
||||
public var formValidator: FormValidator?
|
||||
@ -18,6 +18,7 @@ import Foundation
|
||||
public var pageType: String
|
||||
public var screenHeading: String?
|
||||
public var isAtomicTabs: Bool?
|
||||
public var navigationItem: (NavigationItemModelProtocol & MoleculeModelProtocol)?
|
||||
|
||||
public var header: MoleculeModelProtocol?
|
||||
public var middle: MoleculeModelProtocol?
|
||||
|
||||
@ -9,20 +9,11 @@
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
public func validate() {
|
||||
|
||||
}
|
||||
|
||||
public var formValidator: FormValidator?
|
||||
|
||||
public var templateModel: ThreeLayerPageTemplateModel?
|
||||
|
||||
open override func parsePageJSON(_ error: NSErrorPointer) {
|
||||
do {
|
||||
try parseTemplateJSON()
|
||||
} catch let parseError {
|
||||
error?.pointee = parseError as NSError
|
||||
}
|
||||
open override func parsePageJSON() throws {
|
||||
try parseTemplate(json: loadObject?.pageJSON)
|
||||
try super.parsePageJSON()
|
||||
}
|
||||
|
||||
override open func viewDidLoad() {
|
||||
@ -31,8 +22,8 @@ import UIKit
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
open override func newDataBuildScreen() {
|
||||
super.newDataBuildScreen()
|
||||
open override func handleNewData() {
|
||||
super.handleNewData()
|
||||
heightConstraint?.isActive = true
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
//
|
||||
// MVMCoreUICommonViewsUtility+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/23/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension MVMCoreUICommonViewsUtility {
|
||||
static func getToolbarWithDoneButton(delegate: ObservingTextFieldDelegate) -> UIToolbar {
|
||||
let toolbar = self.makeEmptyToolbar()
|
||||
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
|
||||
let button = UIBarButtonItem(barButtonSystemItem: .done, target: delegate, action: #selector(ObservingTextFieldDelegate.dismissFieldInput(sender:)))
|
||||
button.tintColor = .black
|
||||
toolbar.setItems([space, button], animated: false)
|
||||
return toolbar
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// Returns the margins for a view.
|
||||
+ (UIEdgeInsets)getMarginsForView:(nullable UIView *)view;
|
||||
|
||||
/// Gets the current visible view controller. Checks presented view controllers first, and then it checks on the NavigationController in the session object.
|
||||
+ (UIViewController *)getCurrentVisibleController;
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
+ (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom;
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#import "MVMCoreUIConstants.h"
|
||||
#import "MVMCoreUISession.h"
|
||||
#import "MVMCoreUISplitViewController.h"
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
@import MVMCore.MVMCoreNavigationHandler;
|
||||
@import MVMCore.MVMCoreGetterUtility;
|
||||
|
||||
@ -60,6 +61,26 @@
|
||||
return UIEdgeInsetsMake(view.directionalLayoutMargins.top, view.directionalLayoutMargins.leading, view.directionalLayoutMargins.bottom, view.directionalLayoutMargins.trailing);
|
||||
}
|
||||
|
||||
+ (UIViewController *)getCurrentVisibleController {
|
||||
UIViewController *baseViewController = [MVMCoreNavigationHandler sharedNavigationHandler].viewControllerToPresentOn ?: [UIApplication sharedApplication].keyWindow.rootViewController;
|
||||
UIViewController *viewController = nil;
|
||||
while (baseViewController.presentedViewController && !baseViewController.presentedViewController.isBeingDismissed) {
|
||||
viewController = baseViewController.presentedViewController;
|
||||
baseViewController = viewController;
|
||||
}
|
||||
if ([viewController isKindOfClass:[UINavigationController class]]) {
|
||||
viewController = ((UINavigationController *)viewController).topViewController;
|
||||
}
|
||||
// if it is not presented viewcontroller, existing BAU logic will be working
|
||||
if (!viewController) {
|
||||
viewController = [MVMCoreUISession sharedGlobal].navigationController.topViewController;
|
||||
if ([viewController conformsToProtocol:@protocol(MVMCoreViewManagerProtocol)]) {
|
||||
viewController = [viewController performSelector:@selector(getCurrentViewController)];
|
||||
}
|
||||
}
|
||||
return viewController;
|
||||
}
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
+ (void)setMarginsForView:(nullable UIView *)view leading:(CGFloat)leading top:(CGFloat)top trailing:(CGFloat)trailing bottom:(CGFloat)bottom {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user