From b816afba1cc91ff46261f0bdcc6e8af6a0972d9a Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 28 Jul 2022 18:30:01 -0400 Subject: [PATCH] Fix for top notification dismiss bug --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +++++ .../ActionDismissNotificationHandler.swift | 23 +++++++++++++ .../ActionDismissNotificationModel.swift | 23 +++++++++++++ .../TopNotification/NotificationModel.swift | 26 +++++--------- .../TopNotification/NotificationXButton.swift | 7 ++-- .../OtherHandlers/CoreUIModelMapping.swift | 1 + ...MVMCoreTopAlertAnimationDelegateProtocol.h | 7 ++-- MVMCoreUI/TopAlert/MVMCoreTopAlertOperation.m | 34 +++++++++++-------- .../TopAlert/MVMCoreUITopAlertBaseView.m | 6 +--- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 2 ++ 10 files changed, 93 insertions(+), 44 deletions(-) create mode 100644 MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift create mode 100644 MVMCoreUI/Atomic/Actions/ActionDismissNotificationModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index cc0ba543..7b1bfd19 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -285,6 +285,8 @@ AF1C336F2885A16A006B1001 /* ActionCollapseNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */; }; AF1C33712885AE76006B1001 /* MVMCoreUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */; }; AF1C33732885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */; }; + AF60A7F62892D2E300919EEB /* ActionDismissNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */; }; + AF60A7F82892D34D00919EEB /* ActionDismissNotificationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */; }; AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; }; AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; @@ -883,6 +885,8 @@ AF1C336E2885A16A006B1001 /* ActionCollapseNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionCollapseNotificationHandler.swift; sourceTree = ""; }; AF1C33702885AE76006B1001 /* MVMCoreUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIActionHandler.swift; sourceTree = ""; }; AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIActionOpenPageHandler.swift; sourceTree = ""; }; + AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDismissNotificationModel.swift; sourceTree = ""; }; + AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionDismissNotificationHandler.swift; sourceTree = ""; }; AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = ""; }; AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; @@ -1505,6 +1509,8 @@ C6687440259D92D400F32D13 /* ActionTopNotificationModel.swift */, AF1C33642883B5A4006B1001 /* ActionTopNotificationHandler.swift */, AF1C33722885D481006B1001 /* MVMCoreUIActionOpenPageHandler.swift */, + AF60A7F52892D2E300919EEB /* ActionDismissNotificationModel.swift */, + AF60A7F72892D34D00919EEB /* ActionDismissNotificationHandler.swift */, ); path = Actions; sourceTree = ""; @@ -2999,6 +3005,7 @@ 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */, AA7F32AB246C0F7900C965BA /* ListLeftVariableRadioButtonAllTextAndLinksModel.swift in Sources */, 8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */, + AF60A7F82892D34D00919EEB /* ActionDismissNotificationHandler.swift in Sources */, D253BB9E2458751F002DE544 /* BGImageMoleculeModel.swift in Sources */, AA104AC924472DC7004D2810 /* HeadersH1ButtonModel.swift in Sources */, 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */, @@ -3041,6 +3048,7 @@ D23A8FD9260CE004007E14CE /* MFStyler+PaddingExtension.swift in Sources */, 1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, + AF60A7F62892D2E300919EEB /* ActionDismissNotificationModel.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, AAB7EDF1246ADA2A00E54929 /* ListProgressBarThin.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift b/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift new file mode 100644 index 00000000..65db5455 --- /dev/null +++ b/MVMCoreUI/Atomic/Actions/ActionDismissNotificationHandler.swift @@ -0,0 +1,23 @@ +// +// ActionDismissNotificationHandler.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 7/28/22. +// Copyright © 2022 Verizon Wireless. All rights reserved. +// + +import Foundation +import MVMCore + +/// Collapse the current top notification. +open class ActionDismissNotificationHandler: MVMCoreActionHandlerProtocol { + required public init() {} + + open func performAction(_ 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() + } + } +} diff --git a/MVMCoreUI/Atomic/Actions/ActionDismissNotificationModel.swift b/MVMCoreUI/Atomic/Actions/ActionDismissNotificationModel.swift new file mode 100644 index 00000000..13816f37 --- /dev/null +++ b/MVMCoreUI/Atomic/Actions/ActionDismissNotificationModel.swift @@ -0,0 +1,23 @@ +// +// ActionDismissNotificationModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 7/28/22. +// Copyright © 2022 Verizon Wireless. All rights reserved. +// + +import Foundation +import MVMCore + +public struct ActionDismissNotificationModel: ActionModelProtocol { + + public static var identifier: String = "dismissNotification" + public var actionType: String = ActionDismissNotificationModel.identifier + public var extraParameters: JSONValueDictionary? + public var analyticsData: JSONValueDictionary? + + public init(_ extraParameters: JSONValueDictionary? = nil, _ analyticsData: JSONValueDictionary? = nil) { + self.extraParameters = extraParameters + self.analyticsData = analyticsData + } +} diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift index bd84b7fd..fe40a022 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift @@ -85,24 +85,14 @@ open class NotificationModel: ContainerModel, MoleculeModelProtocol { } button?.size = .tiny - if button?.enabledTextColor == nil { - switch style { - case .error, .warning: - button?.enabledTextColor = Color(uiColor: .mvmBlack) - default: - button?.enabledTextColor = Color(uiColor: .mvmWhite) - } - } - if button?.enabledBorderColor == nil { - switch style { - case .error, .warning: - button?.enabledBorderColor = Color(uiColor: .mvmBlack) - default: - button?.enabledBorderColor = Color(uiColor: .mvmWhite) - } - } - if button?.style == nil { - button?.style = .secondary + button?.style = .secondary + switch style { + case .error, .warning: + button?.enabledTextColor = Color(uiColor: .mvmBlack) + button?.enabledBorderColor = Color(uiColor: .mvmBlack) + default: + button?.enabledTextColor = Color(uiColor: .mvmWhite) + button?.enabledBorderColor = Color(uiColor: .mvmWhite) } if closeButton?.color == nil { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift index 204785cb..2bce8658 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift @@ -7,15 +7,12 @@ // import Foundation +import MVMCore @objcMembers open class NotificationXButton: Button { open func closeTopAlert() { - if let delegate = MVMCoreUITopAlertView.sharedGlobal()?.animationDelegate { - delegate.topAlertCloseButtonPressed() - } else { - MVMCoreUISession.sharedGlobal()?.topAlertView?.hideAlertView(true, completionHandler: nil) - } + _ = MVMCoreUIActionHandler.shared()?.asyncHandleAction(with: ActionDismissNotificationModel(), additionalData: nil, delegateObject: nil) } open override func setupView() { diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 04d10423..061c67fb 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -232,6 +232,7 @@ open class CoreUIModelMapping: ModelMapping { 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) ModelRegistry.register(handler: ActionTopNotificationHandler.self, for: ActionTopNotificationModel.self) ModelRegistry.register(handler: MVMCoreUIActionOpenPageHandler.self, for: ActionOpenPageModel.self, allowsReplace: true) diff --git a/MVMCoreUI/TopAlert/MVMCoreTopAlertAnimationDelegateProtocol.h b/MVMCoreUI/TopAlert/MVMCoreTopAlertAnimationDelegateProtocol.h index bb9f6dfc..52922df4 100644 --- a/MVMCoreUI/TopAlert/MVMCoreTopAlertAnimationDelegateProtocol.h +++ b/MVMCoreUI/TopAlert/MVMCoreTopAlertAnimationDelegateProtocol.h @@ -16,7 +16,10 @@ // Called when the top alert is ending an animation - (void)topAlertViewFinishAnimation; -// Called when the top alert close button was pressed by the user -- (void)topAlertCloseButtonPressed; +// Called when the top alert is starting to dismiss. +- (void)topAlertWillDismiss; + +// Called when the top alert is dismissed. +- (void)topAlertDismissed; @end diff --git a/MVMCoreUI/TopAlert/MVMCoreTopAlertOperation.m b/MVMCoreUI/TopAlert/MVMCoreTopAlertOperation.m index 7a57f989..f0011719 100644 --- a/MVMCoreUI/TopAlert/MVMCoreTopAlertOperation.m +++ b/MVMCoreUI/TopAlert/MVMCoreTopAlertOperation.m @@ -183,11 +183,11 @@ if (self.isCancelled) { // Cancelled, dismiss immediately. - [self dismissAlertView:YES forceful:YES]; + [self dismissAlertView:YES]; } else if (self.isPaused) { // Paused, dismiss for the time being if persistent. - [self dismissAlertView:!self.topAlertObject.persistent forceful:YES]; + [self dismissAlertView:YES]; } else { [self updateDismissTimer]; } @@ -223,7 +223,7 @@ if (weakSelf.isFinished || [weakSelf checkAndHandleForCancellation]) { return; } - [weakSelf dismissAlertView:YES forceful:NO]; + [weakSelf dismissAlertView:NO]; }); dispatch_resume(self.timerSource); } @@ -235,27 +235,21 @@ if (!self.isAnimating) { if (self.isDisplayed) { - [self dismissAlertView:YES forceful:YES]; + [self dismissAlertView:YES]; } else if (self.isExecuting) { [self markAsFinished]; } } } -- (void)dismissAlertView:(BOOL)andFinish forceful:(BOOL)forceful { +- (void)dismissAlertView:(BOOL)forceful { if (self.timerSource) { dispatch_source_cancel(self.timerSource); } if (self.isDisplayed && !self.isAnimating) { // Dismisses. - [[[CoreUIObject sharedInstance].globalTopAlertDelegate getTopAlertView] hideAlertView:forceful completionHandler:^(BOOL finished) { - - self.displayed = NO; - if (andFinish) { - [self markAsFinished]; - } - }]; + [[[CoreUIObject sharedInstance].globalTopAlertDelegate getTopAlertView] hideAlertView:forceful completionHandler:NULL]; } } @@ -266,7 +260,7 @@ self.paused = YES; [self didChangeValueForKey:@"isPaused"]; } - [self dismissAlertView:!self.topAlertObject.persistent forceful:YES]; + [self dismissAlertView:YES]; } - (void)unpause { @@ -291,8 +285,20 @@ self.animating = NO; } +- (void)topAlertDismissed { + self.displayed = NO; + if (!self.isCancelled && self.isPaused && self.topAlertObject.persistent) { return; } + [self markAsFinished]; +} + +- (void)topAlertWillDismiss { + if (self.timerSource) { + dispatch_source_cancel(self.timerSource); + } +} + - (void)topAlertCloseButtonPressed { - [self dismissAlertView:YES forceful:YES]; + [self dismissAlertView:YES]; } - (id)copyWithZone:(nullable NSZone *)zone { diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertBaseView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertBaseView.m index 19570ca2..862e4b5b 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertBaseView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertBaseView.m @@ -70,11 +70,7 @@ - (nonnull Button *)addCloseButtonWithAnimationDelegate:(nullable id )animationDelegate { Button *closeButton = [MVMCoreUICommonViewsUtility addCloseButtonTo:self action:^(Button * _Nonnull button) { - if (animationDelegate) { - [animationDelegate topAlertCloseButtonPressed]; - } else { - [[MVMCoreUISession sharedGlobal].topAlertView hideAlertView:YES completionHandler:nil]; - } + [[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; diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index 108d7a84..292d9132 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -226,6 +226,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; __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 @@ -251,6 +252,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; if (completionHandler) { completionHandler(finished); } + [weakSelf.animationDelegate topAlertDismissed]; weakSelf.topAlertObject = nil; if (weakSelf.currentAlertOverridingStatusBar) { weakSelf.currentAlertOverridingStatusBar = NO;