Merge branch 'feature/add_remove_behavior' into 'develop'
Feature/add remove behavior See merge request BPHV_MIPS/mvm_core_ui!724
This commit is contained in:
commit
f23794bb59
@ -387,6 +387,7 @@
|
|||||||
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; };
|
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; };
|
||||||
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; };
|
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; };
|
||||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */; };
|
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */; };
|
||||||
|
D270E5672642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270E5662642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift */; };
|
||||||
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D272F5F82473163100BD1A8F /* BarButtonItem.swift */; };
|
D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D272F5F82473163100BD1A8F /* BarButtonItem.swift */; };
|
||||||
D274CA332236A78900B01B62 /* FooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* FooterView.swift */; };
|
D274CA332236A78900B01B62 /* FooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* FooterView.swift */; };
|
||||||
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; };
|
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; };
|
||||||
@ -494,6 +495,7 @@
|
|||||||
D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */; };
|
D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */; };
|
||||||
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B93236214AD00A9AEDC /* NavigationController.swift */; };
|
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B93236214AD00A9AEDC /* NavigationController.swift */; };
|
||||||
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */; };
|
D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */; };
|
||||||
|
D2B9D0E4265EEE9D0084735C /* MoleculeListProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */; };
|
||||||
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
||||||
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C521A823EDE79E00CA2634 /* ViewController.swift */; };
|
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C521A823EDE79E00CA2634 /* ViewController.swift */; };
|
||||||
@ -511,6 +513,7 @@
|
|||||||
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
|
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */; };
|
||||||
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; };
|
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */; };
|
||||||
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */; };
|
D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */; };
|
||||||
|
D2E0FFF826AF68530085D696 /* UITableViewRowAnimation+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */; };
|
||||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
||||||
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; };
|
D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */; };
|
||||||
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; };
|
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */; };
|
||||||
@ -951,6 +954,7 @@
|
|||||||
D264FAAB2441009400D98315 /* RadioBoxCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxCollectionViewCell.swift; sourceTree = "<group>"; };
|
D264FAAB2441009400D98315 /* RadioBoxCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioBoxCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; };
|
D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = "<group>"; };
|
D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = "<group>"; };
|
||||||
|
D270E5662642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddRemoveMoleculeBehavior.swift; sourceTree = "<group>"; };
|
||||||
D272F5F82473163100BD1A8F /* BarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonItem.swift; sourceTree = "<group>"; };
|
D272F5F82473163100BD1A8F /* BarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonItem.swift; sourceTree = "<group>"; };
|
||||||
D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; };
|
D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; };
|
||||||
D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = "<group>"; };
|
D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = "<group>"; };
|
||||||
@ -1061,6 +1065,7 @@
|
|||||||
D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIObject.swift; sourceTree = "<group>"; };
|
D2B18B912361E65A00A9AEDC /* CoreUIObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreUIObject.swift; sourceTree = "<group>"; };
|
||||||
D2B18B93236214AD00A9AEDC /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
|
D2B18B93236214AD00A9AEDC /* NavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
|
||||||
D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBody.swift; sourceTree = "<group>"; };
|
D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBody.swift; sourceTree = "<group>"; };
|
||||||
|
D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListProtocol.swift; sourceTree = "<group>"; };
|
||||||
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; };
|
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; };
|
||||||
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
|
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
|
||||||
D2C521A823EDE79E00CA2634 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
D2C521A823EDE79E00CA2634 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||||
@ -1078,6 +1083,7 @@
|
|||||||
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
|
D2D6CD4122E78FAB00D701B8 /* ThreeLayerTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTemplate.swift; sourceTree = "<group>"; };
|
||||||
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = "<group>"; };
|
D2D90B41240463E100DD6EC9 /* MoleculeHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeHeaderModel.swift; sourceTree = "<group>"; };
|
||||||
D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainerProtocol.swift; sourceTree = "<group>"; };
|
D2D90B432404789000DD6EC9 /* MoleculeContainerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeContainerProtocol.swift; sourceTree = "<group>"; };
|
||||||
|
D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewRowAnimation+Extension.swift"; sourceTree = "<group>"; };
|
||||||
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
||||||
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = "<group>"; };
|
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = "<group>"; };
|
||||||
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = "<group>"; };
|
D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = "<group>"; };
|
||||||
@ -1317,6 +1323,7 @@
|
|||||||
0A1C30972620F61A00B47F3B /* Protocols */,
|
0A1C30972620F61A00B47F3B /* Protocols */,
|
||||||
27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */,
|
27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */,
|
||||||
D23A900826125FFB007E14CE /* GetContactBehavior.swift */,
|
D23A900826125FFB007E14CE /* GetContactBehavior.swift */,
|
||||||
|
D270E5662642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift */,
|
||||||
);
|
);
|
||||||
path = Behaviors;
|
path = Behaviors;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1481,6 +1488,7 @@
|
|||||||
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
|
0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */,
|
||||||
D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */,
|
D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */,
|
||||||
D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */,
|
D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */,
|
||||||
|
D2E0FFF726AF68530085D696 /* UITableViewRowAnimation+Extension.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2323,6 +2331,7 @@
|
|||||||
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */,
|
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */,
|
||||||
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
|
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
|
||||||
D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */,
|
D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */,
|
||||||
|
D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */,
|
||||||
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
||||||
);
|
);
|
||||||
path = Protocols;
|
path = Protocols;
|
||||||
@ -2932,9 +2941,11 @@
|
|||||||
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
|
AA85236C244435A20059CC1E /* RadioSwatchCollectionViewCell.swift in Sources */,
|
||||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */,
|
||||||
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */,
|
||||||
|
D270E5672642F77300CDBED2 /* AddRemoveMoleculeBehavior.swift in Sources */,
|
||||||
BB2BF0EC2452A9D5001D0FC2 /* ListDeviceComplexButtonSmallModel.swift in Sources */,
|
BB2BF0EC2452A9D5001D0FC2 /* ListDeviceComplexButtonSmallModel.swift in Sources */,
|
||||||
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */,
|
943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */,
|
||||||
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
|
011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */,
|
||||||
|
D2E0FFF826AF68530085D696 /* UITableViewRowAnimation+Extension.swift in Sources */,
|
||||||
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */,
|
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */,
|
||||||
AA07EA912510A442009A2AE3 /* StarModel.swift in Sources */,
|
AA07EA912510A442009A2AE3 /* StarModel.swift in Sources */,
|
||||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||||
@ -2991,6 +3002,7 @@
|
|||||||
BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */,
|
BB6C6AC924225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShortModel.swift in Sources */,
|
||||||
C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */,
|
C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */,
|
||||||
D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */,
|
D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */,
|
||||||
|
D2B9D0E4265EEE9D0084735C /* MoleculeListProtocol.swift in Sources */,
|
||||||
D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */,
|
D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */,
|
||||||
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */,
|
||||||
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */,
|
||||||
|
|||||||
@ -23,7 +23,7 @@ open class BaseItemPickerEntryField: BaseDropdownEntryField, UIPickerViewDelegat
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
/// Closure passed here will run as picker changes items.
|
/// Closure passed here will run as picker changes items.
|
||||||
public var observeDropdownChange: ((String, String) -> ())?
|
public var observeDropdownChange: ((String?, String) -> ())?
|
||||||
|
|
||||||
/// Closure passed here will run upon dismissing the selection picker.
|
/// Closure passed here will run upon dismissing the selection picker.
|
||||||
public var observeDropdownSelection: ((String) -> ())?
|
public var observeDropdownSelection: ((String) -> ())?
|
||||||
|
|||||||
@ -56,9 +56,9 @@ open class ItemDropdownEntryField: BaseItemPickerEntryField {
|
|||||||
|
|
||||||
if setInitialValueInTextField {
|
if setInitialValueInTextField {
|
||||||
let pickerIndex = pickerView.selectedRow(inComponent: 0)
|
let pickerIndex = pickerView.selectedRow(inComponent: 0)
|
||||||
observeDropdownChange?(text ?? "", pickerData[pickerIndex])
|
|
||||||
text = pickerData[pickerIndex]
|
|
||||||
itemDropdownEntryFieldModel?.selectedIndex = pickerIndex
|
itemDropdownEntryFieldModel?.selectedIndex = pickerIndex
|
||||||
|
observeDropdownChange?(text, pickerData[pickerIndex])
|
||||||
|
text = pickerData[pickerIndex]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +108,8 @@ open class ItemDropdownEntryField: BaseItemPickerEntryField {
|
|||||||
@objc public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
|
@objc public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
|
||||||
guard !pickerData.isEmpty else { return }
|
guard !pickerData.isEmpty else { return }
|
||||||
|
|
||||||
observeDropdownChange?(text ?? "", pickerData[row])
|
|
||||||
text = pickerData[row]
|
|
||||||
itemDropdownEntryFieldModel?.selectedIndex = row
|
itemDropdownEntryFieldModel?.selectedIndex = row
|
||||||
|
observeDropdownChange?(text, pickerData[row])
|
||||||
|
text = pickerData[row]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ open class MultiItemDropdownEntryField: BaseItemPickerEntryField {
|
|||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
// Update observing function and update text UI.
|
// Update observing function and update text UI.
|
||||||
observeDropdownChange?(text ?? "", rowText)
|
observeDropdownChange?(text, rowText)
|
||||||
text = rowText
|
text = rowText
|
||||||
|
|
||||||
// Set row index value of selected component.
|
// Set row index value of selected component.
|
||||||
@ -135,7 +135,7 @@ open class MultiItemDropdownEntryField: BaseItemPickerEntryField {
|
|||||||
|
|
||||||
guard pickerHasComponent(component) else { return }
|
guard pickerHasComponent(component) else { return }
|
||||||
|
|
||||||
let oldText = text ?? ""
|
let oldText = text
|
||||||
dropdownModel?.selectedIndexes[component] = row
|
dropdownModel?.selectedIndexes[component] = row
|
||||||
let newText = dropdownModel?.selectedRowText
|
let newText = dropdownModel?.selectedRowText
|
||||||
observeDropdownChange?(oldText, newText ?? "")
|
observeDropdownChange?(oldText, newText ?? "")
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// UITableViewRowAnimation+Extension.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 7/26/21.
|
||||||
|
// Copyright © 2021 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
extension UITableView.RowAnimation: Codable {}
|
||||||
@ -17,7 +17,10 @@ class AccordionListItemModel: MoleculeListItemModel {
|
|||||||
|
|
||||||
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]
|
public var molecules: [ListItemModelProtocol & MoleculeModelProtocol]
|
||||||
public var hideLineWhenExpanded: Bool = false
|
public var hideLineWhenExpanded: Bool = false
|
||||||
|
public var selected: Bool = false
|
||||||
|
|
||||||
|
private var added: Bool = false
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -27,6 +30,7 @@ class AccordionListItemModel: MoleculeListItemModel {
|
|||||||
case molecules
|
case molecules
|
||||||
case molecule
|
case molecule
|
||||||
case hideLineWhenExpanded
|
case hideLineWhenExpanded
|
||||||
|
case selected
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -45,6 +49,7 @@ class AccordionListItemModel: MoleculeListItemModel {
|
|||||||
required public init(from decoder: Decoder) throws {
|
required public init(from decoder: Decoder) throws {
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
molecules = try typeContainer.decodeModels(codingKey: .molecules)
|
molecules = try typeContainer.decodeModels(codingKey: .molecules)
|
||||||
|
selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) ?? false
|
||||||
if let hideLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideLineWhenExpanded) {
|
if let hideLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideLineWhenExpanded) {
|
||||||
hideLineWhenExpanded = hideLine
|
hideLineWhenExpanded = hideLine
|
||||||
}
|
}
|
||||||
@ -56,6 +61,29 @@ class AccordionListItemModel: MoleculeListItemModel {
|
|||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encodeModels(molecules, forKey: .molecules)
|
try container.encodeModels(molecules, forKey: .molecules)
|
||||||
|
try container.encode(selected, forKey: .selected)
|
||||||
try container.encodeIfPresent(hideLineWhenExpanded, forKey: .hideLineWhenExpanded)
|
try container.encodeIfPresent(hideLineWhenExpanded, forKey: .hideLineWhenExpanded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension AccordionListItemModel: PageBehaviorProtocolRequirer {
|
||||||
|
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||||
|
return [AddRemoveMoleculesBehaviorModel()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AccordionListItemModel: AddMolecules {
|
||||||
|
public func moleculesToAdd() -> AddMolecules.AddParameters? {
|
||||||
|
guard !added, selected else { return nil }
|
||||||
|
added = true
|
||||||
|
return (molecules, .below)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension AccordionListItemModel: RemoveMolecules {
|
||||||
|
public func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||||
|
guard added else { return nil }
|
||||||
|
added = false
|
||||||
|
return molecules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -43,17 +43,27 @@
|
|||||||
accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal)
|
accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal)
|
||||||
|
|
||||||
guard let model = accordionListItemModel else { return }
|
guard let model = accordionListItemModel else { return }
|
||||||
|
model.selected = accordionButton.isSelected
|
||||||
|
|
||||||
if accordionButton.isSelected {
|
if accordionButton.isSelected {
|
||||||
if let indexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) {
|
MVMCoreActionHandler.shared()?.asyncHandleAction(with: AddMoleculesActionModel(.automatic), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||||
delegateObject?.moleculeDelegate?.addMolecules(model.molecules, indexPath: indexPath, animation: .automatic)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
delegateObject?.moleculeDelegate?.removeMolecules(model.molecules, animation: .automatic)
|
MVMCoreActionHandler.shared()?.asyncHandleAction(with: RemoveMoleculesActionModel(.automatic), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) {
|
if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) {
|
||||||
bottomSeparatorView?.isHidden = accordionButton.isSelected
|
bottomSeparatorView?.isHidden = accordionButton.isSelected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
guard let model = model as? AccordionListItemModel else { return }
|
||||||
|
accordionButton.isSelected = model.selected
|
||||||
|
accordionButton.setTitle(accordionButton.isSelected ? "-" : "+", for: .normal)
|
||||||
|
|
||||||
|
if (accordionListItemModel?.hideLineWhenExpanded ?? false) && (self.bottomSeparatorView?.shouldBeVisible() ?? false) {
|
||||||
|
bottomSeparatorView?.isHidden = accordionButton.isSelected
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import UIKit
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
let dropDown = ItemDropdownEntryField()
|
let dropDown = ItemDropdownEntryField()
|
||||||
var delegateObject: MVMCoreUIDelegateObject?
|
var delegateObject: MVMCoreUIDelegateObject?
|
||||||
var previousIndex = NSNotFound
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Lifecycle
|
// MARK: - Lifecycle
|
||||||
@ -28,18 +27,15 @@ import UIKit
|
|||||||
|
|
||||||
guard newValue != oldValue,
|
guard newValue != oldValue,
|
||||||
let self = self,
|
let self = self,
|
||||||
let index = self.dropDown.pickerData.firstIndex(of: newValue),
|
|
||||||
let model = self.listItemModel as? DropDownListItemModel
|
let model = self.listItemModel as? DropDownListItemModel
|
||||||
else { return }
|
else { return }
|
||||||
|
MVMCoreDispatchUtility.performBlock(inBackground: {
|
||||||
if self.previousIndex != NSNotFound {
|
if let oldValue = oldValue,
|
||||||
self.delegateObject?.moleculeDelegate?.removeMolecules(model.molecules[self.previousIndex], animation: .fade)
|
oldValue.count > 0 {
|
||||||
}
|
MVMCoreActionHandler.shared()?.syncHandleAction(with: RemoveMoleculesActionModel(.fade), additionalData: [KeySourceModel: model], delegateObject: self.delegateObject)
|
||||||
|
}
|
||||||
if let indexPath = self.delegateObject?.moleculeDelegate?.getIndexPath(for: model) {
|
MVMCoreActionHandler.shared()?.syncHandleAction(with: AddMoleculesActionModel(.fade), additionalData: [KeySourceModel: model], delegateObject: self.delegateObject)
|
||||||
self.delegateObject?.moleculeDelegate?.addMolecules(model.molecules[index], indexPath: indexPath, animation: .fade)
|
})
|
||||||
}
|
|
||||||
self.previousIndex = index
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,8 @@ import Foundation
|
|||||||
public static var identifier: String = "dropDownListItem"
|
public static var identifier: String = "dropDownListItem"
|
||||||
public var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
|
public var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
|
||||||
public var dropDown: ItemDropdownEntryFieldModel
|
public var dropDown: ItemDropdownEntryFieldModel
|
||||||
|
private var addedMolecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Methods
|
// MARK: - Methods
|
||||||
@ -81,3 +83,27 @@ import Foundation
|
|||||||
try container.encode(dropDown, forKey: .dropDown)
|
try container.encode(dropDown, forKey: .dropDown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension DropDownListItemModel: PageBehaviorProtocolRequirer {
|
||||||
|
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||||
|
return [AddRemoveMoleculesBehaviorModel()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DropDownListItemModel: AddMolecules {
|
||||||
|
public func moleculesToAdd() -> AddMolecules.AddParameters? {
|
||||||
|
guard addedMolecules == nil,
|
||||||
|
let index = dropDown.selectedIndex else { return nil }
|
||||||
|
let addedMolecules = molecules[index]
|
||||||
|
self.addedMolecules = addedMolecules
|
||||||
|
return (addedMolecules, .below)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DropDownListItemModel: RemoveMolecules {
|
||||||
|
public func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||||
|
guard let addedMolecules = addedMolecules else { return nil }
|
||||||
|
self.addedMolecules = nil
|
||||||
|
return addedMolecules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -17,7 +17,8 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
|
|||||||
public static var identifier: String = "tabsListItem"
|
public static var identifier: String = "tabsListItem"
|
||||||
var tabs: TabsModel
|
var tabs: TabsModel
|
||||||
var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
|
var molecules: [[ListItemModelProtocol & MoleculeModelProtocol]]
|
||||||
|
private var addedMolecules: [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -70,3 +71,26 @@ public class TabsListItemModel: ListItemModel, MoleculeModelProtocol {
|
|||||||
try container.encodeModels2D(molecules, forKey: .molecules)
|
try container.encodeModels2D(molecules, forKey: .molecules)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension TabsListItemModel: PageBehaviorProtocolRequirer {
|
||||||
|
public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] {
|
||||||
|
return [AddRemoveMoleculesBehaviorModel()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TabsListItemModel: AddMolecules {
|
||||||
|
public func moleculesToAdd() -> AddMolecules.AddParameters? {
|
||||||
|
guard addedMolecules == nil else { return nil }
|
||||||
|
let addedMolecules = molecules[tabs.selectedIndex]
|
||||||
|
self.addedMolecules = addedMolecules
|
||||||
|
return (addedMolecules, .below)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TabsListItemModel: RemoveMolecules {
|
||||||
|
public func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||||
|
guard let addedMolecules = addedMolecules else { return nil }
|
||||||
|
self.addedMolecules = nil
|
||||||
|
return addedMolecules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -52,11 +52,12 @@ import UIKit
|
|||||||
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 46 }
|
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 46 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Move to AddRemoveMoleculeBehaviorModel
|
||||||
extension TabsTableViewCell: TabsDelegate {
|
extension TabsTableViewCell: TabsDelegate {
|
||||||
public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
|
public func shouldSelectItem(_ indexPath: IndexPath, tabs: Tabs) -> Bool {
|
||||||
|
guard indexPath.row != tabs.selectedIndex else { return false }
|
||||||
if let model = tabsListItemModel {
|
if let model = tabsListItemModel {
|
||||||
let molecules = model.molecules[tabs.selectedIndex]
|
MVMCoreActionHandler.shared()?.asyncHandleAction(with: RemoveMoleculesActionModel(indexPath.row < tabs.selectedIndex ? .right : .left), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||||
delegateObject?.moleculeDelegate?.removeMolecules(molecules, animation: indexPath.row < tabs.selectedIndex ? .right : .left)
|
|
||||||
}
|
}
|
||||||
previousTabIndex = tabs.selectedIndex
|
previousTabIndex = tabs.selectedIndex
|
||||||
return true
|
return true
|
||||||
@ -64,12 +65,9 @@ extension TabsTableViewCell: TabsDelegate {
|
|||||||
|
|
||||||
public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) {
|
public func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) {
|
||||||
let index = indexPath.row
|
let index = indexPath.row
|
||||||
if let model = tabsListItemModel,
|
guard let model = tabsListItemModel,
|
||||||
index < model.molecules.count,
|
index < model.molecules.count else { return }
|
||||||
let cellIndexPath = delegateObject?.moleculeDelegate?.getIndexPath(for: model) {
|
MVMCoreActionHandler.shared()?.asyncHandleAction(with: AddMoleculesActionModel(index < previousTabIndex ? .left : .right), additionalData: [KeySourceModel: model], delegateObject: delegateObject)
|
||||||
let molecules = model.molecules[index]
|
|
||||||
delegateObject?.moleculeDelegate?.addMolecules(molecules, indexPath: cellIndexPath, animation: index < previousTabIndex ? .left : .right)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,22 +18,9 @@ public protocol MoleculeDelegateProtocol: AnyObject {
|
|||||||
|
|
||||||
/// Notifies the delegate that the molecule layout update. Should be called when the layout may change due to an async method. Mainly used for list or collections.
|
/// Notifies the delegate that the molecule layout update. Should be called when the layout may change due to an async method. Mainly used for list or collections.
|
||||||
func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) //optional
|
func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) //optional
|
||||||
|
|
||||||
/// Asks the delegate to add or remove molecules. Mainly used for list or collections.
|
|
||||||
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 {
|
extension MoleculeDelegateProtocol {
|
||||||
|
|
||||||
public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
|
public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
|
||||||
|
|
||||||
public func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { nil }
|
|
||||||
|
|
||||||
public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) { }
|
|
||||||
|
|
||||||
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { }
|
|
||||||
}
|
}
|
||||||
|
|||||||
39
MVMCoreUI/Atomic/Protocols/MoleculeListProtocol.swift
Normal file
39
MVMCoreUI/Atomic/Protocols/MoleculeListProtocol.swift
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// MoleculeListProtocol.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 5/26/21.
|
||||||
|
// Copyright © 2021 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
public protocol MoleculeListProtocol {
|
||||||
|
|
||||||
|
/// Asks the delegate for the index of molecule.
|
||||||
|
func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath?
|
||||||
|
|
||||||
|
/// Asks the delegate to add molecules.
|
||||||
|
func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation?)
|
||||||
|
|
||||||
|
/// Asks the delegate to remove molecules.
|
||||||
|
func removeMolecules(at indexPaths: [IndexPath], animation: UITableView.RowAnimation?)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MoleculeListProtocol {
|
||||||
|
/// Convenience function that removes the passed molecule
|
||||||
|
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation?) {
|
||||||
|
var indexPaths: [IndexPath] = []
|
||||||
|
for molecule in molecules {
|
||||||
|
guard let indexPath = getIndexPath(for: molecule) else { continue }
|
||||||
|
indexPaths.append(indexPath)
|
||||||
|
}
|
||||||
|
if indexPaths.count > 0 {
|
||||||
|
removeMolecules(at: indexPaths, animation: animation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension MVMCoreUIDelegateObject {
|
||||||
|
weak var moleculeListDelegate: (MoleculeListProtocol & NSObjectProtocol)? {
|
||||||
|
return (moleculeDelegate as? MoleculeListProtocol & NSObjectProtocol)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -183,43 +183,14 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
|
open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
|
||||||
guard let tableView = tableView else { return }
|
guard let tableView = tableView else { return }
|
||||||
if let indexPath = tableView.indexPathForRow(at: molecule.center), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
|
|
||||||
|
let point = molecule.convert(molecule.bounds.origin, to: tableView)
|
||||||
|
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
|
||||||
performTableViewUpdates()
|
performTableViewUpdates()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
|
||||||
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
|
||||||
//TODO: check for molecule protocol eqaulity
|
|
||||||
let json = moleculeInfo.molecule.toJSON()
|
|
||||||
return json == molecule.toJSON()
|
|
||||||
}) else { return nil }
|
|
||||||
|
|
||||||
return IndexPath(row: index, section: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
var indexPaths: [IndexPath] = []
|
|
||||||
|
|
||||||
for molecule in molecules {
|
|
||||||
if let info = self.createMoleculeInfo(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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
guard indexPaths.count > 0 else { return }
|
|
||||||
self.tableView?.insertRows(at: indexPaths, with: animation)
|
|
||||||
self.updateViewConstraints()
|
|
||||||
self.view.layoutIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open func newData(for molecule: MoleculeModelProtocol) {
|
open func newData(for molecule: MoleculeModelProtocol) {
|
||||||
//TODO: expand for header, navigation, etc
|
//TODO: expand for header, navigation, etc
|
||||||
let json = molecule.toJSON()
|
let json = molecule.toJSON()
|
||||||
@ -252,24 +223,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
tableView.selectRow(at: selectedIndex, animated: false, scrollPosition: .none)
|
tableView.selectRow(at: selectedIndex, animated: false, scrollPosition: .none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {
|
|
||||||
var indexPaths: [IndexPath] = []
|
|
||||||
//TODO: check for molecule protocol equality
|
|
||||||
|
|
||||||
for molecule in molecules {
|
|
||||||
if let removeIndex = moleculesInfo?.firstIndex(where: { molecule.toJSON() == $0.molecule.toJSON() }) {
|
|
||||||
moleculesInfo?.remove(at: removeIndex)
|
|
||||||
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
guard indexPaths.count > 0 else { return }
|
|
||||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
|
||||||
updateViewConstraints()
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Convenience
|
// MARK: - Convenience
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -335,3 +289,50 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
|||||||
return modules
|
return modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension MoleculeListTemplate: MoleculeListProtocol {
|
||||||
|
open func removeMolecules(at indexPaths: [IndexPath], animation: UITableView.RowAnimation?) {
|
||||||
|
for (index, indexPath) in indexPaths.sorted().enumerated() {
|
||||||
|
let removeIndex = indexPath.row - index
|
||||||
|
moleculesInfo?.remove(at: removeIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let animation = animation,
|
||||||
|
indexPaths.count > 0 else { return }
|
||||||
|
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||||
|
updateViewConstraints()
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
open 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 {
|
||||||
|
var indexPaths: [IndexPath] = []
|
||||||
|
|
||||||
|
for molecule in molecules {
|
||||||
|
if let info = self.createMoleculeInfo(with: molecule) {
|
||||||
|
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
|
||||||
|
let index = indexPath.row + indexPaths.count
|
||||||
|
self.moleculesInfo?.insert(info, at: index)
|
||||||
|
indexPaths.append(IndexPath(row: index, section: 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let animation = animation,
|
||||||
|
indexPaths.count > 0 else { return }
|
||||||
|
self.tableView?.insertRows(at: indexPaths, with: animation)
|
||||||
|
self.updateViewConstraints()
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? {
|
||||||
|
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
|
||||||
|
//TODO: check for molecule protocol eqaulity
|
||||||
|
let json = moleculeInfo.molecule.toJSON()
|
||||||
|
return json == molecule.toJSON()
|
||||||
|
}) else { return nil }
|
||||||
|
|
||||||
|
return IndexPath(row: index, section: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -507,9 +507,6 @@ import UIKit
|
|||||||
|
|
||||||
// Needed otherwise when subclassed, the extension gets called.
|
// Needed otherwise when subclassed, the extension gets called.
|
||||||
open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
|
open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
|
||||||
open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { nil }
|
|
||||||
open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) { }
|
|
||||||
open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { }
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - MVMCoreUIDetailViewProtocol
|
// MARK: - MVMCoreUIDetailViewProtocol
|
||||||
|
|||||||
176
MVMCoreUI/Behaviors/AddRemoveMoleculeBehavior.swift
Normal file
176
MVMCoreUI/Behaviors/AddRemoveMoleculeBehavior.swift
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
//
|
||||||
|
// AddRemoveMoleculeBehavior.swift
|
||||||
|
// MVMCoreUI
|
||||||
|
//
|
||||||
|
// Created by Scott Pfeil on 5/5/21.
|
||||||
|
// Copyright © 2021 Verizon Wireless. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum AddMoleculesPosition {
|
||||||
|
case above
|
||||||
|
case below
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Protocol for adding items to a list
|
||||||
|
public protocol AddMolecules {
|
||||||
|
typealias AddParameters = ([ListItemModelProtocol & MoleculeModelProtocol], AddMoleculesPosition)
|
||||||
|
|
||||||
|
/// Get the molecules that need to be added, the position to add them to, and the animation to use
|
||||||
|
func moleculesToAdd() -> AddParameters?
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Protocol for removing items to a list
|
||||||
|
public protocol RemoveMolecules {
|
||||||
|
/// Get the molecules that need to be removed, and the animation to use
|
||||||
|
func moleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]?
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension AddMolecules {
|
||||||
|
/// Convenience function that gets the molecules that need to be added, recursively checking for additional molecules to add.
|
||||||
|
func getRecursiveMoleculesToAdd() -> AddMolecules.AddParameters? {
|
||||||
|
guard let moleculesToAdd = moleculesToAdd() else { return nil }
|
||||||
|
var newMolecules: [ListItemModelProtocol & MoleculeModelProtocol] = []
|
||||||
|
for molecule in moleculesToAdd.0 {
|
||||||
|
if let anotherAddMolecule = molecule as? AddMolecules,
|
||||||
|
let moreMolecules = anotherAddMolecule.getRecursiveMoleculesToAdd() {
|
||||||
|
guard moreMolecules.1 == .above else {
|
||||||
|
newMolecules.append(molecule)
|
||||||
|
newMolecules.append(contentsOf: moreMolecules.0)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newMolecules.append(contentsOf: moreMolecules.0)
|
||||||
|
}
|
||||||
|
newMolecules.append(molecule)
|
||||||
|
}
|
||||||
|
return (newMolecules, moleculesToAdd.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension RemoveMolecules {
|
||||||
|
/// Convenience function that gets the molecules that need to be removed, recursively checking for additional molecules to remove.
|
||||||
|
func getRecursiveMoleculesToRemove() -> [ListItemModelProtocol & MoleculeModelProtocol]? {
|
||||||
|
guard let moleculesToRemove = moleculesToRemove() else { return nil }
|
||||||
|
var newMolecules: [ListItemModelProtocol & MoleculeModelProtocol] = moleculesToRemove
|
||||||
|
for case let molecule as (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules) in moleculesToRemove {
|
||||||
|
guard let moreMolecules = molecule.getRecursiveMoleculesToRemove() else { continue }
|
||||||
|
newMolecules.append(contentsOf: moreMolecules)
|
||||||
|
}
|
||||||
|
return newMolecules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddRemoveMoleculesBehaviorModel: PageBehaviorModelProtocol {
|
||||||
|
public class var identifier: String { "addRemoveListItemBehavior" }
|
||||||
|
public var shouldAllowMultipleInstances: Bool { false }
|
||||||
|
public init() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddRemoveMoleculesBehavior: PageCustomActionHandlerBehavior, PageMoleculeTransformationBehavior {
|
||||||
|
|
||||||
|
var delegate: MVMCoreUIDelegateObject?
|
||||||
|
|
||||||
|
public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) {
|
||||||
|
self.delegate = delegateObject
|
||||||
|
}
|
||||||
|
|
||||||
|
public func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject) {
|
||||||
|
guard let list = delegate?.moleculeListDelegate else { return }
|
||||||
|
for case let model as (MoleculeModelProtocol & ListItemModelProtocol & AddMolecules) in rootMolecules {
|
||||||
|
if let moleculesToAdd = model.getRecursiveMoleculesToAdd(),
|
||||||
|
let indexPath = list.getAdjustedIndexPath(for: model, position: moleculesToAdd.1) {
|
||||||
|
list.addMolecules(moleculesToAdd.0, indexPath: indexPath, animation: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func handleAction(type actionType: String?, information: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) -> Bool {
|
||||||
|
if actionType == AddMoleculesActionModel.identifier {
|
||||||
|
guard let list = delegate?.moleculeListDelegate,
|
||||||
|
let model = additionalData?[KeySourceModel] as? (ListItemModelProtocol & MoleculeModelProtocol & AddMolecules),
|
||||||
|
let moleculesToAdd = model.getRecursiveMoleculesToAdd(),
|
||||||
|
let indexPath = list.getAdjustedIndexPath(for: model, position: moleculesToAdd.1),
|
||||||
|
let animation = information?["animation"] as? Int else { return true }
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
list.addMolecules(moleculesToAdd.0, indexPath: indexPath, animation: UITableView.RowAnimation(rawValue: animation))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else if actionType == RemoveMoleculesActionModel.identifier {
|
||||||
|
guard let list = delegate?.moleculeListDelegate,
|
||||||
|
let model = additionalData?[KeySourceModel] as? (ListItemModelProtocol & MoleculeModelProtocol & RemoveMolecules),
|
||||||
|
let moleculesToRemove = model.getRecursiveMoleculesToRemove(),
|
||||||
|
let animation = information?["animation"] as? Int else { return true }
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
list.removeMolecules(moleculesToRemove, animation: UITableView.RowAnimation(rawValue: animation))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension MoleculeListProtocol {
|
||||||
|
/// Convenience function to get the index path adjusted for position.
|
||||||
|
func getAdjustedIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol, position: AddMoleculesPosition) -> IndexPath? {
|
||||||
|
guard let indexPath = getIndexPath(for: molecule) else { return nil }
|
||||||
|
if position == .below {
|
||||||
|
return IndexPath(row: indexPath.row + 1, section: indexPath.section)
|
||||||
|
}
|
||||||
|
return indexPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddMoleculesActionModel: ActionModelProtocol {
|
||||||
|
public static var identifier: String = "addMoleculesAction"
|
||||||
|
public var actionType: String = AddMoleculesActionModel.identifier
|
||||||
|
public var animation: UITableView.RowAnimation = .automatic
|
||||||
|
public var extraParameters: JSONValueDictionary?
|
||||||
|
public var analyticsData: JSONValueDictionary?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializer
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public init(_ animation: UITableView.RowAnimation, extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||||
|
self.animation = animation
|
||||||
|
self.extraParameters = extraParameters
|
||||||
|
self.analyticsData = analyticsData
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
if let animation = try typeContainer.decodeIfPresent(UITableView.RowAnimation.self, forKey: .animation) {
|
||||||
|
self.animation = animation
|
||||||
|
}
|
||||||
|
extraParameters = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .extraParameters)
|
||||||
|
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RemoveMoleculesActionModel: ActionModelProtocol {
|
||||||
|
public static var identifier: String = "removeMoleculesAction"
|
||||||
|
public var actionType: String = RemoveMoleculesActionModel.identifier
|
||||||
|
public var animation: UITableView.RowAnimation = .automatic
|
||||||
|
public var extraParameters: JSONValueDictionary?
|
||||||
|
public var analyticsData: JSONValueDictionary?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Initializer
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public init(_ animation: UITableView.RowAnimation, extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) {
|
||||||
|
self.animation = animation
|
||||||
|
self.extraParameters = extraParameters
|
||||||
|
self.analyticsData = analyticsData
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init(from decoder: Decoder) throws {
|
||||||
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
if let animation = try typeContainer.decodeIfPresent(UITableView.RowAnimation.self, forKey: .animation) {
|
||||||
|
self.animation = animation
|
||||||
|
}
|
||||||
|
extraParameters = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .extraParameters)
|
||||||
|
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -222,8 +222,9 @@ open class CoreUIModelMapping: ModelMapping {
|
|||||||
open class func registerBehaviors() {
|
open class func registerBehaviors() {
|
||||||
ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self)
|
ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self)
|
||||||
ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self)
|
ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self)
|
||||||
|
ModelRegistry.register(handler: AddRemoveMoleculesBehavior.self, for: AddRemoveMoleculesBehaviorModel.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
open override class func registerActions() {
|
open override class func registerActions() {
|
||||||
super.registerActions()
|
super.registerActions()
|
||||||
ModelRegistry.register(ActionPopupModel.self)
|
ModelRegistry.register(ActionPopupModel.self)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user