diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5a04c734..7a83f38e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -204,7 +204,6 @@ 9458C3172406C8FD00930963 /* UIFont+FontWrapping.h in Headers */ = {isa = PBXBuildFile; fileRef = 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9458C3182406C8FD00930963 /* UIFont+FontWrapping.m in Sources */ = {isa = PBXBuildFile; fileRef = 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; - 94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C0150924215643005811A9 /* ActionTopAlertModel.swift */; }; 94C0150C2421564A005811A9 /* ActionCollapseNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C0150B2421564A005811A9 /* ActionCollapseNotificationModel.swift */; }; 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */; }; 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */; }; @@ -281,7 +280,6 @@ AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */; }; AF1C33652883B5A4006B1001 /* ActionTopNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33642883B5A4006B1001 /* ActionTopNotificationHandler.swift */; }; AF1C336928859778006B1001 /* ActionAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336828859778006B1001 /* ActionAlertHandler.swift */; }; - AF1C336B28859C73006B1001 /* ActionTopAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336A28859C73006B1001 /* ActionTopAlertHandler.swift */; }; AF1C336D28859EE1006B1001 /* ActionOpenPanelHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336C28859EE1006B1001 /* ActionOpenPanelHandler.swift */; }; AF1C336F2885A16A006B1001 /* ActionCollapseNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */; }; AF1C33712885AE76006B1001 /* MVMCoreUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */; }; @@ -462,16 +460,6 @@ D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */; }; D29DF11C21E684A9003B2FB9 /* MVMCoreUISplitViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */; }; - D29DF12921E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */; }; - D29DF12C21E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */; }; - D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */; }; - D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */; }; - D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */; }; D29DF15421E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF15321E69760003B2FB9 /* MVMCoreUIPanelButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF17521E69E1F003B2FB9 /* ButtonDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -532,8 +520,6 @@ D2CAC7CB251104E100C75681 /* NotificationXButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */; }; D2CAC7CD251104FE00C75681 /* NotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CC251104FE00C75681 /* NotificationModel.swift */; }; D2CAC7CF2511052300C75681 /* CollapsableNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */; }; - D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */; }; - D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */; }; D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */; }; D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */; }; D2D3957A252FDBB300047B11 /* ModalSectionListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2D39579252FDBB300047B11 /* ModalSectionListTemplate.swift */; }; @@ -566,11 +552,6 @@ D2ED27EE254B0CE700A1C293 /* ActionAlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27E9254B0CE600A1C293 /* ActionAlertModel.swift */; }; D2ED27EF254B0CE700A1C293 /* AlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27EA254B0CE700A1C293 /* AlertModel.swift */; }; D2ED27FC254B0E0300A1C293 /* AlertObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2ED27F3254B0E0200A1C293 /* AlertObject.swift */; }; - D2ED280F254B0EB800A1C293 /* MVMCoreTopAlertViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2808254B0EB700A1C293 /* MVMCoreTopAlertViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2ED2810254B0EB800A1C293 /* MVMCoreTopAlertDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2809254B0EB700A1C293 /* MVMCoreTopAlertDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2ED2811254B0EB800A1C293 /* MVMCoreTopAlertObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED280A254B0EB700A1C293 /* MVMCoreTopAlertObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2ED280B254B0EB800A1C293 /* MVMCoreTopAlertObject.m */; }; - D2ED2815254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D2ED2814254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D12513EA6900564112 /* NotificationXButton.swift */; }; D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D32514F80C00564112 /* CollapsableNotification.swift */; }; D2FA83D62515021F00564112 /* CollapsableNotificationTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */; }; @@ -809,7 +790,6 @@ 9458C3152406C8FD00930963 /* UIFont+FontWrapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+FontWrapping.h"; sourceTree = ""; }; 9458C3162406C8FD00930963 /* UIFont+FontWrapping.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIFont+FontWrapping.m"; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; - 94C0150924215643005811A9 /* ActionTopAlertModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionTopAlertModel.swift; sourceTree = ""; }; 94C0150B2421564A005811A9 /* ActionCollapseNotificationModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionCollapseNotificationModel.swift; sourceTree = ""; }; 94C2D9832386F3F80006CF46 /* LabelAttributeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeModel.swift; sourceTree = ""; }; 94C2D9A023872BCC0006CF46 /* LabelAttributeUnderlineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeUnderlineModel.swift; sourceTree = ""; }; @@ -885,7 +865,6 @@ AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = ""; }; AF1C33642883B5A4006B1001 /* ActionTopNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionTopNotificationHandler.swift; sourceTree = ""; }; AF1C336828859778006B1001 /* ActionAlertHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionAlertHandler.swift; sourceTree = ""; }; - AF1C336A28859C73006B1001 /* ActionTopAlertHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionTopAlertHandler.swift; sourceTree = ""; }; AF1C336C28859EE1006B1001 /* ActionOpenPanelHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionOpenPanelHandler.swift; sourceTree = ""; }; AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCollapseNotificationHandler.swift; sourceTree = ""; }; AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIActionHandler.swift; sourceTree = ""; }; @@ -1066,16 +1045,6 @@ D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSLayoutConstraint+MFConvenience.m"; sourceTree = ""; }; D29DF11A21E684A9003B2FB9 /* MVMCoreUISplitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUISplitViewController.h; sourceTree = ""; }; D29DF11B21E684A9003B2FB9 /* MVMCoreUISplitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISplitViewController.m; sourceTree = ""; }; - D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertMainView.h; sourceTree = ""; }; - D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertView.h; sourceTree = ""; }; - D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertExpandableView.m; sourceTree = ""; }; - D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertShortView.h; sourceTree = ""; }; - D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertBaseView.h; sourceTree = ""; }; - D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertView.m; sourceTree = ""; }; - D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertMainView.m; sourceTree = ""; }; - D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertShortView.m; sourceTree = ""; }; - D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreUITopAlertExpandableView.h; sourceTree = ""; }; - D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUITopAlertBaseView.m; sourceTree = ""; }; D29DF13821E68636003B2FB9 /* MFStyler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MFStyler.h; sourceTree = ""; }; D29DF13921E68637003B2FB9 /* MFStyler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFStyler.m; sourceTree = ""; }; D29DF14421E68728003B2FB9 /* MFSizeObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MFSizeObject.m; sourceTree = ""; }; @@ -1138,8 +1107,6 @@ D2CAC7CA251104E100C75681 /* NotificationXButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButtonModel.swift; sourceTree = ""; }; D2CAC7CC251104FE00C75681 /* NotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationModel.swift; sourceTree = ""; }; D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationModel.swift; sourceTree = ""; }; - D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertMainView+Extension.swift"; sourceTree = ""; }; - D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertExpandableView+Extension.swift"; sourceTree = ""; }; D2D2FCEF252B72AF0033EAAA /* MoleculeSectionFooterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooterModel.swift; sourceTree = ""; }; D2D2FCF2252B72CF0033EAAA /* MoleculeSectionFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeSectionFooter.swift; sourceTree = ""; }; D2D39579252FDBB300047B11 /* ModalSectionListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalSectionListTemplate.swift; sourceTree = ""; }; @@ -1171,11 +1138,6 @@ D2ED27E9254B0CE600A1C293 /* ActionAlertModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionAlertModel.swift; sourceTree = ""; }; D2ED27EA254B0CE700A1C293 /* AlertModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertModel.swift; sourceTree = ""; }; D2ED27F3254B0E0200A1C293 /* AlertObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertObject.swift; sourceTree = ""; }; - D2ED2808254B0EB700A1C293 /* MVMCoreTopAlertViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertViewProtocol.h; sourceTree = ""; }; - D2ED2809254B0EB700A1C293 /* MVMCoreTopAlertDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertDelegateProtocol.h; sourceTree = ""; }; - D2ED280A254B0EB700A1C293 /* MVMCoreTopAlertObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreTopAlertObject.h; sourceTree = ""; }; - D2ED280B254B0EB800A1C293 /* MVMCoreTopAlertObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreTopAlertObject.m; sourceTree = ""; }; - D2ED2814254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVMCoreGlobalTopAlertDelegateProtocol.h; sourceTree = ""; }; D2FA83D12513EA6900564112 /* NotificationXButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationXButton.swift; sourceTree = ""; }; D2FA83D32514F80C00564112 /* CollapsableNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotification.swift; sourceTree = ""; }; D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollapsableNotificationTopView.swift; sourceTree = ""; }; @@ -1507,8 +1469,6 @@ 94C01508242155FE005811A9 /* Actions */ = { isa = PBXGroup; children = ( - 94C0150924215643005811A9 /* ActionTopAlertModel.swift */, - AF1C336A28859C73006B1001 /* ActionTopAlertHandler.swift */, 94C0150B2421564A005811A9 /* ActionCollapseNotificationModel.swift */, AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */, D2C78CD124228BBD00B69FDE /* ActionOpenPanelModel.swift */, @@ -2154,23 +2114,8 @@ isa = PBXGroup; children = ( AFA4932129E5EF2E001A9663 /* NotificationHandler.swift */, - D2ED2814254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h */, - D2ED2809254B0EB700A1C293 /* MVMCoreTopAlertDelegateProtocol.h */, - D2ED280A254B0EB700A1C293 /* MVMCoreTopAlertObject.h */, - D2ED280B254B0EB800A1C293 /* MVMCoreTopAlertObject.m */, - D2ED2808254B0EB700A1C293 /* MVMCoreTopAlertViewProtocol.h */, D20C7008250BF99B0095B21C /* TopNotificationModel.swift */, D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */, - D29DF12021E6851E003B2FB9 /* MVMCoreUITopAlertView.h */, - D29DF12421E6851E003B2FB9 /* MVMCoreUITopAlertView.m */, - D29DF12321E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h */, - D29DF12821E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m */, - D29DF11F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h */, - D29DF12521E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m */, - D29DF12221E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h */, - D29DF12621E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m */, - D29DF12721E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h */, - D29DF12121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m */, ); path = Notification; sourceTree = ""; @@ -2478,11 +2423,9 @@ D2FA83D12513EA6900564112 /* NotificationXButton.swift */, D2CAC7CC251104FE00C75681 /* NotificationModel.swift */, D23118B225124E18001C8440 /* Notification.swift */, - D2CAC7D02511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift */, D2CAC7CE2511052300C75681 /* CollapsableNotificationModel.swift */, D2FA83D32514F80C00564112 /* CollapsableNotification.swift */, D2FA83D52515021F00564112 /* CollapsableNotificationTopView.swift */, - D2CAC7D2251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift */, ); path = TopNotification; sourceTree = ""; @@ -2558,7 +2501,6 @@ D29DF25921E6A22D003B2FB9 /* MFButtonProtocol.h in Headers */, D29DF28421E7AB24003B2FB9 /* MVMCoreUICommonViewsUtility.h in Headers */, D29DF2CE21E7C104003B2FB9 /* MFLoadingViewController.h in Headers */, - D29DF12A21E6851E003B2FB9 /* MVMCoreUITopAlertView.h in Headers */, D29DF27521E79E81003B2FB9 /* MVMCoreUILoggingHandler.h in Headers */, D29DF2B321E7B76D003B2FB9 /* MFLoadingSpinner.h in Headers */, D20492A424329A2800A5EED6 /* MVMCoreUIPagingProtocol.h in Headers */, @@ -2567,22 +2509,14 @@ D29DF26E21E6AA0B003B2FB9 /* FLAnimatedImage.h in Headers */, D29DF11621E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.h in Headers */, 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */, - D29DF13121E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.h in Headers */, D29DF2CA21E7BFC8003B2FB9 /* MFSizeThreshold.h in Headers */, D29DF28021E7AA51003B2FB9 /* MVMCoreUIDetailViewProtocol.h in Headers */, D29DF2EE21ECEADF003B2FB9 /* MFFonts.h in Headers */, - D29DF12D21E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.h in Headers */, D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */, - D2ED2811254B0EB800A1C293 /* MVMCoreTopAlertObject.h in Headers */, - D2ED280F254B0EB800A1C293 /* MVMCoreTopAlertViewProtocol.h in Headers */, - D2ED2810254B0EB800A1C293 /* MVMCoreTopAlertDelegateProtocol.h in Headers */, - D2ED2815254B0EE400A1C293 /* MVMCoreGlobalTopAlertDelegateProtocol.h in Headers */, D29DF26F21E6AA0B003B2FB9 /* FLAnimatedImageView.h in Headers */, D29DF2A121E7AF4E003B2FB9 /* MVMCoreUIUtility.h in Headers */, D29DF2C821E7BFC1003B2FB9 /* MFSizeObject.h in Headers */, D29DF2E121E9240B003B2FB9 /* MVMCoreUIPanelProtocol.h in Headers */, - D29DF12921E6851E003B2FB9 /* MVMCoreUITopAlertMainView.h in Headers */, - D29DF12C21E6851E003B2FB9 /* MVMCoreUITopAlertShortView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2745,7 +2679,6 @@ D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */, 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */, EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */, - D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */, BB47A588241615FA002BB23C /* ListOneColumnFullWidthTextDividerSubsection.swift in Sources */, 012A88C8238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift in Sources */, @@ -2786,11 +2719,9 @@ 0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */, D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */, D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */, - D29DF12E21E6851E003B2FB9 /* MVMCoreUITopAlertView.m in Sources */, AA1EC59724373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift in Sources */, D23A8FEB26122F69007E14CE /* VisibleBehaviorForVideoModel.swift in Sources */, BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */, - D2CAC7D3251105A700C75681 /* MVMCoreUITopAlertExpandableView+Extension.swift in Sources */, AA07EA932510A451009A2AE3 /* Star.swift in Sources */, D29DF2CF21E7C104003B2FB9 /* MFLoadingViewController.m in Sources */, D28A837B23C928DA00DFE4FC /* MoleculeListCellProtocol.swift in Sources */, @@ -2828,7 +2759,6 @@ 0A0FEC7425D42A5E00AF2548 /* BaseItemPickerEntryField.swift in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, D23A8FF82612308D007E14CE /* PageBehaviorProtocolRequirer.swift in Sources */, - D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, 94C2D9A723872DA90006CF46 /* LabelAttributeColorModel.swift in Sources */, 943820842432382400B43AF3 /* WebView.swift in Sources */, 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */, @@ -2877,7 +2807,6 @@ 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, AA104ADA244734DB004D2810 /* HeadersH1LandingPageHeader.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, - D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */, 94F6516D2437954100631BF9 /* Tabs.swift in Sources */, 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, @@ -2972,7 +2901,6 @@ D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */, C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, 32F8804624765C6E00C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinksModel.swift in Sources */, - AF1C336B28859C73006B1001 /* ActionTopAlertHandler.swift in Sources */, 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */, D23118B325124E18001C8440 /* Notification.swift in Sources */, @@ -3045,7 +2973,6 @@ D2FA83D22513EA6900564112 /* NotificationXButton.swift in Sources */, D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */, 0A7ECC5F243CEB1200C828E8 /* ColorViewWithLabel.swift in Sources */, - 94C0150A24215643005811A9 /* ActionTopAlertModel.swift in Sources */, BB3BC12F2550094500297977 /* ListLeftVariableIconWithRightCaretAllTextLinks.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D2092355244FA0FD0044AD09 /* ThreeLayerTemplateModelProtocol.swift in Sources */, @@ -3084,7 +3011,6 @@ AA45AA0D24BF0276007A6EA7 /* LockUpsPlanNames.swift in Sources */, 8DE5BECF2456F7B100772E76 /* ListTwoColumnDropdownSelectors.swift in Sources */, D2E1FADF2268B8E700AEFD8C /* ThreeLayerTableViewController.swift in Sources */, - D2CAC7D12511058C00C75681 /* MVMCoreUITopAlertMainView+Extension.swift in Sources */, 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */, 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */, 01F2C20427C81F9700DC3D36 /* SubNavInteractor.swift.swift in Sources */, @@ -3144,7 +3070,6 @@ EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */, D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */, 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */, - D2ED2812254B0EB800A1C293 /* MVMCoreTopAlertObject.m in Sources */, 0AA4D2E125CAEC72008DB32D /* AccessibilityModelProtocol.swift in Sources */, EA05EFA9278DDE2C00828819 /* ClearFormFieldEffectModel.swift in Sources */, C003506123AA94CD00B6AC29 /* Button.swift in Sources */, @@ -3159,7 +3084,6 @@ D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */, AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, - D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */, D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */, BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */, D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Actions/ActionCollapseNotificationHandler.swift b/MVMCoreUI/Atomic/Actions/ActionCollapseNotificationHandler.swift index 069ee74f..27cd6e63 100644 --- a/MVMCoreUI/Atomic/Actions/ActionCollapseNotificationHandler.swift +++ b/MVMCoreUI/Atomic/Actions/ActionCollapseNotificationHandler.swift @@ -9,11 +9,22 @@ import Foundation import MVMCore -/// Collapse the current top notification. +/// Notifications that conform are collapsable and can collapse. +public protocol CollapsableNotificationProtocol { + /// Collapses the notification. + func collapse() +} + +/// Collapses the current notification if it can collapse, otherwise dismisses it. open class ActionCollapseNotificationHandler: MVMCoreActionHandlerProtocol { required public init() {} open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws { - CoreUIObject.sharedInstance()?.globalTopAlertDelegate?.getTopAlertView?().collapseNotification?() + guard let notification = await NotificationHandler.shared().getCurrentNotification() else { return } + guard let notification = notification.0 as? CollapsableNotificationProtocol else { + NotificationHandler.shared().hideTopAlertView() + return + } + notification.collapse() } } diff --git a/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift b/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift index a2e1f279..e172db9c 100644 --- a/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift +++ b/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift @@ -9,15 +9,11 @@ import Foundation import MVMCore -/// Collapse the current top notification. +/// Dismiss the current top notification. open class ActionDismissNotificationHandler: MVMCoreActionHandlerProtocol { required public init() {} open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws { - await withCheckedContinuation { continuation in - CoreUIObject.sharedInstance()?.globalTopAlertDelegate?.getTopAlertView?().hideAlertView?(true, completionHandler: { finished in - continuation.resume() - }) ?? continuation.resume() - } + NotificationHandler.shared().hideTopAlertView() } } diff --git a/MVMCoreUI/Atomic/Actions/ActionTopAlertHandler.swift b/MVMCoreUI/Atomic/Actions/ActionTopAlertHandler.swift deleted file mode 100644 index 92a7d1e5..00000000 --- a/MVMCoreUI/Atomic/Actions/ActionTopAlertHandler.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// ActionTopAlertHandler.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 7/18/22. -// Copyright © 2022 Verizon Wireless. All rights reserved. -// - -import Foundation -import MVMCore - -/// Creates and shows an alert using the ResponseInfo of a Page found in the cache. -open class ActionTopAlertHandler: MVMCoreActionHandlerProtocol { - required public init() {} - - open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws { - guard let model = model as? ActionTopAlertModel else { return } - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in - MVMCoreCache.shared()?.fetchJSON(forPageType: model.pageType, queue: nil, waitUntilFinished: true, completionHandler: { json in - guard let responseInfo = json?.optionalDictionaryForKey(KeyResponseInfo) else { - continuation.resume(throwing: ModelRegistry.Error.decoderOther(message: "Alert Page \(model.pageType) missing ResponseInfo")) - return - } - - let topAlertObject = MVMCoreTopAlertObject(responseInfo: responseInfo)! - topAlertObject.delegate = (delegateObject as? MVMCoreUIDelegateObject)?.topAlertDelegate - topAlertObject.pageType = model.pageType - NotificationHandler.shared().showTopAlert(with: topAlertObject) - continuation.resume() - }) - } - } -} diff --git a/MVMCoreUI/Atomic/Actions/ActionTopAlertModel.swift b/MVMCoreUI/Atomic/Actions/ActionTopAlertModel.swift deleted file mode 100644 index 440e318c..00000000 --- a/MVMCoreUI/Atomic/Actions/ActionTopAlertModel.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// ActionTopAlertModel.swift -// MVMCore -// -// Created by Suresh, Kamlesh on 12/16/19. -// Copyright © 2019 myverizon. All rights reserved. -// - -import Foundation - -public struct ActionTopAlertModel: ActionModelProtocol { - - public static var identifier: String = "topAlert" - public var actionType: String = ActionTopAlertModel.identifier - public var pageType: String - public var extraParameters: JSONValueDictionary? - public var analyticsData: JSONValueDictionary? - - public init(pageType: String, _ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) { - self.pageType = pageType - self.extraParameters = extraParameters - self.analyticsData = analyticsData - } -} diff --git a/MVMCoreUI/Atomic/Actions/ActionTopNotificationHandler.swift b/MVMCoreUI/Atomic/Actions/ActionTopNotificationHandler.swift index a6b9a223..eedfcd9a 100644 --- a/MVMCoreUI/Atomic/Actions/ActionTopNotificationHandler.swift +++ b/MVMCoreUI/Atomic/Actions/ActionTopNotificationHandler.swift @@ -15,6 +15,6 @@ open class ActionTopNotificationHandler: MVMCoreActionHandlerProtocol { open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws { guard let model = model as? ActionTopNotificationModel else { return } - NotificationHandler.shared().showTopNotification(with: model.topNotification) + try await NotificationHandler.shared().showNotification(for: model.topNotification, delegateObject: delegateObject as? MVMCoreUIDelegateObject) } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 8c9416c0..eb18f1fd 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -103,7 +103,7 @@ import Foundation performBlockOperation { [weak self] (operation) in let strongSelf = self MVMCoreDispatchUtility.performBlock(onMainThread: { - MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded() + strongSelf?.superview?.superview?.layoutIfNeeded() let animation = { strongSelf?.topView.isHidden = false strongSelf?.bottomView.isHidden = true @@ -111,7 +111,7 @@ import Foundation } let completion: (Bool) -> Void = { (finished) in strongSelf?.topView.button.isUserInteractionEnabled = true - MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded() + strongSelf?.superview?.superview?.layoutIfNeeded() UIAccessibility.post(notification: .layoutChanged, argument: strongSelf?.getAccessibilityLayoutChangedArgument()) operation.markAsFinished() } @@ -132,7 +132,7 @@ import Foundation performBlockOperation { [weak self] (operation) in let strongSelf = self MVMCoreDispatchUtility.performBlock(onMainThread: { - MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded() + strongSelf?.superview?.superview?.layoutIfNeeded() strongSelf?.topView.button.isUserInteractionEnabled = false let animation = { strongSelf?.topView.isHidden = !topViewShowing @@ -140,7 +140,7 @@ import Foundation strongSelf?.verticalStack.layoutIfNeeded() } let completion: (Bool) -> Void = { (finished) in - MVMCoreUITopAlertView.sharedGlobal()?.superview?.layoutIfNeeded() + strongSelf?.superview?.superview?.layoutIfNeeded() UIAccessibility.post(notification: .layoutChanged, argument: strongSelf?.getAccessibilityLayoutChangedArgument()) strongSelf?.autoCollapse() operation.markAsFinished() @@ -187,3 +187,9 @@ extension CollapsableNotification: AccessibilityProtocol { } } } + +extension CollapsableNotification: CollapsableNotificationProtocol { + public func collapse() { + collapse(animated: true) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift index b3223fc7..04c91450 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotificationTopView.swift @@ -60,7 +60,7 @@ import Foundation isAccessibilityElement = true accessibilityLabel = label.text accessibilityTraits = (button.isUserInteractionEnabled && button.actionModel != nil) ? .button : .none - MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: self) + NotificationView.amendAccesibilityLabel(for: self) } @objc func pressed(_ sender: Notification) { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/MVMCoreUITopAlertExpandableView+Extension.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/MVMCoreUITopAlertExpandableView+Extension.swift deleted file mode 100644 index e1af54e3..00000000 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/MVMCoreUITopAlertExpandableView+Extension.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// MVMCoreUITopAlertExpandableView+Extension.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 9/15/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - - -extension MVMCoreUITopAlertExpandableView: MoleculeViewProtocol { - - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - defaultSetup() - guard let model = model as? CollapsableNotificationModel else { return } - backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen - collapseTime = model.collapseTime - onlyShowTopMessageWhenCollapsed = !model.alwaysShowTopLabel - - var actionMap = model.button?.action.toJSON() - if let title = model.button?.title { - actionMap?.updateValue(title, forKey: KeyTitle) - } - buttonView?.setupCloseButton(model.closeButton != nil, animationDelegate: MVMCoreUITopAlertView.sharedGlobal()?.animationDelegate) - setTopMessage(model.topLabel.text, message: model.headline.text, subMessage: model.body?.text, contentColor: model.headline.textColor?.uiColor ?? .white, actionMap: actionMap, additionalData: nil) - expand(false) - - if let button = shortView?.button, - let topActionMap = model.topAction?.toJSON() { - MVMCoreUITopAlertBaseView.addAction(to: button, actionMap: topActionMap, additionalData: nil) - shortView?.label?.accessibilityTraits = .button - } - - if let accessibilityIdentifier = model.accessibilityIdentifier { - self.accessibilityIdentifier = accessibilityIdentifier - } - } -} - -extension MVMCoreUITopAlertExpandableView: StatusBarUI { - func getStatusBarUI() -> (color: UIColor, style: UIStatusBarStyle) { - if shortView?.label?.text?.count ?? 0 > 0 { - let color = backgroundColor ?? UIColor.mvmGreen - var greyScale: CGFloat = 0 - if shortView?.label?.textColor.getWhite(&greyScale, alpha: nil) ?? false { - return (color, greyScale > 0.5 ? .lightContent : .default) - } else { - return (color, .default) - } - } else { - return (.white, .default) - } - } -} diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/MVMCoreUITopAlertMainView+Extension.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/MVMCoreUITopAlertMainView+Extension.swift deleted file mode 100644 index c6109372..00000000 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/MVMCoreUITopAlertMainView+Extension.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// MVMCoreUITopAlertMainView+Extension.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 9/15/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - - -extension MVMCoreUITopAlertMainView: MoleculeViewProtocol { - - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - defaultSetup() - guard let model = model as? NotificationModel else { return } - - backgroundColor = model.backgroundColor?.uiColor ?? .mvmGreen - var actionMap = model.button?.action.toJSON() - - if let title = model.button?.title { - actionMap?.updateValue(title, forKey: KeyTitle) - } - - if let accessibilityIdentifier = model.accessibilityIdentifier { - self.accessibilityIdentifier = accessibilityIdentifier - } - - setupCloseButton(model.closeButton != nil, animationDelegate: MVMCoreUITopAlertView.sharedGlobal()?.animationDelegate) - setup(withMessage: model.headline.text, subMessage: model.body?.text, color: model.headline.textColor?.uiColor ?? .white, actionMap: actionMap, additionalData: nil) - } -} diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift index c17f43e0..f5176396 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/Notification.swift @@ -74,9 +74,17 @@ import Foundation } open func updateAccessibility() { - MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: headline) - MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: body) - MVMCoreUITopAlertBaseView.amendAccesibilityLabel(for: button) + NotificationView.amendAccesibilityLabel(for: headline) + NotificationView.amendAccesibilityLabel(for: body) + NotificationView.amendAccesibilityLabel(for: button) + } + + /// Formats the accessibilityLabel so voice over users know it's in the notification. + static public func amendAccesibilityLabel(for view: UIView) { + guard let amendment = MVMCoreUIUtility.hardcodedString(withKey: "top_alert_notification"), + let accessibilityLabel = view.accessibilityLabel, + !accessibilityLabel.hasPrefix(amendment) else { return } + view.accessibilityLabel = "\(amendment) - \(accessibilityLabel)" } } diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index c6ec9382..764c82ca 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -178,8 +178,10 @@ public extension MVMCoreUISplitViewController { navigationController.isDisplayed(viewController: viewController), let model = navigationController.getNavigationModel(from: viewController) else { return } setNavigationBar(for: viewController, navigationController: navigationController, navigationItemModel: model) - guard !(topAlertView?.overridingStatusBar() ?? false) else { return } - setStatusBarForCurrentViewController() + Task { + guard (await NotificationHandler.shared().getCurrentNotification()?.0 as? StatusBarUI) == nil else { return } + setStatusBarForCurrentViewController() + } } // MARK: - Status Bar diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h index 589c1cbb..c41e6860 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h @@ -12,7 +12,6 @@ #import #import -@class MVMCoreUITopAlertView; @class MFViewController; @class NavigationController; @protocol TabBarProtocol; @@ -42,7 +41,7 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) { @property (nullable, weak, nonatomic, readonly) NavigationController *navigationController; // Reference to the top alert view -@property (nullable, weak, nonatomic) MVMCoreUITopAlertView *topAlertView; +@property (nullable, weak, nonatomic) UIView *topAlertView; // Reference to the status bar view @property (nullable, weak, nonatomic) UIView *statusBarView; @@ -65,10 +64,10 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) { - (nullable instancetype)initWithLeftPanel:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel; // Returns a split controller with the mvm styling. Also sets the appropriate handlers. -+ (nullable instancetype)setup:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel; ++ (nullable instancetype)setup:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel topAlertView:(nullable UIView*)topAlertView; // Returns a split controller with the mvm styling. Also sets the appropriate handlers. Also sets up the default load screen -+ (nullable instancetype)setupAsMainController:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel; ++ (nullable instancetype)setupAsMainController:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel topAlertView:(nullable UIView*)topAlertView; #pragma mark - Panel Functions diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index 9dd229ea..9f7b2aef 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -20,8 +20,8 @@ #import "MVMCoreUISession.h" #import "MVMCoreUIConstants.h" #import "MVMCoreUICommonViewsUtility.h" -#import "MVMCoreUITopAlertView.h" #import +@import MVMCore.MVMCoreViewProtocol; @interface MVMCoreUISplitViewController () @@ -80,14 +80,15 @@ CGFloat const PanelAnimationDuration = 0.2; return [MVMCoreActionUtility initializerClassCheck:[MVMCoreUISession sharedGlobal].splitViewController classToVerify:self]; } -+ (nullable instancetype)setup:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel topAlertView:(nonnull UIView *)topAlertView { ++ (nullable instancetype)setup:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel topAlertView:(nullable UIView*)topAlertView { MVMCoreUISplitViewController *splitViewController = [[self alloc] initWithLeftPanel:leftPanel rightPanel:rightPanel]; + splitViewController.topAlertView = topAlertView; [MVMCoreUISession sharedGlobal].splitViewController = splitViewController; return splitViewController; } -+ (nullable instancetype)setupAsMainController:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel { - MVMCoreUISplitViewController *splitViewController = [self setup:leftPanel rightPanel:rightPanel]; ++ (nullable instancetype)setupAsMainController:(nullable UIViewController *)leftPanel rightPanel:(nullable UIViewController *)rightPanel topAlertView:(nullable UIView*)topAlertView { + MVMCoreUISplitViewController *splitViewController = [self setup:leftPanel rightPanel:rightPanel topAlertView:topAlertView]; [[MVMCoreUISession sharedGlobal] setupAsStandardLoadViewDelegate:splitViewController]; return splitViewController; } @@ -904,14 +905,9 @@ CGFloat const PanelAnimationDuration = 0.2; self.statusBarView = statusBarView; // Top Alert - MVMCoreUITopAlertView *topAlertView = nil; - if ([[CoreUIObject sharedInstance].globalTopAlertDelegate respondsToSelector:@selector(getTopAlertView)]) { - topAlertView = (MVMCoreUITopAlertView *)[[CoreUIObject sharedInstance].globalTopAlertDelegate getTopAlertView]; - if (topAlertView) { - self.topAlertView = topAlertView; - [self.view addSubview:topAlertView]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topAlertView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:@{@"topAlertView":topAlertView}]]; - } + if (self.topAlertView) { + [self.view addSubview:self.topAlertView]; + [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[topAlertView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:@{@"topAlertView":self.topAlertView}]]; } // The main view. @@ -947,7 +943,8 @@ CGFloat const PanelAnimationDuration = 0.2; bottomProgressHeight.active = YES; self.bottomProgressBarHeightConstraint = bottomProgressHeight; - if (topAlertView) { + if (self.topAlertView) { + UIView *topAlertView = self.topAlertView; [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[topAlertView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,topAlertView, mainView, progressView)]]; } else { [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,mainView, progressView)]]; @@ -1043,7 +1040,8 @@ CGFloat const PanelAnimationDuration = 0.2; /*self.leftPanel.needToUpdateUI = YES; [self.leftPanel.view setNeedsLayout]; [self.leftPanel.view layoutIfNeeded];*/ - [self.topAlertView updateView:size.width]; + if ([self.topAlertView conformsToProtocol:@protocol(MVMCoreViewProtocol)]) + [((UIView *)self.topAlertView) updateView:size.width]; }]; } diff --git a/MVMCoreUI/MVMCoreUI.h b/MVMCoreUI/MVMCoreUI.h index ceb4b574..fa2aaf0b 100644 --- a/MVMCoreUI/MVMCoreUI.h +++ b/MVMCoreUI/MVMCoreUI.h @@ -21,19 +21,6 @@ FOUNDATION_EXPORT const unsigned char MVMCoreUIVersionString[]; #import #import -#pragma mark - TopAlert -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - #pragma mark - Categories #import #import diff --git a/MVMCoreUI/Notification/MVMCoreGlobalTopAlertDelegateProtocol.h b/MVMCoreUI/Notification/MVMCoreGlobalTopAlertDelegateProtocol.h deleted file mode 100644 index ff35c5e9..00000000 --- a/MVMCoreUI/Notification/MVMCoreGlobalTopAlertDelegateProtocol.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// MVMCoreGlobalTopAlertDelegateProtocol.h -// MVMCore -// -// Created by Pfeil, Scott Robert on 1/2/18. -// Copyright © 2018 myverizon. All rights reserved. -// - -#import -#import -@class MVMCoreTopAlertObject; - -@protocol MVMCoreGlobalTopAlertDelegateProtocol - -- (NSOperationQueuePriority)priorityForTopAlertByObject:(nonnull MVMCoreTopAlertObject *)object; - -@optional - -- (nonnull UIView *)getTopAlertView; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreTopAlertDelegateProtocol.h b/MVMCoreUI/Notification/MVMCoreTopAlertDelegateProtocol.h deleted file mode 100644 index af094838..00000000 --- a/MVMCoreUI/Notification/MVMCoreTopAlertDelegateProtocol.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// MVMCoreTopAlertDelegateProtocol.h -// mobilefirst -// -// Created by Scott Pfeil on 6/4/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import - -@class MVMCoreTopAlertObject; - -@protocol MVMCoreTopAlertDelegateProtocol - -@optional - -- (void)topAlertViewShown:(nonnull id)topAlert topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject; -- (void)topAlertViewDismissed:(nonnull id)topAlert; - -// Called when the top alert is pressed. Determines if we should load the option the default way or not. -- (BOOL)shouldLoadTopAlertAction:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreTopAlertObject.h b/MVMCoreUI/Notification/MVMCoreTopAlertObject.h deleted file mode 100644 index c222747a..00000000 --- a/MVMCoreUI/Notification/MVMCoreTopAlertObject.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// MVMCoreTopAlertObject.h -// mobilefirst -// -// Created by Scott Pfeil on 5/24/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import -#import - -extern NSUInteger const TopAlertDismissTime; - -@interface MVMCoreTopAlertObject : NSObject - -@property (nonatomic) BOOL persistent; -@property (nullable, nonatomic) NSString *type; -@property (nonatomic) NSOperationQueuePriority queuePriority; - -// The text -@property (nullable, strong, nonatomic) NSString *title; -@property (nullable, strong, nonatomic) NSString *message; -@property (nullable, strong, nonatomic) NSString *topMessage; - -// For the button. -@property (nullable, strong, nonatomic) NSDictionary *buttonMap; -@property (nullable, strong, nonatomic) NSDictionary *additionalData; -@property (nonatomic) BOOL useCloseButton; - -// For non action map driven button. -@property (nullable, strong, nonatomic) NSString *buttonTitle; -@property (nullable, copy, nonatomic) void (^userActionHandler)(id _Nonnull sender); - -@property (nullable, weak, nonatomic) NSObject *delegate; - -// This is used to ensure legacy style stays intact with new changes -@property (nonatomic) BOOL useNewStyle; - -// The page type used for the top alert -@property (nullable, strong, nonatomic) NSString *pageType; - -// image name or url used imageviews -@property (nullable, strong, nonatomic) NSString *imageNameOrURL; -@property (nullable, strong, nonatomic) NSString *aboveTextImageString; - -// If 0, uses default 5 seconds. -@property (nonatomic) NSInteger topAlertDismissTime; - -// Server can set color. -@property (nullable, strong, nonatomic) UIColor *backgroundColor; -@property (nullable, strong, nonatomic) UIColor *textColor; - -// The full top alert json. Currently only used for molecular. -@property (nullable, strong, nonatomic) NSDictionary *json; - -- (nullable instancetype)initWithResponseInfo:(nullable NSDictionary *)responseInfo; - -- (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message; - -- (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - -- (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreTopAlertObject.m b/MVMCoreUI/Notification/MVMCoreTopAlertObject.m deleted file mode 100644 index 45f5ae35..00000000 --- a/MVMCoreUI/Notification/MVMCoreTopAlertObject.m +++ /dev/null @@ -1,93 +0,0 @@ -// -// MVMCoreTopAlertObject.m -// mobilefirst -// -// Created by Scott Pfeil on 5/24/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreTopAlertObject.h" -@import MVMCore.NSDictionary_MFConvenience; -@import MVMCore.MVMCoreGetterUtility; -@import MVMCore.MVMCoreJSONConstants; - -NSUInteger const TopAlertDismissTime = 5; - -@implementation MVMCoreTopAlertObject - -- (nullable instancetype)initWithResponseInfo:(nullable NSDictionary *)responseInfo { - if (self = [super init]) { - - self.type = [responseInfo string:KeyType]; - self.persistent = [[responseInfo stringForKey:KeyMessageStyle] isEqualToString:ValueMessageStyleTopPersistent]; - - self.title = [responseInfo string:KeyMessage]; - self.message = [responseInfo string:KeyUserMessage]; - self.buttonMap = [responseInfo dict:KeyButtonMap]; - self.topMessage = [responseInfo string:KeyTopMessage]; - self.imageNameOrURL = [responseInfo string:@"topAlertImageUrl"]; - self.aboveTextImageString = [responseInfo string:@"topAlertImageURLAboveText"]; - - NSString *color = [responseInfo string:@"topAlertColor"]; - if (color) { - self.backgroundColor = [MVMCoreGetterUtility getColorForHexString:color]; - } - color = [responseInfo string:@"messageColor"]; - if (color) { - self.textColor = [MVMCoreGetterUtility getColorForHexString:color]; - } - - // The default is yes if not sent by server (for legacy to work as is) - NSNumber *closeButton = [responseInfo optionalNumberForKey:KeyCloseButton]; - if (closeButton != nil) { - self.useCloseButton = [closeButton boolValue]; - } else { - self.useCloseButton = YES; - } - - self.useNewStyle = [responseInfo boolForKey:@"newTopAlertStyle"]; - - // Server driven dismiss time. - NSNumber *topAlertTime = [responseInfo optionalNumberForKey:@"topAlertTime"]; - if (topAlertTime != nil) { - self.topAlertDismissTime = [topAlertTime integerValue]; - } - } - return self; -} - -- (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message { - return [self initWithType:type message:nil subMessage:message persistent:NO actionMap:nil additionalData:nil]; -} - -- (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - - if (self = [super init]) { - - self.type = type; - self.persistent = persistent; - - self.title = message; - self.message = subMessage; - self.buttonMap = actionMap; - self.additionalData = additionalData; - } - return self; -} - -- (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage persistent:(BOOL)persistent buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - - if (self = [super init]) { - - self.type = type; - self.persistent = persistent; - - self.title = message; - self.message = subMessage; - self.buttonTitle = buttonTitle; - self.userActionHandler = userActionHandler; - } - return self; -} - -@end diff --git a/MVMCoreUI/Notification/MVMCoreTopAlertViewProtocol.h b/MVMCoreUI/Notification/MVMCoreTopAlertViewProtocol.h deleted file mode 100644 index d9b07d0e..00000000 --- a/MVMCoreUI/Notification/MVMCoreTopAlertViewProtocol.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// MVMCoreTopAlertViewProtocol.h -// MVMCore -// -// Created by Pfeil, Scott Robert on 1/2/18. -// Copyright © 2018 myverizon. All rights reserved. -// - -#import -@class MVMCoreTopAlertObject; - -@protocol MVMCoreTopAlertViewProtocol - -@optional - -/// Show based on the object -- (nonnull NSOperation *)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler; - -/// Removes the notification -- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler; - -/// Collapses the notification if it has a short top message. Otherwise removes notification. -- (void)collapseNotification; - -/// Updates the existing top alert with the new object -- (void)updateTopAlertWith:(nullable MVMCoreTopAlertObject *)topAlertObject; - -/// Returns if the top alert is currently utilizing the status bar. -- (BOOL)overridingStatusBar; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertBaseView.h b/MVMCoreUI/Notification/MVMCoreUITopAlertBaseView.h deleted file mode 100644 index 4fe50237..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertBaseView.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// MVMCoreUITopAlertBaseView.h -// mobilefirst -// -// Created by Scott Pfeil on 9/6/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import -#import -@import MVMCore.MVMCoreViewProtocol; - -@class Button; - -@interface MVMCoreUITopAlertBaseView : UIView - -// Adds a top alert action. -+ (void)addActionToButton:(nonnull Button *)button actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - -// Returns a top alert styled label. -+ (nonnull UILabel *)topAlertLabel; - -// Returns a string for the passed in messages. -+ (nullable NSAttributedString *)getStringForMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color; - -// Adds a close button. -- (nonnull Button *)addCloseButtonWithAnimationDelegate:(nullable id )animationDelegate; - -// Handles making various parts accessible. -- (void)handleAccessibility; - -/// Adds the top alert accessibility prefix to the view. -+ (void)amendAccesibilityLabelForView:(nonnull UIView *)view; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertBaseView.m b/MVMCoreUI/Notification/MVMCoreUITopAlertBaseView.m deleted file mode 100644 index 862e4b5b..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertBaseView.m +++ /dev/null @@ -1,93 +0,0 @@ -// -// MVMCoreUITopAlertBaseView.m -// mobilefirst -// -// Created by Scott Pfeil on 9/6/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreUITopAlertBaseView.h" -#import "MVMCoreUISplitViewController.h" -@import MVMCore.MVMCoreLoadObject; -@import MVMCore.MVMCoreRequestParameters; -#import "MVMCoreUITopAlertView.h" -@import MVMCore.MVMCoreJSONConstants; -@import MVMCore.NSDictionary_MFConvenience; -#import "UIColor+MFConvenience.h" -#import "MVMCoreUICommonViewsUtility.h" -#import "MFStyler.h" -#import "MVMCoreUISession.h" -#import -#import "MVMCoreTopAlertDelegateProtocol.h" - -@implementation MVMCoreUITopAlertBaseView - -+ (void)addActionToButton:(nonnull Button *)button actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - [button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { - // Check with the current screen if we should perform the action (not if it's the same page type) - BOOL performAction = YES; - UIViewController *topViewController = [MVMCoreUISession sharedGlobal].splitViewController.getCurrentDetailViewController; - if ([topViewController respondsToSelector:@selector(shouldLoadTopAlertAction:additionalData:)]) { - performAction = [((NSObject *)topViewController) shouldLoadTopAlertAction:actionMap additionalData:additionalData]; - } - - if (performAction) { - [[MVMCoreUIActionHandler sharedActionHandler] handleActionWithDictionary:actionMap additionalData:additionalData delegateObject:[MVMCoreUIDelegateObject createWithDelegateForAll:[MVMCoreUISession sharedGlobal].topAlertView]]; - } - }]; -} - -+ (UILabel *)topAlertLabel { - - UILabel *label = [MVMCoreUICommonViewsUtility label]; - [label setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; - label.textColor = [UIColor whiteColor]; - label.font = [MFStyler fontB1]; - label.lineBreakMode = NSLineBreakByTruncatingTail; - return label; -} - -+ (nullable NSAttributedString *)getStringForMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color { - - UIColor *textColor = color ?: [UIColor whiteColor]; - NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init]; - if (message.length > 0) { - [string appendAttributedString:[MFStyler styleGetAttributedString:message font:[MFStyler fontB1] color:textColor]]; - } - - if (subMessage.length > 0) { - - NSString *subMessageToAppend = nil; - if (string.length > 0) { - subMessageToAppend = [NSString stringWithFormat:@"\n%@",subMessage]; - } else { - subMessageToAppend = subMessage; - } - [string appendAttributedString:[MFStyler styleGetAttributedString:subMessageToAppend font:[MFStyler fontB2] color:textColor]]; - } - return string; -} - -- (nonnull Button *)addCloseButtonWithAnimationDelegate:(nullable id )animationDelegate { - Button *closeButton = [MVMCoreUICommonViewsUtility addCloseButtonTo:self action:^(Button * _Nonnull button) { - [[MVMCoreUIActionHandler sharedActionHandler] handleActionWithDictionary:@{KeyActionType: @"dismissNotification"} additionalData:nil delegateObject:nil]; - } centeredVertically:YES]; - [closeButton.heightAnchor constraintEqualToConstant:16.0].active = YES; - [closeButton.widthAnchor constraintEqualToConstant:16.0].active = YES; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:closeButton]; - return closeButton; -} - -- (void)updateView:(CGFloat)size {} - -- (void)handleAccessibility {} - -+ (void)amendAccesibilityLabelForView:(nonnull UIView *)view { - NSString *amendment = [MVMCoreUIUtility hardcodedStringWithKey:@"top_alert_notification"]; - NSString *accessibilityLabel = view.accessibilityLabel; - if (accessibilityLabel && ![accessibilityLabel hasPrefix:amendment]) { - view.accessibilityLabel = [NSString stringWithFormat:@"%@ - %@", amendment, accessibilityLabel]; - } -} - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertExpandableView.h b/MVMCoreUI/Notification/MVMCoreUITopAlertExpandableView.h deleted file mode 100644 index 7a5519b3..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertExpandableView.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// MVMCoreUITopAlertExpandableView.h -// mobilefirst -// -// Created by Scott Pfeil on 8/18/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import -#import -#import - -@class PrimaryButton; -@class MVMCoreUITopAlertShortView; -@class MVMCoreUITopAlertMainView; -@class MVMCoreTopAlertObject; - -@interface MVMCoreUITopAlertExpandableView : MVMCoreUITopAlertBaseView - -@property (nullable, weak, nonatomic) MVMCoreUITopAlertShortView *shortView; -@property (nullable, weak, nonatomic) MVMCoreUITopAlertMainView *buttonView; - -// Setting this will hide the short view when the notification is collapsed. -@property (nonatomic) BOOL onlyShowTopMessageWhenCollapsed; - -// A flag for if the top alert expandable view should collapse automatically after being expanded -@property (nonatomic) BOOL collapseAutomaticallyAfterExpanded; - -@property (nonatomic) NSInteger collapseTime; - -// Standard -- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - -// Used primarily for when button presses will expand or collapse. (Short view button will need to be set manually) -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - -// Used when button uses standard action map. -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout; - -// Convenience change functions -- (void)defaultSetup; -- (void)setTopMessage:(nullable NSString *)topMessage; -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - -// Setters for making buttons expand and collapse the cell. -- (void)setButtonPressToExpand; -- (void)setButtonPressToCollapse; -- (void)setShortViewPressToCollapse; -- (void)setShortViewPressToExpand; - -// Animates -- (void)expand:(BOOL)animated; -- (void)collapse; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/Notification/MVMCoreUITopAlertExpandableView.m deleted file mode 100644 index eab93d0c..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertExpandableView.m +++ /dev/null @@ -1,431 +0,0 @@ -// -// MVMCoreUITopAlertExpandableView.m -// mobilefirst -// -// Created by Scott Pfeil on 8/18/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreUITopAlertExpandableView.h" -#import "MVMCoreUITopAlertShortView.h" -#import "MVMCoreUITopAlertMainView.h" -@import MVMCore.MVMCoreDispatchUtility; -#import -@import MVMCore.MVMCoreBlockOperation; -@import MVMCore.MVMCoreNavigationHandler; -#import "MFStyler.h" -#import "NSLayoutConstraint+MFConvenience.h" -#import "MVMCoreUIUtility.h" -#import "MVMCoreUITopAlertView.h" -#import - -@interface MVMCoreUITopAlertExpandableView () - -@property (nonatomic) BOOL expanded; - -@property (nullable, weak, nonatomic) id animationDelegate; - -@property (nullable, weak, nonatomic) UIView *viewToLayout; - -@property (nullable, strong, nonatomic) NSLayoutConstraint *topLabelConstraintBottom; -@property (nullable, strong, nonatomic) NSLayoutConstraint *topConstraint; -@property (nullable, strong, nonatomic) NSLayoutConstraint *shortViewHeight; - -// Sets up the short view. -- (void)setupTopMessage:(nullable NSString *)topMessage; - -// Sets up the button view. -- (void)setupTopAlertWithButton:(MVMCoreUITopAlertMainView *)topAlertWithButton; - -// Sets up the whole view without setting button action. -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle; - -// Sets up the whole view while setting button action. -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - -@end - -@implementation MVMCoreUITopAlertExpandableView - -- (void)handleAccessibility { - - if (self.shortView.label.text.length > 0 && !self.expanded) { - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.shortView.label); - } else if (self.buttonView.label.text.length > 0) { - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.buttonView.label); - } else { - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); - } -} - -#pragma mark - Setup View - -- (void)updateView:(CGFloat)size { - [super updateView:size]; - [self.shortView updateView:size]; - [self.buttonView updateView:size]; -} - -- (nullable instancetype)init { - if (self = [super init]) { - self.translatesAutoresizingMaskIntoConstraints = NO; - self.clipsToBounds = YES; - self.expanded = NO; - } - return self; -} - -- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - if (self = [self init]) { - self.animationDelegate = animationDelegate; - self.viewToLayout = viewTolayout; - - if (topAlertObject.useNewStyle) { - - // New style, collapses automatically after x time if there is a top message. - self.collapseTime = topAlertObject.topAlertDismissTime; - if (topAlertObject.persistent && topAlertObject.topMessage) { - _collapseAutomaticallyAfterExpanded = YES; - } - - // Setup the views. - [self setupTopMessage:topAlertObject.topMessage]; - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithTopAlertObject:topAlertObject animationDelegate:animationDelegate]; - [self setupTopAlertWithButton:topAlertWithButton]; - - // Sets the color - self.shortView.label.textColor = topAlertObject.textColor ?: [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; - self.backgroundColor = topAlertObject.backgroundColor ?: [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; - - if (topAlertWithButton.label.text.length > 0) { - [self expand:NO]; - } - } else { - - // Old style, has no top alert and main view is limited. - self.backgroundColor = [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; - UIColor *contentColor = [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; - [self setupTopMessage:nil]; - self.shortView.label.textColor = contentColor; - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:self.backgroundColor contentColor:contentColor message:topAlertObject.message subMessage:nil closeButton:YES animationDelegate:animationDelegate]; - [self setupTopAlertWithButton:topAlertWithButton]; - [self expand:NO]; - } - } - return self; -} - -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - if (self = [self init]) { - self.animationDelegate = animationDelegate; - self.viewToLayout = viewTolayout; - [self setupViewWithTopMessage:topMessage message:message subMessage:nil contentColor:contentColor buttonTitle:buttonTitle]; - } - return self; -} - -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - if (self = [self init]) { - self.animationDelegate = animationDelegate; - self.viewToLayout = viewTolayout; - [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage contentColor:contentColor buttonTitle:buttonTitle]; - } - return self; -} - -- (nullable instancetype)initWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData animationDelegate:(nullable id )animationDelegate viewToLayout:(nonnull UIView *)viewTolayout { - if (self = [self init]) { - self.animationDelegate = animationDelegate; - self.viewToLayout = viewTolayout; - [self setupViewWithTopMessage:topMessage message:message subMessage:subMessage contentColor:contentColor actionMap:actionMap additionalData:additionalData]; - } - return self; -} - -- (void)defaultSetup { - if (!self.shortView) { - self.translatesAutoresizingMaskIntoConstraints = NO; - self.clipsToBounds = YES; - _collapseAutomaticallyAfterExpanded = YES; - self.viewToLayout = MVMCoreUITopAlertView.sharedGlobal.superview; - self.expanded = NO; - [self setupTopMessage:nil]; - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] init]; - [topAlertWithButton defaultSetup]; - [self setupTopAlertWithButton:topAlertWithButton]; - } -} - -- (void)setupTopMessage:(nullable NSString *)topMessage { - - MVMCoreUITopAlertShortView *shortView = [[MVMCoreUITopAlertShortView alloc] initWithColor:[UIColor clearColor] message:nil actionMap:nil additionalData:nil topAlertObject:nil]; - shortView.label.font = [MFStyler fontB2]; - [self addSubview:shortView]; - self.shortView = shortView; - - [NSLayoutConstraint constraintPinSubview:shortView pinTop:YES topConstant:0 pinBottom:NO bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; - self.topLabelConstraintBottom = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:shortView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0]; - self.topLabelConstraintBottom.active = YES; - - self.shortViewHeight = [NSLayoutConstraint constraintWithItem:shortView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0]; - [self setTopMessage:topMessage]; -} - -- (void)setupTopAlertWithButton:(MVMCoreUITopAlertMainView *)topAlertWithButton { - topAlertWithButton.label.alpha = 0; - topAlertWithButton.button.alpha = 0; - topAlertWithButton.backgroundColor = [UIColor clearColor]; - [self insertSubview:topAlertWithButton belowSubview:self.shortView]; - self.buttonView = topAlertWithButton; - - self.topConstraint = [NSLayoutConstraint constraintWithItem:topAlertWithButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.shortView attribute:NSLayoutAttributeBottom multiplier:1 constant:0]; - [NSLayoutConstraint constraintPinSubview:topAlertWithButton pinTop:NO topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; -} - -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle { - - [self setupTopMessage:topMessage]; - self.shortView.label.textColor = contentColor; - - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage buttonTitle:buttonTitle userActionHandler:nil]; - [self setupTopAlertWithButton:topAlertWithButton]; -} - -- (void)setupViewWithTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - - [self setupTopMessage:topMessage]; - self.shortView.label.textColor = contentColor; - - MVMCoreUITopAlertMainView *topAlertWithButton = [[MVMCoreUITopAlertMainView alloc] initWithColor:[UIColor clearColor] contentColor:contentColor message:message subMessage:subMessage actionMap:actionMap additionalData:additionalData]; - [self setupTopAlertWithButton:topAlertWithButton]; -} - -#pragma mark - Setters - -- (void)setTopMessage:(nullable NSString *)topMessage { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - self.shortView.label.text = topMessage; - self.shortView.label.accessibilityLabel = topMessage; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.shortView.label]; - - if (topMessage && (!self.onlyShowTopMessageWhenCollapsed || !self.expanded)) { - self.shortViewHeight.active = NO; - } else if (!topMessage || (self.onlyShowTopMessageWhenCollapsed && self.expanded)) { - self.shortViewHeight.active = YES; - } - }]; -} - -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [self setTopMessage:topMessage]; - [self.buttonView setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; - }]; -} - -- (void)setTopMessage:(nullable NSString *)topMessage message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage contentColor:(nonnull UIColor *)contentColor buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [self setTopMessage:topMessage]; - [self.buttonView setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:buttonTitle userActionHandler:userActionHandler]; - }]; -} - -- (void)setButtonPressToExpand { - __weak typeof(self) weakSelf = self; - [self.buttonView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { - if (weakSelf) { - [weakSelf expand:YES]; - } - }]; -} - -- (void)setButtonPressToCollapse { - __weak typeof(self) weakSelf = self; - [self.buttonView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { - if (weakSelf) { - [weakSelf collapse]; - } - }]; -} - -- (void)setShortViewPressToExpand { - __weak typeof(self) weakSelf = self; - self.shortView.label.accessibilityTraits = UIAccessibilityTraitButton; - [self.shortView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { - if (weakSelf) { - [weakSelf expand:YES]; - } - }]; -} - -- (void)setShortViewPressToCollapse { - __weak typeof(self) weakSelf = self; - self.shortView.label.accessibilityTraits = UIAccessibilityTraitButton; - [self.shortView.button addActionBlockWithEvent:UIControlEventTouchUpInside :^(Button * _Nonnull button) { - if (weakSelf) { - [weakSelf collapse]; - } - }]; -} - -- (void)setOnlyShowTopMessageWhenCollapsed:(BOOL)onlyShowTopMessageWhenCollapsed { - _onlyShowTopMessageWhenCollapsed = onlyShowTopMessageWhenCollapsed; - if (onlyShowTopMessageWhenCollapsed && self.expanded) { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - self.shortView.label.alpha = 0; - self.shortViewHeight.active = YES; - }]; - } else if (!onlyShowTopMessageWhenCollapsed && self.expanded) { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - self.shortView.label.alpha = 1; - self.shortViewHeight.active = NO; - }]; - } -} - -- (void)setCollapseAutomaticallyAfterExpanded:(BOOL)collapseAutomaticallyAfterExpanded { - _collapseAutomaticallyAfterExpanded = collapseAutomaticallyAfterExpanded; - if (collapseAutomaticallyAfterExpanded) { - [self autoCollapse]; - } -} - -#pragma mark - Expand/Collapse - -- (void)expand:(BOOL)animated { - if (!self.expanded) { - __weak typeof(self) weakSelf = self; - MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [weakSelf performExpansion:animated onCompletion:^{ - [operation markAsFinished]; - }]; - }]; - }]; - [[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation]; - } -} - -- (void)performExpansion:(BOOL)animated onCompletion:(void(^)(void))completionHandler { - // Must notify animation delegate before animating. - if (animated && self.animationDelegate) { - [self.animationDelegate topAlertViewBeginAnimation]; - } - - [self.viewToLayout layoutIfNeeded]; - self.topLabelConstraintBottom.active = NO; - self.topConstraint.active = YES; - self.expanded = YES; - - void(^animation)(void) = ^(void) { - self.buttonView.button.alpha = 1; - self.buttonView.label.alpha = 1; - if (self.onlyShowTopMessageWhenCollapsed) { - self.shortViewHeight.active = YES; - } - [self.viewToLayout layoutIfNeeded]; - }; - - //accessibility - added to make only top alert label and close button accessible. Posted notification when top alert is displayed - self.accessibilityElements = @[self.buttonView]; - self.shortView.isAccessibilityElement = NO; - - void(^completion)(void) = ^(void) { - UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, self.buttonView.label); - completionHandler(); - }; - if (animated) { - [UIView animateWithDuration:.5 animations:animation completion:^(BOOL finished) { - [self.viewToLayout layoutIfNeeded]; - - // Must notify animation delegate when animating finished. - [MVMCoreDispatchUtility performBlockInBackground:^{ - if (self.animationDelegate) { - [self.animationDelegate topAlertViewFinishAnimation]; - } - }]; - completion(); - }]; - } else { - animation(); - completion(); - } - - // Collapse after 5 seconds (if the view still exists) - [self autoCollapse]; -} - -- (void)autoCollapse { - if (self.collapseAutomaticallyAfterExpanded) { - __weak typeof(self) weakSelf = self; - NSInteger dismissTime; - if (self.collapseTime > 0) { - dismissTime = self.collapseTime; - } else { - dismissTime = TopAlertDismissTime; - } - dispatch_time_t dispatchTime = dispatch_time(DISPATCH_TIME_NOW, dismissTime * NSEC_PER_SEC); - dispatch_after(dispatchTime, dispatch_get_main_queue(), ^(void){ - typeof(self) strongSelf = weakSelf; - if (strongSelf && strongSelf.expanded && strongSelf.collapseAutomaticallyAfterExpanded) { - // If accessibility focused, delay collapse. - if ([MVMCoreUIUtility viewContainsAccessiblityFocus:strongSelf]) { - [[NSNotificationCenter defaultCenter] addObserver:strongSelf selector:@selector(accessibilityFocusChanged:) name:UIAccessibilityElementFocusedNotification object:nil]; - } else { - [strongSelf collapse]; - } - } - }); - } -} - -- (void)collapse { - if (self.expanded) { - __weak typeof(self) weakSelf = self; - MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [weakSelf performCollapseAnimationThen:^{ - [operation markAsFinished]; - }]; - }]; - }]; - [[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation]; - } -} - -- (void)performCollapseAnimationThen:(void(^)(void))completionHandler { - // Must notify animation delegate before animating. - if (self.animationDelegate) { - [self.animationDelegate topAlertViewBeginAnimation]; - } - [self.viewToLayout layoutIfNeeded]; - self.topConstraint.active = NO; - self.topLabelConstraintBottom.active = YES; - self.expanded = NO; - [UIView animateWithDuration:.5 animations:^{ - [self.viewToLayout layoutIfNeeded]; - self.buttonView.button.alpha = 0; - self.buttonView.label.alpha = 0; - self.shortViewHeight.active = NO; - } completion:^(BOOL finished) { - [self.viewToLayout layoutIfNeeded]; - self.accessibilityElements = @[self.shortView.label]; - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); - // Must notify animation delegate when animating finished. - [MVMCoreDispatchUtility performBlockInBackground:^{ - if (self.animationDelegate) { - [self.animationDelegate topAlertViewFinishAnimation]; - } - }]; - completionHandler(); - }]; -} - -- (void)accessibilityFocusChanged:(NSNotification *)notification { - if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil]; - [self collapse]; - } -} - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertMainView.h b/MVMCoreUI/Notification/MVMCoreUITopAlertMainView.h deleted file mode 100644 index 618730bc..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertMainView.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// MVMCoreUITopAlertMainView.h -// mobilefirst -// -// Created by Scott Pfeil on 8/17/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import -#import -#import - -@class PillButton; -@class MVMCoreTopAlertObject; - -@interface MVMCoreUITopAlertMainView : MVMCoreUITopAlertBaseView - -@property (nullable, nonatomic, weak) UILabel *label; -@property (nullable, nonatomic, weak) PillButton *button; - -@property (nullable, nonatomic, strong) NSLayoutConstraint *height; - -// Standard -- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate; -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; - -// inits with images -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; - -// Sets up without image -- (void)defaultSetup; - -// Setters for label and button. -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - -// Setters for button. -- (void)setupButtonWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; -- (void)setupButtonWithButtonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - -// Setters for close button. -- (void)setupCloseButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; - -#pragma mark - legacy inits - -// Legacy init: inits with a label and button, no close button or icon. -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData; - -// Legacy init: inits with a label and possible icon and close button. No main button. -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate; - -// Legacy init: inits with a label and button, no close button or icon. If passing in a block to use for the button, the top alert delegate button functions will not be called. -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler; - - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertMainView.m b/MVMCoreUI/Notification/MVMCoreUITopAlertMainView.m deleted file mode 100644 index 1e660906..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertMainView.m +++ /dev/null @@ -1,343 +0,0 @@ -// -// MVMCoreUITopAlertMainView.m -// mobilefirst -// -// Created by Scott Pfeil on 8/17/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreUITopAlertMainView.h" -#import "MFStyler.h" -#import "NSLayoutConstraint+MFConvenience.h" -@import MVMCore.NSDictionary_MFConvenience; -@import MVMCore.MVMCoreDispatchUtility; -#import -#import "UIColor+MFConvenience.h" -#import -@import MVMCore.MVMCoreJSONConstants; -#import "MVMCoreUICommonViewsUtility.h" -#import "MVMCoreUITopAlertView.h" -#import - -@interface MVMCoreUITopAlertMainView () - -@property (nullable, strong, nonatomic) NSLayoutConstraint *labelRightConstraint; - -@property (nullable, weak, nonatomic) UIView *centerView; -@property (nullable, weak, nonatomic) LoadImageView *iconView; -@property (nullable, weak, nonatomic) LoadImageView *topIconView; -@property (nullable, weak, nonatomic) Button *closeButton; -@property (nullable, strong, nonatomic) NSString *message; -@property (nullable, strong, nonatomic) NSString *subMessage; -@property (nullable, strong, nonatomic) UIColor *contentColor; - -@end - -@implementation MVMCoreUITopAlertMainView - -- (void)handleAccessibility { - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.label); -} - -#pragma mark - Setup View - -- (void)updateView:(CGFloat)size { - [super updateView:size]; - self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:self.message subMessage:self.subMessage color:self.contentColor]; - self.label.accessibilityLabel = self.label.text; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.label]; - [self.button updateView:size]; -} - -- (nullable instancetype)init { - if (self = [super init]) { - self.translatesAutoresizingMaskIntoConstraints = NO; - self.clipsToBounds = YES; - self.height = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:96]; - self.height.active = YES; - } - return self; -} - -- (nullable instancetype)initWithTopAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nullable id )animationDelegate { - if (self = [self init]) { - UIColor *contentColor = topAlertObject.textColor ?: [[MVMCoreUITopAlertView sharedGlobal] getContentColorForType:topAlertObject.type]; - self.backgroundColor = topAlertObject.backgroundColor ?: [[MVMCoreUITopAlertView sharedGlobal] getBackgroundColorForType:topAlertObject.type]; - [self setupViewWithLabelAndImage:topAlertObject.imageNameOrURL topImage:topAlertObject.aboveTextImageString]; - [self setupCloseButton:topAlertObject.useCloseButton animationDelegate:animationDelegate]; - [self setupWithMessage:topAlertObject.title subMessage:topAlertObject.message color:contentColor actionMap:topAlertObject.buttonMap additionalData:topAlertObject.additionalData]; - } - return self; -} - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { - - // Handles all scenarios. - if (self = [self init]) { - self.backgroundColor = color; - [self setupViewWithLabelAndImage:nil topImage:nil]; - [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; - } - return self; -} - -#pragma mark - inits with images - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { - - // Handles all scenarios. - if (self = [self init]) { - self.backgroundColor = color; - [self setupViewWithLabelAndImage:imageURL topImage:nil]; - [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; - } - return self; -} - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nullable UIColor *)contentColor imageURL:(nullable NSString *)imageURL message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { - - // No main button. - if (self = [self init]) { - self.backgroundColor = color; - [self setupViewWithLabelAndImage:imageURL topImage:nil]; - [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:nil userActionHandler:NULL]; - } - return self; -} - -#pragma mark - setup - -- (void)defaultSetup { - if (!self.label) { - self.translatesAutoresizingMaskIntoConstraints = NO; - self.clipsToBounds = YES; - self.height = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:96]; - self.height.active = YES; - [self setupViewWithLabelAndImage:nil topImage:nil]; - } -} - -- (void)setupViewWithLabelAndImage:(NSString *)imageURL topImage:(NSString *)topImageString { - - UIView *centerView = [MVMCoreUICommonViewsUtility commonView]; - [self addSubview:centerView]; - self.centerView = centerView; - [centerView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor].active = YES; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=0-[centerView]->=0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(centerView)]]; - - // Add the label. - UILabel *label = self.label; - if (label) { - [label removeFromSuperview]; - } else { - label = [MVMCoreUITopAlertBaseView topAlertLabel]; - self.label = label; - } - [centerView addSubview:label]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[label]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(label)]]; - [label setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; - - // Add Top Image - if (self.topIconView) { - [self.topIconView removeFromSuperview]; - } - if (topImageString) { - LoadImageView *imageView = [[LoadImageView alloc] initWithPinnedEdges:UIRectEdgeLeft | UIRectEdgeTop | UIRectEdgeBottom]; - imageView.imageView.contentMode = UIViewContentModeScaleAspectFit; - imageView.addSizeConstraintsForAspectRatio = YES; - imageView.translatesAutoresizingMaskIntoConstraints = NO; - [centerView addSubview:imageView]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-out-[imageView]-between-[label]-out-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"out":@(PaddingTwo),@"between":@(PaddingOne)} views:NSDictionaryOfVariableBindings(imageView,label)]]; - [imageView.leftAnchor constraintEqualToAnchor:label.leftAnchor].active = YES; - [imageView.rightAnchor constraintEqualToAnchor:label.rightAnchor].active = YES; - [imageView loadImageWithName:topImageString height:@(12)]; - } else { - [NSLayoutConstraint constraintPinSubview:label pinTop:YES topConstant:PaddingTwo pinBottom:YES bottomConstant:PaddingTwo pinLeft:NO leftConstant:0 pinRight:NO rightConstant:0]; - } - - // Add main image. - if (self.iconView) { - [self.iconView removeFromSuperview]; - } - - CGFloat horizontalPadding = [MFStyler defaultHorizontalPaddingForApplicationWidth]; - if (imageURL) { - LoadImageView *imageView = [[LoadImageView alloc] init]; - imageView.translatesAutoresizingMaskIntoConstraints = NO; - [imageView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; - [self addSubview:imageView]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=space-[imageView]->=space-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(PaddingFive)} views:NSDictionaryOfVariableBindings(imageView)]]; - [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-space-[imageView]-space-[centerView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:@{@"space":@(horizontalPadding)} views:NSDictionaryOfVariableBindings(imageView,centerView)]]; - [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES; - self.iconView = imageView; - [imageView loadImageWithName:imageURL width:@(32)]; - } else { - [NSLayoutConstraint constraintWithItem:centerView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:horizontalPadding].active = YES; - } -} - -- (void)setupCloseButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { - - if (closeButton && !self.closeButton) { - self.closeButton = [self addCloseButtonWithAnimationDelegate:animationDelegate]; - [self.closeButton setTintColor:self.contentColor ?: [UIColor whiteColor]]; - } else if (!closeButton && self.closeButton) { - [self.closeButton removeFromSuperview]; - self.closeButton = nil; - } -} - -- (void)setupWithButton:(BOOL)showButton { - - // Setup the button. - CGFloat horizontalPadding = [MFStyler defaultHorizontalPaddingForApplicationWidth]; - if (showButton) { - - if (!self.button) { - - // remove label right constraint - self.labelRightConstraint.active = NO; - - // Sets up to use a button action. Always uses the top view controller - PillButton *button = [[PillButton alloc] initAsPrimaryButton:false makeTiny:true]; - [button setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; - [button setContentHuggingPriority:800 forAxis:UILayoutConstraintAxisHorizontal]; - - button.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:button]; - [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0].active = YES; - [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:PaddingThree].active = YES; - [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:button attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : horizontalPadding)].active = YES; - self.button = button; - } - } else { - - // remove button. - if (self.button) { - [self.button removeFromSuperview]; - self.button = nil; - } - - if (!self.labelRightConstraint) { - self.labelRightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.centerView attribute:NSLayoutAttributeRight multiplier:1 constant:(self.closeButton ? PaddingTen : horizontalPadding)]; - } - self.labelRightConstraint.active = YES; - } -} - - -#pragma mark - Setters - -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - self.message = message; - self.subMessage = subMessage; - self.contentColor = color; - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - - // Sets the string - self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color]; - self.label.accessibilityLabel = self.label.text; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.label]; - - // Sets the button - [self setupButtonWithActionMap:actionMap additionalData:additionalData]; - if (color) { - self.button.layer.borderColor = color.CGColor; - [self.button setTitleColor:color forState:UIControlStateNormal]; - [self.closeButton setTintColor:color]; - } - }]; -} - -- (void)setupWithMessage:(nullable NSString *)message subMessage:(nullable NSString *)subMessage color:(nullable UIColor *)color buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - self.message = message; - self.subMessage = subMessage; - self.contentColor = color; - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - - // Sets the string - self.label.attributedText = [MVMCoreUITopAlertBaseView getStringForMessage:message subMessage:subMessage color:color]; - self.label.accessibilityLabel = self.label.text; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.label]; - - // Sets the color - if (color) { - self.button.layer.borderColor = color.CGColor; - [self.button setTitleColor:color forState:UIControlStateNormal]; - [self.closeButton setTintColor:color]; - } - - // Sets the button - [self setupButtonWithButtonTitle:buttonTitle userActionHandler:userActionHandler]; - }]; -} - -- (void)setupButtonWithActionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - BOOL showButton = actionMap != nil; - [self setupWithButton:showButton]; - if (showButton) { - [self.button setTitle:[actionMap stringForKey:KeyTitle] forState:UIControlStateNormal]; - self.button.accessibilityLabel = [self.button titleForState:UIControlStateNormal]; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.button]; - - [MVMCoreUITopAlertBaseView addActionToButton:self.button actionMap:actionMap additionalData:additionalData]; - } - }]; -} - -- (void)setupButtonWithButtonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - BOOL showButton = buttonTitle.length > 0; - [self setupWithButton:showButton]; - [self.button setTitle:buttonTitle forState:UIControlStateNormal]; - self.button.accessibilityLabel = [self.button titleForState:UIControlStateNormal]; - [MVMCoreUITopAlertBaseView amendAccesibilityLabelForView:self.button]; - if (showButton && userActionHandler) { - [self.button addActionBlockWithEvent:UIControlEventTouchUpInside :userActionHandler]; - } - }]; -} - -#pragma mark - legacy inits - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData { - - // No icon or close button. - if (self = [self init]) { - self.backgroundColor = color; - [self setupViewWithLabelAndImage:nil topImage:nil]; - [self setupWithMessage:message subMessage:subMessage color:contentColor actionMap:actionMap additionalData:additionalData]; - } - return self; -} - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage closeButton:(BOOL)closeButton animationDelegate:(nullable id )animationDelegate { - - // No main button. - if (self = [self init]) { - self.backgroundColor = color; - [self setupViewWithLabelAndImage:nil topImage:nil]; - [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:nil userActionHandler:NULL]; - [self setupCloseButton:closeButton animationDelegate:animationDelegate]; - } - return self; -} - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color contentColor:(nonnull UIColor *)contentColor message:(nullable NSString *)message subMessage:(nullable NSString *)subMessage buttonTitle:(nullable NSString *)buttonTitle userActionHandler:(nullable void (^)(id _Nonnull sender))userActionHandler { - - // No icon or close button. Custom button action. - if (self = [self init]) { - self.backgroundColor = color; - [self setupViewWithLabelAndImage:nil topImage:nil]; - [self setupWithMessage:message subMessage:subMessage color:contentColor buttonTitle:buttonTitle userActionHandler:userActionHandler]; - } - return self; -} - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertShortView.h b/MVMCoreUI/Notification/MVMCoreUITopAlertShortView.h deleted file mode 100644 index 6241a71e..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertShortView.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// MVMCoreUITopAlertShortView.h -// mobilefirst -// -// Created by Scott Pfeil on 7/20/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import -#import - -@class MVMCoreTopAlertObject; -@class Button; - -@interface MVMCoreUITopAlertShortView : MVMCoreUITopAlertBaseView - -@property (nullable, weak, nonatomic) UILabel *label; -@property (nullable, weak, nonatomic) Button *button; - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData topAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertShortView.m b/MVMCoreUI/Notification/MVMCoreUITopAlertShortView.m deleted file mode 100644 index 3890cdd3..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertShortView.m +++ /dev/null @@ -1,67 +0,0 @@ -// -// MVMCoreUITopAlertShortView.m -// mobilefirst -// -// Created by Scott Pfeil on 7/20/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreUITopAlertShortView.h" -#import "MFStyler.h" -#import "NSLayoutConstraint+MFConvenience.h" -#import "MVMCoreUIConstants.h" -#import - -@interface MVMCoreUITopAlertShortView () - -@end - -@implementation MVMCoreUITopAlertShortView - -- (void)updateView:(CGFloat)size { - [super updateView:size]; - self.label.font = [MFStyler fontB1]; -} - -- (nullable instancetype)initWithColor:(nonnull UIColor *)color message:(nullable NSString *)message actionMap:(nullable NSDictionary *)actionMap additionalData:(nullable NSDictionary *)additionalData topAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject { - - if (self = [super init]) { - - self.backgroundColor = color; - self.translatesAutoresizingMaskIntoConstraints = NO; - - UILabel *label = [MVMCoreUITopAlertBaseView topAlertLabel]; - label.numberOfLines = 1; - label.textAlignment = NSTextAlignmentCenter; - label.text = message; - [self addSubview:label]; - [label setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisVertical]; - [NSLayoutConstraint constraintPinSubview:label pinTop:YES topConstant:0 pinBottom:YES bottomConstant:4 pinLeft:YES leftConstant:PaddingThree pinRight:YES rightConstant:PaddingThree]; - self.label = label; - - // Sets up to use a button action. - Button *button = [Button buttonWithType:UIButtonTypeCustom]; - button.backgroundColor = [UIColor clearColor]; - button.translatesAutoresizingMaskIntoConstraints = NO; - [button setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical]; - [button setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; - [self addSubview:button]; - [NSLayoutConstraint constraintPinSubview:button pinTop:YES topConstant:0 pinBottom:YES bottomConstant:-5 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0]; - if (actionMap) { - [MVMCoreUITopAlertBaseView addActionToButton:button actionMap:actionMap additionalData:additionalData]; - } - self.button = button; - - // Listen for status bar touches. - [[NSNotificationCenter defaultCenter] addObserverForName:NotificationStatusBarTouched object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) { - [button sendActionsForControlEvents:UIControlEventAllEvents]; - }]; - } - return self; -} - -- (void)handleAccessibility { - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.label); -} - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertView+Extension.swift b/MVMCoreUI/Notification/MVMCoreUITopAlertView+Extension.swift index 4fbe51d6..29fd7ccd 100644 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertView+Extension.swift +++ b/MVMCoreUI/Notification/MVMCoreUITopAlertView+Extension.swift @@ -14,68 +14,118 @@ protocol StatusBarUI { func getStatusBarUI() -> (color: UIColor, style: UIStatusBarStyle) } -public extension MVMCoreUITopAlertView { +public class NotificationContainerView: UIView { - /// Shows the top alert with the json. - @objc func showTopAlert(with json: [AnyHashable: Any]) { - TopNotificationHandler.shared().showTopNotification(with: json) + public var currentModel: TopNotificationModel? + public var currentNotificationView: UIView? + + lazy private var height = heightAnchor.constraint(equalToConstant: 0) + + public init() { + super.init(frame: .zero) + setupView() } - /// Updates the current top alert molecule with the new object - @objc func updateMolecule(with topAlertObject: MVMCoreTopAlertObject) { - guard topAlertObject.type == self.topAlertObject?.type else { return } + required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } + + func updateAccessibilityForTopAlert(_ view: UIView) { + // Update accessibility with top alert + var accessibilityArgument: Any? = view + if let view = view as? AccessibilityProtocol { + accessibilityArgument = view.getAccessibilityLayoutChangedArgument() + } + UIAccessibility.post(notification: .layoutChanged, argument: accessibilityArgument) + } + + // accessibilityFocusChanged; No longer seeing this function, needs a testing. +} + +extension NotificationContainerView: NotificationTransitionDelegateProtocol { + @MainActor + public func show(notification: UIView) async { + currentNotificationView?.removeFromSuperview() + addSubview(notification) + NSLayoutConstraint.constraintPinSubview(toSuperview: notification) + currentNotificationView = notification + + if let conformer = notification as? MVMCoreViewProtocol { + conformer.updateView(bounds.width) + } + + if let conformer = notification as? StatusBarUI { + let statusBarUI = conformer.getStatusBarUI() + MVMCoreUISplitViewController.main()?.setStatusBarBackgroundColor(statusBarUI.color, style: statusBarUI.style) + } + + superview?.layoutIfNeeded() + await withCheckedContinuation { continuation in + UIView.animate(withDuration: 0.5) { + self.height.isActive = false + self.superview?.layoutIfNeeded() + } completion: { finished in + self.superview?.layoutIfNeeded() + self.updateAccessibilityForTopAlert(notification) + continuation.resume() + } + } + } + + @MainActor + public func hide(notification: UIView) async { + // accessibility - below line added to notify VI user through voiceover user when the top alert is closed + UIAccessibility.post(notification: .screenChanged, argument: MVMCoreUIUtility.hardcodedString(withKey: "AccTopAlertClosed")) + await withCheckedContinuation { continuation in + UIView.animate(withDuration: 0.5) { + self.height.isActive = true + self.superview?.layoutIfNeeded() + } completion: { finished in + UIAccessibility.post(notification: .layoutChanged, argument: nil) + if let _ = self.currentNotificationView as? StatusBarUI { + MVMCoreUISplitViewController.main()?.setStatusBarForCurrentViewController() + } + self.currentNotificationView?.removeFromSuperview() + self.currentNotificationView = nil + continuation.resume() + } + } + } + + @MainActor + public func update(with model: TopNotificationModel) { + guard let currentModel = currentModel, + currentModel.type == model.type else { return } let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self) - guard let newJson = topAlertObject.json, - let newModel = TopNotificationHandler.shared().decodeTopNotification(with: newJson, delegateObject: delegateObject), - let newModelName = ModelRegistry.getMoleculeClass(newModel.molecule)?.nameForReuse(with: newModel.molecule, delegateObject), - let currentJson = self.topAlertObject?.json, - let currentModel = TopNotificationHandler.shared().decodeTopNotification(with: currentJson, delegateObject: delegateObject), - let currentModelName = ModelRegistry.getMoleculeClass(currentModel.molecule)?.nameForReuse(with: currentModel.molecule, delegateObject), - newModelName == currentModelName, - let molecule = currentAlert as? MoleculeViewProtocol else { + guard let molecule = currentNotificationView as? MoleculeViewProtocol, + currentModel.molecule.moleculeName == model.molecule.moleculeName else { // Log that we couldn't update. - if let errorObject = MVMCoreErrorObject(title: nil, message: nil, messageToLog: nil, code: ErrorCode.parsingJSON.rawValue, domain: ErrorDomainNative, location: "TopNotification update \(String(describing: topAlertObject.type))") { + if let errorObject = MVMCoreErrorObject(title: nil, message: nil, messageToLog: nil, code: ErrorCode.parsingJSON.rawValue, domain: ErrorDomainNative, location: "TopNotification update \(String(describing: model.type))") { MVMCoreUILoggingHandler.addError(toLog: errorObject) } return } - MVMCoreDispatchUtility.performBlock(onMainThread: { - // Update molecule - molecule.reset() - molecule.set(with: newModel.molecule, delegateObject, nil) - (molecule as? MVMCoreViewProtocol)?.updateView(self.bounds.width) - - // Update status bar. - guard let statusBarDelegate = molecule as? StatusBarUI else { return } - let statusBarUI = statusBarDelegate.getStatusBarUI() - MVMCoreUISplitViewController.main()?.setStatusBarBackgroundColor(statusBarUI.color, style: statusBarUI.style) - }) - } - - /// Returns the top alert molecule to use and status bar color legacy style. - @objc func molecule(for topAlertObject: MVMCoreTopAlertObject, statusBarColor: AutoreleasingUnsafeMutablePointer?, statusBarStyle: UnsafeMutablePointer?) -> UIView? { - do { - let delegateObject = MVMCoreUIDelegateObject.create(withDelegateForAll: self) - guard let json = topAlertObject.json else { return nil } - let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject) - guard let molecule = ModelRegistry.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil) else { - throw ModelRegistry.Error.decoderOther(message: "Molecule not mapped") - } - if let castView = molecule as? StatusBarUI { - let (color, style) = castView.getStatusBarUI() - statusBarColor?.pointee = color - statusBarStyle?.pointee = style - } - // TODO: Temporary, waiting for actual restriction from design. - molecule.heightAnchor.constraint(lessThanOrEqualToConstant: 140).isActive = true - return molecule - } catch { - if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") { - MVMCoreUILoggingHandler.addError(toLog: errorObject) - } - return nil - } + + // Update molecule + molecule.reset() + molecule.set(with: model.molecule, delegateObject, nil) + (molecule as? MVMCoreViewProtocol)?.updateView(self.bounds.width) + + // Update status bar. + guard let statusBarDelegate = molecule as? StatusBarUI else { return } + let statusBarUI = statusBarDelegate.getStatusBarUI() + MVMCoreUISplitViewController.main()?.setStatusBarBackgroundColor(statusBarUI.color, style: statusBarUI.style) } } -extension MVMCoreUITopAlertView: ActionDelegateProtocol {} +extension NotificationContainerView: MVMCoreViewProtocol { + public func updateView(_ size: CGFloat) { + (currentNotificationView as? MVMCoreViewProtocol)?.updateView(size) + } + + public func setupView() { + clipsToBounds = false + height.isActive = true + } +} diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertView.h b/MVMCoreUI/Notification/MVMCoreUITopAlertView.h deleted file mode 100644 index fad65957..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertView.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// MVMCoreUITopAlertView.h -// myverizon -// -// Created by Chris Yang on 2/3/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import -@import MVMCore.MVMCoreLoadDelegateProtocol; -@import MVMCore.MVMCoreActionDelegateProtocol; -@import MVMCore.MVMCorePresentationDelegateProtocol; -@import MVMCore.MVMCoreViewProtocol; -#import -#import -#import - -@class MVMCoreTopAlertObject; - -@interface MVMCoreUITopAlertView : UIView - -// Delegate for the top alert view -@property (nonatomic, nullable, weak) id animationDelegate; - -// Current top alert object -@property (strong, nullable, nonatomic) MVMCoreTopAlertObject *topAlertObject; - -/// Current top alert view. -@property (weak, nullable, nonatomic, readonly) UIView *currentAlert; - -// Returns the top alert view -+ (nullable instancetype)sharedGlobal; - -// Returns a TopAlertView with the mvm styling. Also sets the property in the session. -+ (nullable instancetype)setupTopAlertView; - -// Can be subclassed for custom views. -- (nonnull UIView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle; - -/// Get the background color based on the type -- (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type; - -/// Get the content color based on the type -- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type; - -@end diff --git a/MVMCoreUI/Notification/MVMCoreUITopAlertView.m b/MVMCoreUI/Notification/MVMCoreUITopAlertView.m deleted file mode 100644 index 6ad48095..00000000 --- a/MVMCoreUI/Notification/MVMCoreUITopAlertView.m +++ /dev/null @@ -1,291 +0,0 @@ -// -// MVMCoreUITopAlertView.m -// myverizon -// -// Created by Chris Yang on 2/3/16. -// Copyright © 2016 Verizon Wireless. All rights reserved. -// - -#import "MVMCoreUITopAlertView.h" -#import "MVMCoreUICommonViewsUtility.h" -#import "UIColor+MFConvenience.h" -#import "MVMCoreUITopAlertShortView.h" -#import "MVMCoreUITopAlertMainView.h" -#import "MVMCoreUITopAlertExpandableView.h" -#import "MVMCoreUISplitViewController.h" -#import "NSLayoutConstraint+MFConvenience.h" -#import "MVMCoreUISession.h" -#import "MVMCoreUIUtility.h" -#import -#import -@import MVMCore.MVMCoreLoadHandler; -@import MVMCore.MVMCoreNavigationHandler; -@import MVMCore.MVMCoreBlockOperation; -@import MVMCore.NSDictionary_MFConvenience; -@import MVMCore.MVMCoreRequestParameters; -@import MVMCore.MVMCoreJSONConstants; -@import MVMCore.MVMCoreDispatchUtility; - -NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; - -@interface MVMCoreUITopAlertView () - -@property (weak, nullable, nonatomic, readwrite) UIView *currentAlert; -@property (strong, nonatomic) NSLayoutConstraint *height; - -@property (weak, nonatomic) MVMCoreUITopAlertExpandableView *topAlertClearspotView; -@property (strong, nonatomic) NSString *time; - -/// Used if we delayed the collapse due to accessibility. -@property (copy, nonatomic) void (^ hideCompletionHandler)(BOOL finished); - -@property (nonatomic) BOOL currentAlertOverridingStatusBar; - -@end - -@implementation MVMCoreUITopAlertView - -- (instancetype)init { - self = [super init]; - if (self) { - [self setupView]; - } - return self; -} - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - [self setupView]; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)coder { - self = [super initWithCoder:coder]; - if (self) { - [self setupView]; - } - return self; -} - -+ (nullable instancetype)sharedGlobal { - return [MVMCoreUISession sharedGlobal].topAlertView; -} - -+ (nullable instancetype)setupTopAlertView { - MVMCoreUITopAlertView *topAlertView = [[self alloc] init]; - topAlertView.translatesAutoresizingMaskIntoConstraints = NO; - [MVMCoreUISession sharedGlobal].topAlertView = topAlertView; - return topAlertView; -} - -- (void)setupView { - if (self.height) { return; } - self.clipsToBounds = YES; - self.height = [self.heightAnchor constraintEqualToConstant:0]; - self.height.active = YES; -} - -- (void)updateView:(CGFloat)size { - if ([self.currentAlert respondsToSelector:@selector(updateView:)]) { - [((UIView *)(self.currentAlert)) updateView:size]; - } -} - -- (nonnull UIView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle { - if (topAlertObject.json) { - return [self moleculeFor:topAlertObject statusBarColor:statusBarColor statusBarStyle:statusBarStyle]; - } else { - MVMCoreUITopAlertExpandableView *view = [[MVMCoreUITopAlertExpandableView alloc] initWithTopAlertObject:topAlertObject animationDelegate:animationDelegate viewToLayout:self.superview]; - if (statusBarColor && view.shortView.label.text) { - *statusBarColor = view.backgroundColor; - - if (statusBarStyle) { - CGFloat greyScale = 0; - if ([view.shortView.label.textColor getWhite:&greyScale alpha:nil]) { - *statusBarStyle = greyScale > 0.5 ? UIStatusBarStyleLightContent : UIStatusBarStyleDefault; - } - } - } - return view; - } -} - -- (nonnull UIColor *)getBackgroundColorForType:(nullable NSString *)type { - if ([type isEqualToString:ValueTypeError]) { - return [UIColor mvmOrange]; - } else { - return [UIColor mvmGreen]; - } -} - -- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type { - if ([type isEqualToString:ValueTypeError]) { - return [UIColor blackColor]; - } else { - return [UIColor whiteColor]; - } -} - -- (void)updateAccessibilityForTopAlert:(nullable UIView *)view { - // Update accessibility with top alert - if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) { - [((MVMCoreUITopAlertBaseView *)view) handleAccessibility]; - } else { - id accessibilityArgument = view; - if ([view conformsToProtocol:@protocol(AccessibilityProtocol)]) { - accessibilityArgument = [((id )view) getAccessibilityLayoutChangedArgument]; - } - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, accessibilityArgument); - } -} - -- (nonnull NSOperation *)showAlertView:(nullable UIView *)view topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject completionHandler:(void (^ __nullable)(BOOL finished))completionHandler { - - __weak typeof(self) weakSelf = self; - MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - if (weakSelf.currentAlert.superview) { - [weakSelf.currentAlert removeFromSuperview]; - } - [weakSelf addSubview:view]; - [NSLayoutConstraint constraintPinSubviewToSuperview:view]; - weakSelf.currentAlert = view; - - [weakSelf.animationDelegate topAlertViewBeginAnimation]; - [weakSelf.superview layoutIfNeeded]; - [UIView animateWithDuration:.5 animations:^{ - weakSelf.height.active = NO; - [weakSelf.superview layoutIfNeeded]; - } completion:^(BOOL finished) { - [weakSelf.superview layoutIfNeeded]; - [weakSelf.animationDelegate topAlertViewFinishAnimation]; - - [weakSelf updateAccessibilityForTopAlert:view]; - - [MVMCoreDispatchUtility performBlockInBackground:^{ - if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewShown:topAlertObject:)]) { - [weakSelf.topAlertObject.delegate topAlertViewShown:view topAlertObject:topAlertObject]; - } - [[MVMCoreUILoggingHandler sharedLoggingHandler] trackTopNotificationShown:view topAlertObject:topAlertObject additionalData:nil]; - [operation markAsFinished]; - completionHandler(finished); - }]; - }]; - }]; - }]; - [[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation]; - return operation; -} - - -/// If the voice over user leaves top alert focus, hide. -- (void)accessibilityFocusChanged:(NSNotification *)notification { - if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil]; - [self hideAlertView:YES completionHandler:self.hideCompletionHandler]; - self.hideCompletionHandler = nil; - } -} - -#pragma mark - MVMCoreTopAlertViewProtocol - -- (nonnull NSOperation *)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler { - - self.animationDelegate = animationDelegate; - __block NSOperation *operation = nil; - [MVMCoreDispatchUtility performSyncBlockOnMainThread:^{ - self.topAlertObject = topAlertObject; - self.topAlertClearspotView = nil; - - UIColor *statusBarColor = nil; - UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault; - UIView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle]; - if ([view conformsToProtocol:@protocol(MVMCoreViewProtocol)]) { - [((UIView *)view) updateView:CGRectGetWidth(self.bounds)]; - } - if (statusBarColor) { - self.currentAlertOverridingStatusBar = YES; - [[MVMCoreUISplitViewController mainSplitViewController] setStatusBarBackgroundColor:statusBarColor style:statusBarStyle]; - } - operation = [self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler]; - }]; - return operation; -} - -- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler { - // If accessible and focused, do not collapse until unfocused. - if (!forceful && [MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { - self.hideCompletionHandler = completionHandler; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessibilityFocusChanged:) name:UIAccessibilityElementFocusedNotification object:nil]; - return; - } - - __weak typeof(self) weakSelf = self; - MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) { - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [weakSelf.animationDelegate topAlertWillDismiss]; - [weakSelf.animationDelegate topAlertViewBeginAnimation]; - - // accessibility - below line added to notify VI user through voiceover user when the top alert is closed - UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, [MVMCoreUIUtility hardcodedStringWithKey:@"AccTopAlertClosed"]); - - [UIView animateWithDuration:.5 animations:^{ - weakSelf.height.active = YES; - [weakSelf.superview layoutIfNeeded]; - } completion:^(BOOL finished) { - [weakSelf.animationDelegate topAlertViewFinishAnimation]; - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); - - UIView *view = weakSelf.currentAlert; - if (view.superview) { - [view removeFromSuperview]; - } - - [MVMCoreDispatchUtility performBlockInBackground:^{ - if ([weakSelf.topAlertObject.delegate respondsToSelector:@selector(topAlertViewDismissed:)]) { - [weakSelf.topAlertObject.delegate topAlertViewDismissed:view]; - } - [operation markAsFinished]; - if (completionHandler) { - completionHandler(finished); - } - [weakSelf.animationDelegate topAlertDismissed]; - weakSelf.topAlertObject = nil; - if (weakSelf.currentAlertOverridingStatusBar) { - weakSelf.currentAlertOverridingStatusBar = NO; - [MVMCoreDispatchUtility performBlockOnMainThread:^{ - [[MVMCoreUISplitViewController mainSplitViewController] setStatusBarForCurrentViewController]; - }]; - } - }]; - }]; - }]; - }]; - [[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation]; -} - - -- (void)updateTopAlertWith:(MVMCoreTopAlertObject *)topAlertObject { - [self updateMoleculeWith:topAlertObject]; -} - -- (void)collapseNotification { - if (self.currentAlert) { - if ([self.currentAlert isKindOfClass:[MVMCoreUITopAlertExpandableView class]] && ((MVMCoreUITopAlertExpandableView *)self.currentAlert).shortView.label.text.length > 0) { - - // We have a short message, collapse to show short message. - [((MVMCoreUITopAlertExpandableView *)self.currentAlert) collapse]; - } else { - // Top alert is not collapsable, remove it instead. - [self hideAlertView:NO completionHandler:NULL]; - } - } -} - -- (BOOL)overridingStatusBar { - return self.currentAlertOverridingStatusBar; -} - -@end diff --git a/MVMCoreUI/Notification/NotificationHandler.swift b/MVMCoreUI/Notification/NotificationHandler.swift index fc6227aa..1040a6b2 100644 --- a/MVMCoreUI/Notification/NotificationHandler.swift +++ b/MVMCoreUI/Notification/NotificationHandler.swift @@ -8,6 +8,7 @@ import MVMCore import Dispatch +import Combine public protocol NotificationTransitionDelegateProtocol { @MainActor @@ -22,9 +23,9 @@ public protocol NotificationTransitionDelegateProtocol { public class NotificationOperation: MVMCoreOperation { - private let notification: UIView + public let notification: UIView - private var notificationModel: TopNotificationModel + public var notificationModel: TopNotificationModel /// The delegate that manages transitioning the notification. private let transitionDelegate: NotificationTransitionDelegateProtocol @@ -71,27 +72,27 @@ public class NotificationOperation: MVMCoreOperation { } } - private actor Properties { + public actor Properties { private var isDisplayed: Bool = false private var isAnimating: Bool = false - func set(displayed: Bool) { + fileprivate func set(displayed: Bool) { isDisplayed = displayed } - func getIsDisplayed() -> Bool { + public func getIsDisplayed() -> Bool { return isDisplayed } - func set(animating: Bool) { + fileprivate func set(animating: Bool) { isAnimating = animating } - func getIsAnimating() -> Bool { + public func getIsAnimating() -> Bool { return isAnimating } } - private var properties = Properties() + public var properties = Properties() // A flag for tracking if the operation needs to be re-added because it was cancelled for a higher priority notification. public var reAddAfterCancel = false @@ -106,7 +107,8 @@ public class NotificationOperation: MVMCoreOperation { public override func main() { guard !checkAndHandleForCancellation() else { return } - add { + add { [weak self] in + guard let self = self else { return } await self.showNotification() guard !self.isCancelled else { // Cancelled, dismiss immediately. @@ -124,7 +126,8 @@ public class NotificationOperation: MVMCoreOperation { Task { guard await properties.getIsDisplayed(), await !properties.getIsAnimating() else { return } - add { + add { [weak self] in + guard let self = self else { return } await self.hideNotification() guard !self.isCancelled, !self.notificationModel.persistent else { return } @@ -138,12 +141,8 @@ public class NotificationOperation: MVMCoreOperation { Task { guard await properties.getIsDisplayed(), await !properties.getIsAnimating() else { return } - transitionOperation = MVMCoreBlockOperation(block: { [weak self] blockOperation in + transitionOperation = MVMCoreBlockOperation(block: { blockOperation in guard !blockOperation.checkAndHandleForCancellation() else { return } - guard let self = self else { - blockOperation.markAsFinished() - return - } Task { await transition() blockOperation.markAsFinished() @@ -168,6 +167,14 @@ public class NotificationOperation: MVMCoreOperation { guard let self = self, !self.isFinished, !self.checkAndHandleForCancellation() else { return } + /* + // If accessible and focused, do not collapse until unfocused. + if (!forceful && [MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { + self.hideCompletionHandler = completionHandler; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessibilityFocusChanged:) name:UIAccessibilityElementFocusedNotification object:nil]; + return; + } + */ self.stop() }) timerSource?.setCancelHandler(handler: { [weak self] in @@ -200,6 +207,7 @@ public class NotificationOperation: MVMCoreOperation { await transitionDelegate.show(notification: notification) await properties.set(displayed: true) await properties.set(animating: false) + NotificationHandler.shared().onNotificationShown.send((notification, notificationModel)) } @MainActor @@ -208,6 +216,7 @@ public class NotificationOperation: MVMCoreOperation { await transitionDelegate.hide(notification: notification) await properties.set(displayed: false) await properties.set(animating: false) + NotificationHandler.shared().onNotificationDismissed.send((notification, notificationModel)) } /// Updates the notification with the new model. @@ -240,12 +249,23 @@ public class NotificationHandler { /// The operation queue of top notification operations. private var queue = OperationQueue() + public var transitionDelegate: NotificationTransitionDelegateProtocol + + private var delegateObject: MVMCoreUIDelegateObject? + + /// Publishes when a notification is shown. + public let onNotificationShown = PassthroughSubject<(UIView, TopNotificationModel), Never>() + + /// Publishes when a notification is dismissed. + public let onNotificationDismissed = PassthroughSubject<(UIView, TopNotificationModel), Never>() + /// Returns the handler stored in the CoreUIObject public static func shared() -> Self { return MVMCoreActionUtility.fatalClassCheck(object: CoreUIObject.sharedInstance()?.topNotificationHandler) } - public init() { + public init(with transitionDelegate: NotificationTransitionDelegateProtocol) { + self.transitionDelegate = transitionDelegate registerWithNotificationCenter() registerForPageChanges() } @@ -262,14 +282,8 @@ public class NotificationHandler { MVMCoreNavigationHandler.shared()?.addDelegate(self) } - private func getDelegateObject() -> MVMCoreUIDelegateObject? { - // TODO: Top alert view is current delegate. Should move to current view controller eventually? - guard let alertView = MVMCoreUISplitViewController.main()?.topAlertView else { return nil } - return MVMCoreUIDelegateObject.create(withDelegateForAll: alertView) - } - /// Checks for new top alert json - @objc private func responseJSONUpdated(notification: Notification) { + @objc private func responseJSONUpdated(notification: Notification) async { guard let loadObject = (notification.userInfo?[String(describing: MVMCoreLoadObject.self)] as? MVMCoreLoadObject) else { return } // Dismiss any top alerts that server wants us to dismiss/ @@ -279,29 +293,31 @@ public class NotificationHandler { // Show any new top alert. guard let responseJSON = loadObject.responseJSON, - let json = responseJSON.optionalDictionaryForKey(KeyTopAlert) else { return } - showTopNotification(with: json) + let json = responseJSON.optionalDictionaryForKey(KeyTopAlert) else { return } + Task { + await showNotification(for: json, delegateObject: delegateObject) + } } - /// Decodes the json into a TopNotificationModel - public func decodeTopNotification(with json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) -> TopNotificationModel? { + public func showNotification(for json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) async { do { - return try TopNotificationModel.decode(json: json, delegateObject: delegateObject) + let model = try TopNotificationModel.decode(json: json, delegateObject: delegateObject) + try await showNotification(for: model, delegateObject: delegateObject) } catch { if let errorObject = MVMCoreErrorObject.createErrorObject(for: error, location: "\(self)") { MVMCoreUILoggingHandler.addError(toLog: errorObject) } - return nil } } // MARK: - Operation Handling - private func add(operation: MVMCoreTopAlertOperation) { + /// Adds the operation to the queue. + private func add(operation: NotificationOperation) { operation.completionBlock = { [weak self] in // If the alert was cancelled to show another with higher priority, re-add to the operation when cancelled to the queue. if operation.reAddAfterCancel { - let newOperation: MVMCoreTopAlertOperation = operation.copy() as! MVMCoreTopAlertOperation + let newOperation: NotificationOperation = operation.copy() as! NotificationOperation newOperation.reAddAfterCancel = false self?.add(operation: newOperation) } @@ -309,20 +325,19 @@ public class NotificationHandler { } let currentPageType = (MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() as? MVMCoreViewControllerProtocol)?.pageType - operation.updateDisplayable(byPageType: currentPageType) + operation.updateDisplayable(by: currentPageType) queue.addOperation(operation) reevaluteQueue() } /// Checks for existing top alert object of same type and updates it. Only happens for molecular top alerts. Returns true if we updated. - private func checkAndUpdateExisting(with topAlertObject: MVMCoreTopAlertObject) -> Bool { - for case let operation as MVMCoreTopAlertOperation in queue.operations { - guard topAlertObject.json != nil, - operation.topAlertObject.type == topAlertObject.type else { continue } - operation.update(with: topAlertObject) + private func checkAndUpdateExisting(with model: TopNotificationModel) -> Bool { + for case let operation as NotificationOperation in queue.operations { + guard operation.notificationModel.type == model.type else { continue } + operation.update(with: model) let pageType = (MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() as? MVMCoreViewControllerProtocol)?.pageType - operation.updateDisplayable(byPageType: pageType) + operation.updateDisplayable(by: pageType) reevaluteQueue() return true } @@ -331,9 +346,9 @@ public class NotificationHandler { /// Re-evaluates the queue operations private func reevaluteQueue() { - var highestReadyOperation: MVMCoreTopAlertOperation? - var executingOperation: MVMCoreTopAlertOperation? - for case let operation as MVMCoreTopAlertOperation in queue.operations { + var highestReadyOperation: NotificationOperation? + var executingOperation: NotificationOperation? + for case let operation as NotificationOperation in queue.operations { guard !operation.isCancelled, !operation.isFinished else { continue } if operation.isReady, @@ -348,7 +363,7 @@ public class NotificationHandler { // Cancel the executing operation if it is no longer ready to run. Re-add for later if it is persistent. guard currentOperation.isReady else { - currentOperation.reAddAfterCancel = currentOperation.topAlertObject.persistent + currentOperation.reAddAfterCancel = currentOperation.notificationModel.persistent currentOperation.cancel() return } @@ -356,7 +371,7 @@ public class NotificationHandler { // If the highest priority operation is not executing, and the executing operation is persistent, cancel it. if let newOperation = highestReadyOperation, currentOperation != newOperation, - currentOperation.topAlertObject.persistent { + currentOperation.notificationModel.persistent { currentOperation.reAddAfterCancel = true currentOperation.cancel() } @@ -373,37 +388,25 @@ public class NotificationHandler { public func hasPersistentTopAlert(of type: String) -> Bool { return queue.operations.first(where: { operation in guard operation.isExecuting, - let operation = operation as? MVMCoreTopAlertOperation else { return false } - return operation.topAlertObject.persistent && operation.topAlertObject.type == type - }) as? MVMCoreTopAlertOperation != nil + let operation = operation as? NotificationOperation else { return false } + return operation.notificationModel.persistent && operation.notificationModel.type == type + }) as? NotificationOperation != nil } - /// Shows the top alert with the json. - func showTopNotification(with json: [AnyHashable: Any]) { - guard let model = decodeTopNotification(with: json, delegateObject: getDelegateObject()) else { return } - showTopNotification(with: model) - } - - /// Shows the top notification with the model. - func showTopNotification(with model: TopNotificationModel) { - let object = model.createTopAlertObject() - guard !checkAndUpdateExisting(with: object), - let operation = MVMCoreTopAlertOperation(topAlertObject: object) else { return } + /// Creates the view and queues up the notification. + public func showNotification(for model: TopNotificationModel, delegateObject: MVMCoreUIDelegateObject? = nil) async throws { + guard !checkAndUpdateExisting(with: model) else { return } + let view = try await createMolecule(for: model, delegateObject: delegateObject) + let operation = NotificationOperation(with: view, notificationModel: model, transitionDelegate: transitionDelegate) NotificationHandler.shared().add(operation: operation) } - - /// Show the top alert with the legacy object. - public func showTopAlert(with topAlertObject: MVMCoreTopAlertObject) { - let alertOperation = MVMCoreTopAlertOperation(topAlertObject: topAlertObject)! - add(operation: alertOperation) - } /// Cancel the current top alert view. public func hideTopAlertView() { guard let currentOperation = queue.operations.first(where: { operation in return operation.isExecuting - }) as? MVMCoreTopAlertOperation else { return } - currentOperation.topAlertObject.persistent = false + }) as? NotificationOperation else { return } + currentOperation.notificationModel.persistent = false currentOperation.reAddAfterCancel = false currentOperation.cancel() } @@ -411,8 +414,8 @@ public class NotificationHandler { /// Cancel all operations of this type. public func hideTopAlertView(of type: String) { for operation in queue.operations { - guard let operation = operation as? MVMCoreTopAlertOperation, - operation.topAlertObject.type == type else { continue } + guard let operation = operation as? NotificationOperation, + operation.notificationModel.type == type else { continue } operation.reAddAfterCancel = false operation.cancel() } @@ -421,19 +424,19 @@ public class NotificationHandler { /// Cancel all persistent operations of this type. public func hidePersistentTopAlertView(of type: String) { for operation in queue.operations { - guard let operation = operation as? MVMCoreTopAlertOperation, - operation.topAlertObject.persistent, - operation.topAlertObject.type == type else { continue } + guard let operation = operation as? NotificationOperation, + operation.notificationModel.persistent, + operation.notificationModel.type == type else { continue } operation.reAddAfterCancel = false operation.cancel() } } /// Finds an cancels top alerts associated with the object. - public func removeTopAlert(for object: MVMCoreTopAlertObject) { + public func removeTopAlert(for object: TopNotificationModel) { for operation in queue.operations { - guard let operation = operation as? MVMCoreTopAlertOperation, - operation.topAlertObject === object else { return } + guard let operation = operation as? NotificationOperation, + operation.notificationModel.id == object.id else { return } operation.reAddAfterCancel = false operation.cancel() } @@ -442,6 +445,27 @@ public class NotificationHandler { public func removeAllTopAlerts() { queue.cancelAllOperations() } + + public func getCurrentNotification() async -> (UIView, TopNotificationModel)? { + for operation in queue.operations { + guard operation.isExecuting, + let operation = operation as? NotificationOperation, + await operation.properties.getIsDisplayed() else { continue } + return (operation.notification, operation.notificationModel) + } + return nil + } + + /// Creates and returns the molecule view. + @MainActor + private func createMolecule(for model: TopNotificationModel, delegateObject: MVMCoreUIDelegateObject? = nil) throws -> UIView { + do { + guard let molecule = ModelRegistry.createMolecule(model.molecule, delegateObject: delegateObject, additionalData: nil) else { + throw ModelRegistry.Error.decoderOther(message: "Molecule not mapped") + } + return molecule + } + } } extension NotificationHandler: MVMCorePresentationDelegateProtocol { @@ -452,11 +476,11 @@ extension NotificationHandler: MVMCorePresentationDelegateProtocol { guard viewController == MVMCoreUISplitViewController.main()?.getCurrentViewController() else { return } let pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType queue.operations.compactMap { - $0 as? MVMCoreTopAlertOperation + $0 as? NotificationOperation }.sorted { $0.queuePriority.rawValue > $1.queuePriority.rawValue }.forEach { - $0.updateDisplayable(byPageType: pageType) + $0.updateDisplayable(by: pageType) } reevaluteQueue() } @@ -464,7 +488,15 @@ extension NotificationHandler: MVMCorePresentationDelegateProtocol { extension NotificationOperation { /// Updates if the operation is displayable based on the page type. - func updateDisplayable(by pageType: String) { - isDisplayable = notificationModel.pages?.contains(pageType) ?? true + func updateDisplayable(by pageType: String?) { + guard let pages = notificationModel.pages else { + isDisplayable = true + return + } + guard let pageType = pageType else { + isDisplayable = false + return + } + isDisplayable = pages.contains(pageType) } } diff --git a/MVMCoreUI/Notification/TopNotificationModel.swift b/MVMCoreUI/Notification/TopNotificationModel.swift index 75300a3f..9e84c8b9 100644 --- a/MVMCoreUI/Notification/TopNotificationModel.swift +++ b/MVMCoreUI/Notification/TopNotificationModel.swift @@ -7,8 +7,9 @@ // import Foundation +import MVMCore -open class TopNotificationModel: Codable { +open class TopNotificationModel: Codable, Identifiable { public var type: String public var priority = Operation.QueuePriority.normal public var molecule: MoleculeModelProtocol @@ -16,7 +17,8 @@ open class TopNotificationModel: Codable { public var dismissTime = 5 public var pages: [String]? public var analyticsData: JSONValueDictionary? - + public var id: String + private enum CodingKeys: String, CodingKey { case type case priority @@ -25,6 +27,7 @@ open class TopNotificationModel: Codable { case dismissTime case pages case analyticsData + case id } //-------------------------------------------------- @@ -55,17 +58,6 @@ open class TopNotificationModel: Codable { return (shifted / Float(scale)) * 100.0 } - open func createTopAlertObject() -> MVMCoreTopAlertObject { - let object = MVMCoreTopAlertObject() - object.persistent = persistent - object.type = type - object.topAlertDismissTime = dismissTime - object.queuePriority = priority - object.useNewStyle = true - object.json = toJSON() - return object - } - /// Decodes the top alert json to a model. public static func decode(json: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?) throws -> Self { let data = try JSONSerialization.data(withJSONObject: json) @@ -77,7 +69,7 @@ open class TopNotificationModel: Codable { // MARK: - Initializer //-------------------------------------------------- - public init(with type: String, molecule: MoleculeModelProtocol, priority: Operation.QueuePriority = .normal, persistent: Bool = false, dismissTime: Int = 5, pages: [String]? = nil, analyticsData: JSONValueDictionary? = nil) { + public init(with type: String, molecule: MoleculeModelProtocol, priority: Operation.QueuePriority = .normal, persistent: Bool = false, dismissTime: Int = 5, pages: [String]? = nil, analyticsData: JSONValueDictionary? = nil, id: String = UUID().uuidString) { self.type = type self.molecule = molecule self.priority = priority @@ -85,6 +77,7 @@ open class TopNotificationModel: Codable { self.dismissTime = dismissTime self.pages = pages self.analyticsData = analyticsData + self.id = id } //-------------------------------------------------- @@ -95,6 +88,7 @@ open class TopNotificationModel: Codable { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) type = try typeContainer.decode(String.self, forKey: .type) molecule = try typeContainer.decodeModel(codingKey: .molecule) + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString if let priorityPercent = try typeContainer.decodeIfPresent(Float.self, forKey: .priority) { setPriority(with: priorityPercent) } @@ -117,5 +111,6 @@ open class TopNotificationModel: Codable { try container.encode(dismissTime, forKey: .dismissTime) try container.encodeIfPresent(pages, forKey: .pages) try container.encodeIfPresent(analyticsData, forKey: .analyticsData) + try container.encode(id, forKey: .id) } } diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 11108eeb..1a109624 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -232,7 +232,6 @@ open class CoreUIModelMapping: ModelMapping { open override class func registerActions() { super.registerActions() ModelRegistry.register(handler: ActionAlertHandler.self, for: ActionAlertModel.self) - ModelRegistry.register(handler: ActionTopAlertHandler.self, for: ActionTopAlertModel.self) ModelRegistry.register(handler: ActionCollapseNotificationHandler.self, for: ActionCollapseNotificationModel.self) ModelRegistry.register(handler: ActionDismissNotificationHandler.self, for: ActionDismissNotificationModel.self) ModelRegistry.register(handler: ActionOpenPanelHandler.self, for: ActionOpenPanelModel.self) diff --git a/MVMCoreUI/OtherHandlers/CoreUIObject.swift b/MVMCoreUI/OtherHandlers/CoreUIObject.swift index 358e74ad..6312581e 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIObject.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIObject.swift @@ -17,14 +17,16 @@ import MVMCore CoreUIModelMapping.registerObjects() loadHandler = MVMCoreLoadHandler() cache = MVMCoreCache() + session = MVMCoreUISession() Task { @MainActor in self.sessionHandler = MVMCoreSessionTimeHandler() + let topAlertView = NotificationContainerView() + MVMCoreUISession.sharedGlobal()?.topAlertView = topAlertView + self.topNotificationHandler = NotificationHandler(with: topAlertView) } actionHandler = MVMCoreUIActionHandler() - session = MVMCoreUISession() viewControllerMapping = MVMCoreUIViewControllerMappingObject() loggingDelegate = MVMCoreUILoggingHandler() alertHandler = AlertHandler() - topNotificationHandler = NotificationHandler() } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift index 0a79ae9e..17ded151 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift @@ -18,7 +18,6 @@ open class MVMCoreUIDelegateObject: DelegateObject { public weak var observingTextFieldDelegate: ObservingTextFieldDelegate? public weak var moleculeDelegate: MoleculeDelegateProtocol? public weak var alertDelegate: (AlertDelegateProtocol & NSObjectProtocol)? - public weak var topAlertDelegate: (MVMCoreTopAlertDelegateProtocol & NSObjectProtocol)? open override func setAll(withDelegate delegate: Any) { super.setAll(withDelegate: delegate) @@ -29,7 +28,6 @@ open class MVMCoreUIDelegateObject: DelegateObject { observingTextFieldDelegate = delegate as? ObservingTextFieldDelegate moleculeDelegate = delegate as? MoleculeDelegateProtocol alertDelegate = delegate as? (AlertDelegateProtocol & NSObjectProtocol) - topAlertDelegate = delegate as? (MVMCoreTopAlertDelegateProtocol & NSObjectProtocol) } class func delegateObject(from controller: MVMCoreViewControllerProtocol?) -> MVMCoreUIDelegateObject? { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h index b61c2b0a..a4b66ef9 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.h @@ -7,8 +7,6 @@ // @import MVMCore.MVMCoreLoggingHandler; -@class MFViewController; -@class MVMCoreTopAlertObject; NS_ASSUME_NONNULL_BEGIN @@ -21,9 +19,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)defaultLogActionForController:(nullable id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; - (nullable NSDictionary *)defaultGetActionTrackDataDictionaryForController:(nullable id )controller actionInformation:(nullable NSDictionary *)actionInformation additionalData:(nullable NSDictionary *)additionalData; -// Logging top notification. -- (void)trackTopNotificationShown:(nonnull UIView *)topNotification topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject additionalData:(nullable NSDictionary *)additionalData; - @end NS_ASSUME_NONNULL_END diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m index ed073722..45a13acf 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUILoggingHandler.m @@ -20,7 +20,4 @@ return nil; } -- (void)trackTopNotificationShown:(UIView *)topNotification topAlertObject:(MVMCoreTopAlertObject *)topAlertObject additionalData:(NSDictionary *)additionalData { -} - @end diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUISession.h b/MVMCoreUI/OtherHandlers/MVMCoreUISession.h index a81c8ee2..134ae00d 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUISession.h +++ b/MVMCoreUI/OtherHandlers/MVMCoreUISession.h @@ -8,7 +8,6 @@ @import UIKit.UIView; @import MVMCore.MVMCoreSessionObject; -@class MVMCoreUITopAlertView; @class MVMCoreUISplitViewController; @class MFViewController; @class MFLoadingViewController; @@ -18,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @interface MVMCoreUISession : MVMCoreSessionObject -@property (weak, nonatomic, nullable) MVMCoreUITopAlertView *topAlertView; +@property (weak, nonatomic, nullable) UIView *topAlertView; @property (weak, nonatomic, nullable) MVMCoreUISplitViewController *splitViewController; @property (weak, nonatomic, nullable) NavigationController *navigationController; @property (weak, nonatomic, nullable) MFLoadingViewController *loadingViewController; @@ -32,9 +31,6 @@ NS_ASSUME_NONNULL_BEGIN /// indicates if the app launched successfully @property (assign, nonatomic) BOOL launchAppLoadedSuccessfully; -/// Allows a global overload of the title view of navigation item. -- (nullable UIView *)titleViewForController:(nonnull MFViewController *)controller; - /// Sets up the session as delegate for standard load view controller. Pass the view controller that will be used to present and will be disabled when load view is presented. - (void)setupAsStandardLoadViewDelegate:(nonnull UIViewController *)mainViewController; diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUISession.m b/MVMCoreUI/OtherHandlers/MVMCoreUISession.m index 957b5c19..42a3e769 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUISession.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUISession.m @@ -19,10 +19,6 @@ @implementation MVMCoreUISession -- (nullable UIView *)titleViewForController:(nonnull MFViewController *)controller { - return nil; -} - - (void)setupAsStandardLoadViewDelegate:(nonnull UIViewController *)mainViewController { self.mainViewController = mainViewController; [MVMCoreObject sharedInstance].loadingProtocol = self;