From 0f7d62c912aafa3c9c87128f53480a2835693b09 Mon Sep 17 00:00:00 2001 From: Ryan Lepinski Date: Wed, 6 Dec 2023 12:47:12 -0800 Subject: [PATCH] Fix mc display (#2889) --- .../DefaultAppIntegrationDelegate.swift | 4 + .../DefaultAppIntegrationDelegateTest.swift | 1 + .../Source/MessageCenter.swift | 67 +++++++------- .../views/MessageCenterController.swift | 19 ++-- .../Source/views/MessageCenterListView.swift | 87 ++++++++----------- .../Source/views/MessageCenterView.swift | 8 +- 6 files changed, 82 insertions(+), 104 deletions(-) diff --git a/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift b/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift index 7c3e47a08..27aa4771f 100644 --- a/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift +++ b/Airship/AirshipCore/Source/DefaultAppIntegrationDelegate.swift @@ -53,6 +53,7 @@ class DefaultAppIntegrationDelegate: NSObject, AppIntegrationDelegate { } #if !os(watchOS) + @MainActor public func didReceiveRemoteNotification( userInfo: [AnyHashable: Any], isForeground: Bool, @@ -76,6 +77,7 @@ class DefaultAppIntegrationDelegate: NSObject, AppIntegrationDelegate { } } #else + @MainActor public func didReceiveRemoteNotification( userInfo: [AnyHashable: Any], isForeground: Bool, @@ -100,6 +102,7 @@ class DefaultAppIntegrationDelegate: NSObject, AppIntegrationDelegate { } #endif + @MainActor public func willPresentNotification( notification: UNNotification, presentationOptions: UNNotificationPresentationOptions, @@ -205,6 +208,7 @@ class DefaultAppIntegrationDelegate: NSObject, AppIntegrationDelegate { } } + @MainActor private func processPush( _ userInfo: [AnyHashable: Any], isForeground: Bool, diff --git a/Airship/AirshipCore/Tests/DefaultAppIntegrationDelegateTest.swift b/Airship/AirshipCore/Tests/DefaultAppIntegrationDelegateTest.swift index 1c3deb58a..611bc084d 100644 --- a/Airship/AirshipCore/Tests/DefaultAppIntegrationDelegateTest.swift +++ b/Airship/AirshipCore/Tests/DefaultAppIntegrationDelegateTest.swift @@ -43,6 +43,7 @@ class DefaultAppIntegrationdelegateTest: XCTestCase { XCTAssertEqual("some error", error.localizedDescription) } + @MainActor func testDidReceiveRemoteNotification() throws { let expectedUserInfo = ["neat": "story"] diff --git a/Airship/AirshipMessageCenter/Source/MessageCenter.swift b/Airship/AirshipMessageCenter/Source/MessageCenter.swift index f906e0eb1..53213f4e3 100644 --- a/Airship/AirshipMessageCenter/Source/MessageCenter.swift +++ b/Airship/AirshipMessageCenter/Source/MessageCenter.swift @@ -131,6 +131,7 @@ public class MessageCenter: NSObject, ObservableObject { /// Display the message center. @objc + @MainActor public func display() { guard self.enabled else { AirshipLogger.warn("Message center disabled. Unable to display.") @@ -139,10 +140,8 @@ public class MessageCenter: NSObject, ObservableObject { guard let displayDelegate = self.displayDelegate else { AirshipLogger.trace("Launching OOTB message center") - self.controller.displayMessageCenter(true) - Task { - await openDefaultMessageCenter() - } + showDefaultMessageCenter() + self.controller.navigate(messageID: nil) return } @@ -154,6 +153,7 @@ public class MessageCenter: NSObject, ObservableObject { /// - Parameters: /// - messageID: The messageID of the message. @objc(displayWithMessageID:) + @MainActor public func display(messageID: String) { guard self.enabled else { AirshipLogger.warn("Message center disabled. Unable to display.") @@ -162,10 +162,8 @@ public class MessageCenter: NSObject, ObservableObject { guard let displayDelegate = self.displayDelegate else { AirshipLogger.trace("Launching OOTB message center") - self.controller.displayMessage(messageID) - Task { - await openDefaultMessageCenter() - } + showDefaultMessageCenter() + self.controller.navigate(messageID: messageID) return } @@ -181,33 +179,15 @@ public class MessageCenter: NSObject, ObservableObject { if let displayDelegate = self.displayDelegate { displayDelegate.dismissMessageCenter() } else { - currentDisplay?.dispose() + Task { @MainActor in + self.dismissDefaultMessageCenter() + } } } private func updateEnableState() { self.inbox.enabled = self.enabled } - - @MainActor - private func openDefaultMessageCenter() async { - guard let scene = try? AirshipUtils.findWindowScene() else { - AirshipLogger.error( - "Unable to display message center, missing scene." - ) - return - } - - currentDisplay?.dispose() - - AirshipLogger.debug("Opening default message center UI") - - self.currentDisplay = showMessageCenter( - scene: scene, - theme: theme - ) - } - } extension MessageCenter: AirshipComponent, PushableComponent { @@ -226,6 +206,7 @@ extension MessageCenter: AirshipComponent, PushableComponent { } } + @MainActor func deepLink(deepLink: URL) -> Bool { if !(deepLink.scheme == Airship.deepLinkScheme) { return false @@ -254,6 +235,7 @@ extension MessageCenter: AirshipComponent, PushableComponent { // MARK: PushableComponent + @MainActor public func receivedRemoteNotification( _ notification: [AnyHashable: Any], completionHandler: @escaping (UIBackgroundFetchResult) -> Void @@ -290,13 +272,21 @@ extension MessageCenter: AirshipComponent, PushableComponent { extension MessageCenter { @MainActor - fileprivate func showMessageCenter( - scene: UIWindowScene, - theme: MessageCenterTheme? - ) -> Disposable { + fileprivate func showDefaultMessageCenter() { + guard self.currentDisplay == nil else { + return + } + + guard let scene = try? AirshipUtils.findWindowScene() else { + AirshipLogger.error( + "Unable to display message center, missing scene." + ) + return + } + var window: UIWindow? = UIWindow(windowScene: scene) - let disposable = Disposable { + self.currentDisplay = Disposable { window?.windowLevel = .normal window?.isHidden = true window = nil @@ -306,14 +296,19 @@ extension MessageCenter { theme: theme, controller: self.controller ) { - disposable.dispose() + self.currentDisplay?.dispose() + self.currentDisplay = nil } window?.isHidden = false window?.windowLevel = .alert window?.makeKeyAndVisible() window?.rootViewController = viewController + } - return disposable + @MainActor + fileprivate func dismissDefaultMessageCenter() { + self.currentDisplay?.dispose() + self.currentDisplay = nil } } diff --git a/Airship/AirshipMessageCenter/Source/views/MessageCenterController.swift b/Airship/AirshipMessageCenter/Source/views/MessageCenterController.swift index c6e46c9e3..19d58cd04 100644 --- a/Airship/AirshipMessageCenter/Source/views/MessageCenterController.swift +++ b/Airship/AirshipMessageCenter/Source/views/MessageCenterController.swift @@ -18,23 +18,18 @@ public enum MessageCenterState: Equatable { public class MessageCenterController: NSObject, ObservableObject { @Published - private(set) var visibleMessageID: String? = nil + var messageID: String? = nil + + @Published + var visibleMessageID: String? = nil @Published - private var isMessageCenterVisible: Bool = false + var isMessageCenterVisible: Bool = false private var subscriptions: Set = Set() private let updateSubject = PassthroughSubject() - - func displayMessageCenter(_ display: Bool) { - self.isMessageCenterVisible = display - } - - func displayMessage(_ messageId: String?) { - self.visibleMessageID = messageId - } - + /// Publisher that emits the message center state. public var statePublisher: AnyPublisher { self.updateSubject @@ -47,7 +42,7 @@ public class MessageCenterController: NSObject, ObservableObject { /// - messageID: The message ID to navigate to. @objc public func navigate(messageID: String?) { - self.displayMessage(messageID) + self.messageID = messageID } @objc diff --git a/Airship/AirshipMessageCenter/Source/views/MessageCenterListView.swift b/Airship/AirshipMessageCenter/Source/views/MessageCenterListView.swift index dd48ed30c..a2ee5198c 100644 --- a/Airship/AirshipMessageCenter/Source/views/MessageCenterListView.swift +++ b/Airship/AirshipMessageCenter/Source/views/MessageCenterListView.swift @@ -23,8 +23,6 @@ public struct MessageCenterListView: View { @Environment(\.airshipMessageCenterTheme) private var theme - @Environment(\.airshipMessageViewStyle) - private var messageStyle @StateObject private var viewModel = MessageCenterListViewModel() @@ -51,23 +49,30 @@ public struct MessageCenterListView: View { viewModel.delete(messages: messages) } + @ViewBuilder + private func makeDestination(messageID: String, title: String?) -> some View { + MessageCenterMessageView( + messageID: messageID, + title: title + ) + .onAppear { + self.controller.visibleMessageID = messageID + } + .onDisappear { + if (messageID == self.controller.visibleMessageID) { + self.controller.visibleMessageID = nil + } + } + .id(messageID) + } + @ViewBuilder private func makeCell( item: MessageCenterListItemViewModel, messageID: String ) -> some View { let cell = NavigationLink( - destination: - MessageCenterMessageView( - messageID: messageID, - title: item.message.title - ) - .onAppear { - self.controller.displayMessage(messageID) - } - .onDisappear { - self.controller.displayMessage(nil) - } + destination: makeDestination(messageID: messageID, title: item.message.title) ) { MessageCenterListItemView(viewModel: item) } @@ -105,11 +110,8 @@ public struct MessageCenterListView: View { self.$selection.wrappedValue.removeAll() } } - .onAppear{ - let _ = self.controller.$visibleMessageID - .sink { - isActive = ($0 != nil) - } + .onReceive(self.controller.$messageID) { messageID in + isActive = (messageID != nil) } } @@ -124,7 +126,6 @@ public struct MessageCenterListView: View { @ViewBuilder private func makeContent() -> some View { - let content = ZStack { makeList() .opacity(self.listOpacity) @@ -154,42 +155,24 @@ public struct MessageCenterListView: View { } } } - - let destination = self.messageStyle.makeBody( - configuration: MessageViewStyleConfiguration( - messageID: self.controller.visibleMessageID ?? "", - title: self.viewModel.messageItem( - forID: self.controller.visibleMessageID ?? "" - )?.message.title, - dismissAction: nil - ) + + let selected = self.controller.messageID ?? "" + let destination = makeDestination( + messageID: selected, + title: self.viewModel.messageItem(forID: selected)?.message.title ) - .onAppear { - self.controller.displayMessage(self.controller.visibleMessageID) - } - .onDisappear { - self.controller.displayMessage(nil) - } - + if #available(iOS 16.0, *) { - content - .background( - NavigationLink( - "", - value: self.controller.visibleMessageID) - .navigationDestination(isPresented: $isActive) { - destination - } - ) + content.background( + NavigationLink("", value: selected) + .navigationDestination(isPresented: $isActive) { + destination + } + ) } else { - content - .background( - NavigationLink( - "", - destination: destination, - isActive: $isActive - ) - ) + content.background( + NavigationLink("", destination: destination, isActive: $isActive) + ) } } diff --git a/Airship/AirshipMessageCenter/Source/views/MessageCenterView.swift b/Airship/AirshipMessageCenter/Source/views/MessageCenterView.swift index 884033653..c13ed993b 100644 --- a/Airship/AirshipMessageCenter/Source/views/MessageCenterView.swift +++ b/Airship/AirshipMessageCenter/Source/views/MessageCenterView.swift @@ -65,10 +65,10 @@ public struct MessageCenterView: View { content } .onAppear { - self.controller.displayMessageCenter(true) + self.controller.isMessageCenterVisible = true } .onDisappear { - self.controller.displayMessageCenter(false) + self.controller.isMessageCenterVisible = false } } else { NavigationView { @@ -76,10 +76,10 @@ public struct MessageCenterView: View { } .navigationViewStyle(.stack) .onAppear { - self.controller.displayMessageCenter(true) + self.controller.isMessageCenterVisible = true } .onDisappear { - self.controller.displayMessageCenter(false) + self.controller.isMessageCenterVisible = false } } }