diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 664974b2..d16065f6 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -125,7 +125,7 @@ 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; }; 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */; }; 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */; }; - 27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehavior.swift */; }; + 27F973532466074500CAB5C5 /* PageBehaviorProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F973522466074500CAB5C5 /* PageBehaviorProtocol.swift */; }; 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */; }; 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */; }; 31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31BE15CA23D8924C00452370 /* CheckboxModel.swift */; }; @@ -348,13 +348,18 @@ 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 */; }; + D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */; }; + D23A8FEE26122F7D007E14CE /* VisibleBehaviorForVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */; }; + D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */; }; + D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */; }; + D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */; }; + D23A9004261234CE007E14CE /* PageBehaviorHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */; }; + D23A900926125FFB007E14CE /* GetContactBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23A900826125FFB007E14CE /* GetContactBehavior.swift */; }; D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */; }; D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */; }; D23EA800247EBD6C00D60C34 /* LabelBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */; }; D23EA802247EBED400D60C34 /* ImageBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23EA801247EBED400D60C34 /* ImageBarButtonItem.swift */; }; D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; }; - D24918F625D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24918F525D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift */; }; - D24918FA25D5ADBB00CAB4B1 /* PageScrolledClosureBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24918F925D5ADBA00CAB4B1 /* PageScrolledClosureBehavior.swift */; }; D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */; }; D2509ED62472EE2F001BFB9D /* NavigationImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2509ED52472EE2F001BFB9D /* NavigationImageButtonModel.swift */; }; D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260106423D0CEA700764D80 /* StackModel.swift */; }; @@ -683,7 +688,7 @@ 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = ""; }; 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTreeTraversalProtocol.swift; sourceTree = ""; }; 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentMoleculeModelProtocol.swift; sourceTree = ""; }; - 27F973522466074500CAB5C5 /* PageBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehavior.swift; sourceTree = ""; }; + 27F973522466074500CAB5C5 /* PageBehaviorProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorProtocol.swift; sourceTree = ""; }; 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenBrightnessModifierBehavior.swift; sourceTree = ""; }; 31BE15C923D8924C00452370 /* CheckboxLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxLabelModel.swift; sourceTree = ""; }; 31BE15CA23D8924C00452370 /* CheckboxModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckboxModel.swift; sourceTree = ""; }; @@ -906,13 +911,18 @@ D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = ""; }; D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = ""; }; D236E5B6242007C500C38625 /* MVMControllerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMControllerModelProtocol.swift; sourceTree = ""; }; + D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibleBehaviorForVideoModel.swift; sourceTree = ""; }; + D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisibleBehaviorForVideo.swift; sourceTree = ""; }; + D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorProtocolRequirer.swift; sourceTree = ""; }; + D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorModelProtocol.swift; sourceTree = ""; }; + D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerModelProtocol.swift; sourceTree = ""; }; + D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageBehaviorHandlerProtocol.swift; sourceTree = ""; }; + D23A900826125FFB007E14CE /* GetContactBehavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetContactBehavior.swift; sourceTree = ""; }; D23EA7FA2475F09800D60C34 /* CarouselItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselItemProtocol.swift; sourceTree = ""; }; D23EA7FD247EBBB700D60C34 /* NavigationLabelButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationLabelButtonModel.swift; sourceTree = ""; }; D23EA7FF247EBD6C00D60C34 /* LabelBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelBarButtonItem.swift; sourceTree = ""; }; D23EA801247EBED400D60C34 /* ImageBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageBarButtonItem.swift; sourceTree = ""; }; D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; - D24918F525D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageVisibilityClosureBehavior.swift; sourceTree = ""; }; - D24918F925D5ADBA00CAB4B1 /* PageScrolledClosureBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageScrolledClosureBehavior.swift; sourceTree = ""; }; D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModelProtocol.swift; sourceTree = ""; }; D2509ED52472EE2F001BFB9D /* NavigationImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationImageButtonModel.swift; sourceTree = ""; }; D253BB9B245874F8002DE544 /* BGImageMolecule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageMolecule.swift; sourceTree = ""; }; @@ -1286,10 +1296,13 @@ 27F973512466071600CAB5C5 /* Behaviors */ = { isa = PBXGroup; children = ( - 27F973522466074500CAB5C5 /* PageBehavior.swift */, + D23A8FF72612308D007E14CE /* PageBehaviorProtocolRequirer.swift */, + D23A8FFA26123189007E14CE /* PageBehaviorModelProtocol.swift */, + D23A8FFF2612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift */, + D23A9003261234CE007E14CE /* PageBehaviorHandlerProtocol.swift */, + 27F973522466074500CAB5C5 /* PageBehaviorProtocol.swift */, 27F97369246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift */, - D24918F525D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift */, - D24918F925D5ADBA00CAB4B1 /* PageScrolledClosureBehavior.swift */, + D23A900826125FFB007E14CE /* GetContactBehavior.swift */, ); path = Behaviors; sourceTree = ""; @@ -1708,6 +1721,18 @@ path = TwoColumn; sourceTree = ""; }; + D23A8FE926122F41007E14CE /* Video */ = { + isa = PBXGroup; + children = ( + D29C559525C099630082E7D6 /* VideoDataManager.swift */, + D29C559225C0992D0082E7D6 /* VideoModel.swift */, + D29C558F25C095210082E7D6 /* Video.swift */, + D23A8FEA26122F69007E14CE /* VisibleBehaviorForVideoModel.swift */, + D23A8FED26122F7D007E14CE /* VisibleBehaviorForVideo.swift */, + ); + path = Video; + sourceTree = ""; + }; D23EA7FC247EBB7500D60C34 /* Buttons */ = { isa = PBXGroup; children = ( @@ -2055,6 +2080,7 @@ D29DF17D21E69E26003B2FB9 /* Views */ = { isa = PBXGroup; children = ( + D23A8FE926122F41007E14CE /* Video */, 0A9D09162433796500D2E6C0 /* CarouselIndicator */, 9445890B2385BCE300DE9FD4 /* ProgressBarModel.swift */, 01509D922327ECFB00EF99AA /* ProgressBar.swift */, @@ -2087,9 +2113,6 @@ AA37CBD42519072F0027344C /* Stars.swift */, AA07EA902510A442009A2AE3 /* StarModel.swift */, AA07EA922510A451009A2AE3 /* Star.swift */, - D29C559525C099630082E7D6 /* VideoDataManager.swift */, - D29C559225C0992D0082E7D6 /* VideoModel.swift */, - D29C558F25C095210082E7D6 /* Video.swift */, ); path = Views; sourceTree = ""; @@ -2579,6 +2602,7 @@ AAB9C10A243496DD00151545 /* RadioSwatch.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, + D23A900926125FFB007E14CE /* GetContactBehavior.swift in Sources */, D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */, AA617AB22453012400910B8F /* ListDeviceComplexLinkSmallModel.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, @@ -2590,11 +2614,13 @@ D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, 01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */, D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */, + D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */, 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */, + D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */, BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */, D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */, AA07EA932510A451009A2AE3 /* Star.swift in Sources */, @@ -2612,6 +2638,7 @@ D2ED27EC254B0CE700A1C293 /* UIAlertControllerStyle+Extension.swift in Sources */, C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */, 014AA72D23C5059B006F3E93 /* StackPageTemplateModel.swift in Sources */, + D23A8FEE26122F7D007E14CE /* VisibleBehaviorForVideo.swift in Sources */, 0A9D091F2433796500D2E6C0 /* NumericIndicatorView.swift in Sources */, D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, @@ -2633,6 +2660,7 @@ AAC23FAF24D92A1E009208DF /* ListThreeColumnSpeedTest.swift in Sources */, 0A0FEC7425D42A5E00AF2548 /* BaseItemPickerEntryField.swift in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, + D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */, D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, D2ED27ED254B0CE700A1C293 /* ActionPopupModel.swift in Sources */, 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */, @@ -2755,7 +2783,6 @@ 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */, 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */, 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */, - D24918F625D5AD8E00CAB4B1 /* PageVisibilityClosureBehavior.swift in Sources */, D20492A624329CE200A5EED6 /* LoadImageView.swift in Sources */, 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */, D274CA332236A78900B01B62 /* FooterView.swift in Sources */, @@ -2842,7 +2869,6 @@ 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, 0AE14F64238315D2005417F8 /* TextField.swift in Sources */, - D24918FA25D5ADBB00CAB4B1 /* PageScrolledClosureBehavior.swift in Sources */, 0A51F3E22475CB73002E08B6 /* LoadingSpinnerModel.swift in Sources */, D2169303251E53D9002A6324 /* SectionListTemplateModel.swift in Sources */, 0AB764D124460F6300E7FE72 /* UIDatePicker+Extension.swift in Sources */, @@ -2908,7 +2934,7 @@ D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */, 0AB000BC24BF64A50090C5E7 /* ModalStackPageTemplateModel.swift in Sources */, - 27F973532466074500CAB5C5 /* PageBehavior.swift in Sources */, + 27F973532466074500CAB5C5 /* PageBehaviorProtocol.swift in Sources */, 94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */, D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */, D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, @@ -2917,6 +2943,7 @@ 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, + D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */, 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */, 0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */, @@ -2979,6 +3006,7 @@ 011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */, AA0A257A24766CA200862F64 /* ListLeftVariableIconWithRightCaretBodyText.swift in Sources */, 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */, + D23A9004261234CE007E14CE /* PageBehaviorHandlerProtocol.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */, 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift index 6b120d0c..fbbc9e03 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Label/LabelModel.swift @@ -7,12 +7,12 @@ // -@objcMembers public class LabelModel: MoleculeModelProtocol { +@objcMembers open class LabelModel: MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "label" + open class var identifier: String { "label" } public var backgroundColor: Color? public var text: String public var accessibilityText: String? diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Views/Video.swift rename to MVMCoreUI/Atomic/Atoms/Views/Video/Video.swift diff --git a/MVMCoreUI/Atomic/Atoms/Views/VideoDataManager.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoDataManager.swift similarity index 100% rename from MVMCoreUI/Atomic/Atoms/Views/VideoDataManager.swift rename to MVMCoreUI/Atomic/Atoms/Views/Video/VideoDataManager.swift diff --git a/MVMCoreUI/Atomic/Atoms/Views/VideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift similarity index 64% rename from MVMCoreUI/Atomic/Atoms/Views/VideoModel.swift rename to MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift index 1d079599..7c348760 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/VideoModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VideoModel.swift @@ -8,7 +8,7 @@ import Foundation -open class VideoModel: MoleculeModelProtocol { +open class VideoModel: MoleculeModelProtocol, PageBehaviorProtocolRequirer { public static var identifier = "video" public var backgroundColor: Color? public var video: String @@ -39,8 +39,6 @@ open class VideoModel: MoleculeModelProtocol { /// Keeps a reference to the video data. public var videoDataManager: VideoDataManager - private weak var visibleBehavior: PageVisibilityClosureBehavior? - private weak var scrollBehavior: PageScrolledClosureBehavior? private var activeListener: Any? private var resignActiveListener: Any? @@ -81,61 +79,16 @@ open class VideoModel: MoleculeModelProtocol { try container.encode(alwaysReset, forKey: .alwaysReset) } + public func getRequiredBehaviors() -> [PageBehaviorModelProtocol] { + return [VisibleBehaviorForVideoModel(with: self)] + } + open func addVisibilityHalting(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { self.view = view halted = false - addVisibleBehavior(for: view, delegateObject: delegateObject) - addScrollBehavior(for: view, delegateObject: delegateObject) addActiveListener(for: view, delegateObject: delegateObject) } - /// Adds a behavior to pause the video on page hidden behavior and unpause if necessary on page shown. - open func addVisibleBehavior(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { - - let onShow = { [weak self] in - guard let self = self, - let view = self.view, - view.isVisibleInDelegate() else { return } - self.halted = false - } - let onHide: () -> Void = { [weak self] in - self?.halted = true - } - - guard visibleBehavior == nil else { - visibleBehavior?.pageShownHandler = onShow - visibleBehavior?.pageHiddenHandler = onHide - return - } - - guard var delegate = delegateObject?.behaviorTemplateDelegate else { return } - let pauseBehavior = PageVisibilityClosureBehavior(with: onShow, onPageHiddenHandler: onHide) - delegate.add(behavior: pauseBehavior) - self.visibleBehavior = pauseBehavior - } - - /// Adds a behavior to pause the video if scrolled off of the page and unpause if necessary if scrolled on. - open func addScrollBehavior(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { - - let onScroll = { [weak self] (scrollView: UIScrollView) in - // If visible to not visible, pause video. - // If not visible to visible, unpause if needed, add visible behavior - guard let self = self, - let view = self.view else { return } - self.halted = !view.isVisible(in: scrollView) - } - - guard scrollBehavior == nil else { - scrollBehavior?.pageScrolledHandler = onScroll - return - } - - guard var delegate = delegateObject?.behaviorTemplateDelegate else { return } - let scrollBehavior = PageScrolledClosureBehavior(with: onScroll) - delegate.add(behavior: scrollBehavior) - self.scrollBehavior = scrollBehavior - } - open func addActiveListener(for view: Video, delegateObject: MVMCoreUIDelegateObject?) { removeActiveListener() diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift new file mode 100644 index 00000000..4f01e375 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideo.swift @@ -0,0 +1,36 @@ +// +// VisibleBehaviorForVideo.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class VisibleBehaviorForVideo: PageVisibilityBehavior, PageScrolledBehavior { + var model: PageBehaviorModelProtocol + + required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.model = model + } + + public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { + guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, + let view = model.view, + view.isVisibleInDelegate() else { return } + model.halted = false + } + + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) { + (model as? VisibleBehaviorForVideoModel)?.videoModel?.halted = true + } + + public func pageScrolled(scrollView: UIScrollView, _ delegateObject: MVMCoreUIDelegateObject?) { + // If visible to not visible, pause video. + // If not visible to visible, unpause if needed, add visible behavior + guard let model = (model as? VisibleBehaviorForVideoModel)?.videoModel, + let view = model.view else { return } + model.halted = !view.isVisible(in: scrollView) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift new file mode 100644 index 00000000..45734dac --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Video/VisibleBehaviorForVideoModel.swift @@ -0,0 +1,20 @@ +// +// VisibleBehaviorForVideoModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class VisibleBehaviorForVideoModel: PageBehaviorModelProtocol { + + public static var identifier: String = "visibleBehaviorForVideoModel" + public var shouldAllowMultipleInstances: Bool = true + public weak var videoModel: VideoModel? + + init(with videoModel: VideoModel) { + self.videoModel = videoModel + } +} diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index f868169d..539ed2ba 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -243,6 +243,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: NotificationView.self, viewModelClass: NotificationModel.self) MoleculeObjectMapping.shared()?.register(viewClass: CollapsableNotification.self, viewModelClass: CollapsableNotificationModel.self) + // TODO: move all of these out of here. // MARK:- Helper models try? ModelRegistry.register(RuleRequiredModel.self) try? ModelRegistry.register(RuleAnyRequiredModel.self) @@ -261,7 +262,8 @@ import Foundation try? ModelRegistry.register(ActionTopNotificationModel.self) // MARK:- Behaviors - try? ModelRegistry.register(ScreenBrightnessModifierBehavior.self) + try? ModelRegistry.register(handler: ScreenBrightnessModifierBehavior.self, for: ScreenBrightnessModifierBehaviorModel.self) + try? ModelRegistry.register(handler: PageGetContactBehavior.self, for: PageGetContactBehaviorModel.self) } /// Convenience function to get required modules for a give model diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift index 8581deb1..46de07fa 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableIconAllTextLinksModel.swift @@ -7,7 +7,7 @@ // -public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModelProtocol { +public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -16,6 +16,10 @@ public class ListLeftVariableIconAllTextLinksModel: ListItemModel, MoleculeModel public var image: ImageViewModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel + public var children: [MoleculeModelProtocol] { + return [image, eyebrowHeadlineBodyLink] + } + //-------------------------------------------------- // MARK: - Method //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift index c9410775..ec646f86 100644 --- a/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift +++ b/MVMCoreUI/Atomic/Molecules/VerticalCombinationViews/EyebrowHeadlineBodyLinkModel.swift @@ -7,7 +7,7 @@ // -public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { +public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -20,6 +20,10 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { public var body: LabelModel? public var link: LinkModel? + public var children: [MoleculeModelProtocol] { + [eyebrow, headline, body, link].compactMap { (molecule: MoleculeModelProtocol?) in molecule } + } + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -68,7 +72,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) eyebrow = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .eyebrow) - headline = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .headline) + headline = try typeContainer.decodeMoleculeIfPresent(codingKey: .headline) body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) link = try typeContainer.decodeIfPresent(LinkModel.self, forKey: .link) setDefaults() @@ -83,7 +87,7 @@ public class EyebrowHeadlineBodyLinkModel: MoleculeModelProtocol { try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(eyebrow, forKey: .eyebrow) - try container.encodeIfPresent(headline, forKey: .headline) + try container.encodeModelIfPresent(headline, forKey: .headline) try container.encodeIfPresent(body, forKey: .body) try container.encodeIfPresent(link, forKey: .link) } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift index 79368f01..2823e5a5 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeModelProtocol.swift @@ -21,6 +21,20 @@ public extension MoleculeModelProtocol { static var categoryCodingKey: String { "moleculeName" } } +extension KeyedDecodingContainer where Key: CodingKey { + /// Decodes to a registered molecule based on the identifier + public func decodeMoleculeIfPresent(codingKey: KeyedDecodingContainer.Key) throws -> T? { + + guard let model: MoleculeModelProtocol = try decodeModelIfPresent(codingKey: codingKey) else { return nil } + guard let modelT = model as? T else { + let message = "ModelRegistry Error wrong type: \(codingKey.stringValue)" + MVMCoreLoggingHandler.logDebugMessage(withDelegate: message) + throw ModelRegistry.Error.decoderOther(message: message) + } + return modelT + } +} + public extension MoleculeModelProtocol { // Base case. No additional children to traverse. diff --git a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift index 04bc080b..9a7e9e33 100644 --- a/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/TemplateProtocol.swift @@ -22,12 +22,29 @@ public extension TemplateProtocol where Self: ViewController { let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() try decoder.add(delegateObject: delegateObjectIVar) - self.templateModel = try decodeTemplate(using: decoder, from: data) - self.model = templateModel as? MVMControllerModelProtocol + templateModel = try decodeTemplate(using: decoder, from: data) + model = templateModel as? MVMControllerModelProtocol + guard let model = model else { return } + traverseAndAddRequiredBehaviors() + var behaviorHandler = self + behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar) } func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel { return try decoder.decode(TemplateModel.self, from: data) } + /// Traverses all models and adds any required behavior models. + func traverseAndAddRequiredBehaviors() { + guard var model = model else { return } + let behaviorModels: [PageBehaviorModelProtocol] = model.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in + if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer { + return accumulator + behaviorRequirer.getRequiredBehaviors() + } + return accumulator + } + for behavior in behaviorModels { + model.add(behavior: behavior) + } + } } diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index c3d9bbbb..94d6ee80 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -29,7 +29,7 @@ import Foundation public var screenHeading: String? public var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? public var formRules: [FormGroupRule]? - public var behaviors: [PageBehaviorProtocol]? + public var behaviors: [PageBehaviorModelProtocol]? public var rootMolecules: [MoleculeModelProtocol] { [] } public var tabBarHidden: Bool = false diff --git a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift index 64242fc3..78f6f604 100644 --- a/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift +++ b/MVMCoreUI/BaseControllers/MVMControllerModelProtocol.swift @@ -9,6 +9,6 @@ import Foundation -public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol, PageBehaviorsTemplateProtocol { +public protocol MVMControllerModelProtocol: TemplateModelProtocol, FormHolderModelProtocol, PageBehaviorHandlerModelProtocol { } diff --git a/MVMCoreUI/BaseControllers/ScrollingViewController.swift b/MVMCoreUI/BaseControllers/ScrollingViewController.swift index 19c9d001..4fd23be2 100644 --- a/MVMCoreUI/BaseControllers/ScrollingViewController.swift +++ b/MVMCoreUI/BaseControllers/ScrollingViewController.swift @@ -74,8 +74,8 @@ open class ScrollingViewController: ViewController { } open func scrollViewDidScroll(_ scrollView: UIScrollView) { - executeBehaviors { (behavior: PageScrolledBehavior) in - behavior.pageScrolled(scrollView: scrollView) + executeBehaviors { [weak self] (behavior: PageScrolledBehavior) in + behavior.pageScrolled(scrollView: scrollView, self?.delegateObjectIVar) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index a2d82952..b06260a8 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -8,7 +8,7 @@ import UIKit -@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol, PageProtocol { +@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol, PageProtocol, PageBehaviorHandlerProtocol { //-------------------------------------------------- // MARK: - Properties @@ -34,6 +34,8 @@ import UIKit public var formValidator: FormValidator? + public var behaviors: [PageBehaviorProtocol]? + public var needsUpdateUI = false private var observingForResponses = false private var initialLoadFinished = false @@ -380,16 +382,16 @@ import UIKit pageShown() } - executeBehaviors { (behavior: PageVisibilityBehavior) in - behavior.onPageShown() + executeBehaviors { [weak self] (behavior: PageVisibilityBehavior) in + behavior.onPageShown(self?.delegateObjectIVar) } } open override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - executeBehaviors { (behavior: PageVisibilityBehavior) in - behavior.onPageHidden() + executeBehaviors { [weak self] (behavior: PageVisibilityBehavior) in + behavior.onPageHidden(self?.delegateObjectIVar) } } @@ -620,6 +622,6 @@ import UIKit //-------------------------------------------------- func executeBehaviors(_ behaviorBlock:(_ behavior:T)->Void) { - model?.behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } + behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } } } diff --git a/MVMCoreUI/Behaviors/GetContactBehavior.swift b/MVMCoreUI/Behaviors/GetContactBehavior.swift new file mode 100644 index 00000000..179fb8b2 --- /dev/null +++ b/MVMCoreUI/Behaviors/GetContactBehavior.swift @@ -0,0 +1,56 @@ +// +// GetContactBehavior.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/22/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation +import Contacts + +public protocol PageGetContactBehaviorConsumerProtocol { + func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])? + func consume(contacts: [CNContact]) +} + +public class PageGetContactBehaviorModel: PageBehaviorModelProtocol { + public class var identifier: String { "pageGetContactBehavior" } + public var shouldAllowMultipleInstances: Bool { false } + + public init() {} +} + +public class PageGetContactBehavior: PageVisibilityBehavior { + var delegate: MVMCoreUIDelegateObject? + + public required init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.delegate = delegateObject + } + + public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { + // Ask for permission + CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in + guard access, + error == nil, + let model = (self?.delegate?.moleculeDelegate as? PageProtocol)?.pageModel as? TemplateModelProtocol else { return } + // Iterate models and provide contact + let page = self?.delegate?.moleculeDelegate as? PageProtocol + let store = CNContactStore() + let consumers: [PageGetContactBehaviorConsumerProtocol] = model.allMoleculesOfType() + for consumer in consumers { + guard let parameters = consumer.getMatchParameters(), + let contacts = try? store.unifiedContacts(matching: parameters.0, keysToFetch: parameters.1) else { return } + consumer.consume(contacts: contacts) + } + + // Tell template to update + MVMCoreDispatchUtility.performBlock(onMainThread: { + // TODO: move to protocol function instead + (page as? ViewController)?.handleNewData() + }) + } + } + + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {} +} diff --git a/MVMCoreUI/Behaviors/PageBehavior.swift b/MVMCoreUI/Behaviors/PageBehavior.swift deleted file mode 100644 index aaf915a1..00000000 --- a/MVMCoreUI/Behaviors/PageBehavior.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// PageBehaviors.swift -// MVMCoreUI -// -// Created by Kyle on 5/8/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public protocol PageBehaviorProtocol: ModelProtocol { - - /// The type of rule - var behaviorName: String { get } -} - -public extension PageBehaviorProtocol { - - var behaviorName: String { - get { Self.identifier } - } - - static var categoryCodingKey: String { - "behaviorName" - } - - static var categoryName: String { - "\(PageBehaviorProtocol.self)" - } -} - -public protocol PageVisibilityBehavior: PageBehaviorProtocol { - - func onPageShown() - func onPageHidden() -} - -public protocol PageScrolledBehavior: PageBehaviorProtocol { - - func pageScrolled(scrollView: UIScrollView) -} - -public protocol PageBehaviorsTemplateProtocol { - - var behaviors: [PageBehaviorProtocol]? { get set } - -} - -public extension PageBehaviorsTemplateProtocol { - mutating func add(behavior: PageBehaviorProtocol) { - var newBehaviors = behaviors ?? [] - newBehaviors.append(behavior) - self.behaviors = newBehaviors - } -} - -public extension MVMCoreUIDelegateObject { - weak var behaviorTemplateDelegate: (PageBehaviorsTemplateProtocol & NSObjectProtocol)? { - get { - return (moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorsTemplateProtocol & NSObjectProtocol) - } - } -} diff --git a/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift new file mode 100644 index 00000000..17f1b85e --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorHandlerModelProtocol.swift @@ -0,0 +1,25 @@ +// +// PageBehaviorHandlerModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol PageBehaviorHandlerModelProtocol { + var behaviors: [PageBehaviorModelProtocol]? { get set } +} + +public extension PageBehaviorHandlerModelProtocol { + + /// Adds the behavior model to the behaviors if possible. + mutating func add(behavior: PageBehaviorModelProtocol) { + var newBehaviors = behaviors ?? [] + guard !behavior.shouldAllowMultipleInstances, + !newBehaviors.contains(where: { $0.behaviorName == behavior.behaviorName + }) else { return } + newBehaviors.append(behavior) + self.behaviors = newBehaviors + } +} + diff --git a/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift new file mode 100644 index 00000000..b90ac1aa --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorHandlerProtocol.swift @@ -0,0 +1,30 @@ +// +// PageBehaviorHandlerProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol PageBehaviorHandlerProtocol { + var behaviors: [PageBehaviorProtocol]? { get set } +} + +public extension PageBehaviorHandlerProtocol { + /// Creates the behaviors and sets the variable. + mutating func createBehaviors(for model: PageBehaviorHandlerModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + guard let behaviorModels = model.behaviors else { + behaviors = nil + return + } + var behaviors: [PageBehaviorProtocol] = [] + for behaviorModel in behaviorModels { + guard let handlerType = ModelRegistry.getHandler(behaviorModel) as? PageBehaviorProtocol.Type else { continue } + let behavior = handlerType.init(model: behaviorModel, delegateObject: delegateObject) + behaviors.append(behavior) + } + self.behaviors = behaviors.count > 0 ? behaviors : nil + } +} diff --git a/MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift new file mode 100644 index 00000000..d8502a7e --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorModelProtocol.swift @@ -0,0 +1,35 @@ +// +// PageBehaviorModelProtocol.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol PageBehaviorModelProtocol: ModelProtocol { + + /// The type of rule + var behaviorName: String { get } + + /// If the behavior should allow multiple instances + var shouldAllowMultipleInstances: Bool { get } +} + +public extension PageBehaviorModelProtocol { + + var behaviorName: String { + get { type(of:self).identifier } + } + + static var shouldAllowMultipleInstances: Bool { + get { true } + } + + static var categoryCodingKey: String { + "behaviorName" + } + + static var categoryName: String { + "\(PageBehaviorModelProtocol.self)" + } +} diff --git a/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift b/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift new file mode 100644 index 00000000..6085188c --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorProtocol.swift @@ -0,0 +1,34 @@ +// +// PageBehaviorProtocol.swift +// MVMCoreUI +// +// Created by Kyle on 5/8/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol PageBehaviorProtocol: ModelHandlerProtocol { + + /// Initializes the behavior with the model + init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) +} + +public protocol PageVisibilityBehavior: PageBehaviorProtocol { + + func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) + func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) +} + +public protocol PageScrolledBehavior: PageBehaviorProtocol { + + func pageScrolled(scrollView: UIScrollView,_ delegateObject: MVMCoreUIDelegateObject?) +} + +public extension MVMCoreUIDelegateObject { + weak var behaviorTemplateDelegate: (PageBehaviorHandlerProtocol & NSObjectProtocol)? { + get { + return (moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorHandlerProtocol & NSObjectProtocol) + } + } +} diff --git a/MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift b/MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift new file mode 100644 index 00000000..9ca72e1d --- /dev/null +++ b/MVMCoreUI/Behaviors/PageBehaviorProtocolRequirer.swift @@ -0,0 +1,11 @@ +// +// PageBehaviorProtocolRequirer.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/29/21. +// Copyright © 2021 Verizon Wireless. All rights reserved. +// + +public protocol PageBehaviorProtocolRequirer { + func getRequiredBehaviors() -> [PageBehaviorModelProtocol] +} diff --git a/MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift b/MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift deleted file mode 100644 index c43d4ecc..00000000 --- a/MVMCoreUI/Behaviors/PageScrolledClosureBehavior.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// PageScrolledClosureBehavior.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 2/11/21. -// Copyright © 2021 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class PageScrolledClosureBehavior: PageScrolledBehavior { - - public static var identifier = "pageScrolledClosureBehavior" - - public var pageScrolledHandler: (_ scrollView: UIScrollView) -> Void - - public init(with onPageScrolledHandler: @escaping (_ scrollView: UIScrollView) -> Void) { - self.pageScrolledHandler = onPageScrolledHandler - } - - // This class is not meant to be decoded and encoded really. - public required init(from decoder: Decoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageScrolledClosureBehavior does not decode.") - } - - public func encode(to encoder: Encoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageScrolledClosureBehavior does not encode.") - } - - public func pageScrolled(scrollView: UIScrollView) { - pageScrolledHandler(scrollView) - } -} diff --git a/MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift b/MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift deleted file mode 100644 index f5ecd82c..00000000 --- a/MVMCoreUI/Behaviors/PageVisibilityClosureBehavior.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// PageVisibilityClosureBehavior.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 2/11/21. -// Copyright © 2021 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class PageVisibilityClosureBehavior: PageVisibilityBehavior { - - public static var identifier = "pageVisibilityClosureBehavior" - - public var pageShownHandler: () -> Void - public var pageHiddenHandler: () -> Void - - public init(with onPageShownHandler: @escaping () -> Void, onPageHiddenHandler: @escaping () -> Void) { - self.pageShownHandler = onPageShownHandler - self.pageHiddenHandler = onPageHiddenHandler - } - - // This class is not meant to be decoded and encoded really. - public required init(from decoder: Decoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageVisibilityClosureBehavior does not decode.") - } - - public func encode(to encoder: Encoder) throws { - throw ModelRegistry.Error.decoderOther(message: "PageVisibilityClosureBehavior does not encode.") - } - - //MARK:- PageVisibilityBehavior - public func onPageShown() { - pageShownHandler() - } - - public func onPageHidden() { - pageHiddenHandler() - } -} diff --git a/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift b/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift index b6ea9f6d..59d80211 100644 --- a/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift +++ b/MVMCoreUI/Behaviors/ScreenBrightnessModifierBehavior.swift @@ -6,52 +6,14 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // -public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { - +public class ScreenBrightnessModifierBehaviorModel: PageBehaviorModelProtocol { + public var shouldAllowMultipleInstances: Bool = false public static var identifier = "screenBrightnessModifier" - @Clamping(range: 0...1) var screenBrightness: CGFloat - var originalScreenBrightness: CGFloat? - //MARK:- PageVisibilityBehavior - - public func onPageShown() { - changeScreenBrightness() - } - - public func onPageHidden() { - restoreScreenBrightness() - } - - //MARK:- Behavior - - func changeScreenBrightness() { - guard originalScreenBrightness == nil else { return } - originalScreenBrightness = UIScreen.main.brightness - UIScreen.main.brightness = screenBrightness - NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil) - } - - func restoreScreenBrightness() { - guard let originalScreenBrightness = originalScreenBrightness else { return } - UIScreen.main.brightness = originalScreenBrightness - self.originalScreenBrightness = nil - NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil) - } - - @objc func willResignActive() { - restoreScreenBrightness() - NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) - } - - @objc func didBecomeActive() { - NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) - changeScreenBrightness() - } - //MARK:- Codable - + private enum CodingKeys: String, CodingKey { case screenBrightness } @@ -66,3 +28,49 @@ public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { try container.encode(screenBrightness, forKey: .screenBrightness) } } + +public class ScreenBrightnessModifierBehavior: PageVisibilityBehavior { + var model: PageBehaviorModelProtocol + + required public init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?) { + self.model = model + } + + //MARK:- PageVisibilityBehavior + + public func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) { + changeScreenBrightness() + } + + public func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) { + restoreScreenBrightness() + } + + //MARK:- Behavior + + func changeScreenBrightness() { + guard let model = model as? ScreenBrightnessModifierBehaviorModel, + model.originalScreenBrightness == nil else { return } + model.originalScreenBrightness = UIScreen.main.brightness + UIScreen.main.brightness = model.screenBrightness + NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification, object: nil) + } + + func restoreScreenBrightness() { + guard let model = model as? ScreenBrightnessModifierBehaviorModel, + let originalScreenBrightness = model.originalScreenBrightness else { return } + UIScreen.main.brightness = originalScreenBrightness + model.originalScreenBrightness = nil + NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil) + } + + @objc func willResignActive() { + restoreScreenBrightness() + NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) + } + + @objc func didBecomeActive() { + NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) + changeScreenBrightness() + } +}