diff --git a/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayController.swift b/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayController.swift index f8e813e96..52d8b39d3 100644 --- a/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayController.swift +++ b/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayController.swift @@ -1,59 +1,26 @@ import SwiftUI class OverlayController: ObservableObject { - private var overlay: UIWindow? - private var views: [UIView] - - init() { - self.overlay = OverlayWindow() - self.views = [] - } - - func present( + var rootVC: UIViewController? + + @MainActor func present( @ViewBuilder content: @escaping () -> Content ) { - guard let overlay else { return } - - let viewController = UIHostingController( - rootView: content() - .environmentObject(self) - ) + let viewController = UIHostingController(rootView: content()) viewController.view.backgroundColor = .clear - - views.append(viewController.view) - - if let rootViewController = overlay.rootViewController { - viewController.view.frame = rootViewController.view.frame - } else { - overlay.rootViewController = viewController - overlay.isUserInteractionEnabled = true - overlay.isHidden = false - } + viewController.modalTransitionStyle = .crossDissolve + viewController.modalPresentationStyle = .overCurrentContext + + self.rootVC = UIApplication + .shared + .connectedScenes + .flatMap { ($0 as? UIWindowScene)?.windows ?? [] } + .first(where: { $0.isKeyWindow })?.rootViewController + + rootVC?.present(viewController, animated: true) } - - func dismiss() { - guard let overlay else { return } - - guard !views.isEmpty else { - return - } - - views.removeFirst() - - if let first = views.first { - guard - let rootViewController = overlay.rootViewController - else { - return - } - rootViewController.view.subviews.forEach { view in - view.removeFromSuperview() - } - rootViewController.view.addSubview(first) - } else { - overlay.isHidden = true - overlay.isUserInteractionEnabled = false - overlay.rootViewController = nil - } + + @MainActor func dismiss() { + rootVC?.dismiss(animated: false) } } diff --git a/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayModifier.swift b/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayModifier.swift index 7c98f1467..73e8170a3 100644 --- a/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayModifier.swift +++ b/Flipper/Packages/UI/Sources/InAppNotifications/Overlay/OverlayModifier.swift @@ -6,21 +6,13 @@ struct OverlayModifier: ViewModifier { @EnvironmentObject private var controller: OverlayController - init( - isPresented: Binding, - @ViewBuilder overlayContent: @escaping () -> OverlayContent - ) { - self.isPresented = isPresented - self.overlayContent = overlayContent - } - func body(content: Content) -> some View { content - // NOTE: can't use controller.dismiss here as the isPresented - // change doesn't fire when containing view was dismissed .onChange(of: isPresented.wrappedValue) { newValue in if newValue { controller.present(content: overlayContent) + } else { + controller.dismiss() } } } diff --git a/Flipper/Packages/UI/Sources/InAppNotifications/Views/AlertView.swift b/Flipper/Packages/UI/Sources/InAppNotifications/Views/AlertView.swift index 56a2d4853..3c5b37786 100644 --- a/Flipper/Packages/UI/Sources/InAppNotifications/Views/AlertView.swift +++ b/Flipper/Packages/UI/Sources/InAppNotifications/Views/AlertView.swift @@ -5,9 +5,6 @@ struct AlertView: View { let content: Content @State private var isPresentedAnimated: Bool = false - - @EnvironmentObject private var controller: OverlayController - var animationDuration: Double { 0.1 } var body: some View { @@ -62,7 +59,6 @@ struct AlertView: View { isPresentedAnimated = false } try? await Task.sleep(seconds: animationDuration) - controller.dismiss() } } } diff --git a/Flipper/Packages/UI/Sources/InAppNotifications/Views/NotificationView.swift b/Flipper/Packages/UI/Sources/InAppNotifications/Views/NotificationView.swift index 6b47251f9..e2ec5e9da 100644 --- a/Flipper/Packages/UI/Sources/InAppNotifications/Views/NotificationView.swift +++ b/Flipper/Packages/UI/Sources/InAppNotifications/Views/NotificationView.swift @@ -6,8 +6,6 @@ struct NotificationView: View { @State private var isPresentedAnimated: Bool = false - @EnvironmentObject var controller: OverlayController - var animationDuration: Double { 0.1 } var presentingDuration: Double { 3.0 } @@ -42,7 +40,6 @@ struct NotificationView: View { isPresentedAnimated = false } try? await Task.sleep(seconds: animationDuration) - controller.dismiss() } } } diff --git a/Flipper/Packages/UI/Sources/InAppNotifications/Views/PopupView.swift b/Flipper/Packages/UI/Sources/InAppNotifications/Views/PopupView.swift index ded3162a2..75d19266f 100644 --- a/Flipper/Packages/UI/Sources/InAppNotifications/Views/PopupView.swift +++ b/Flipper/Packages/UI/Sources/InAppNotifications/Views/PopupView.swift @@ -6,8 +6,6 @@ struct PopupView: View { @State private var isPresentedAnimated: Bool = false - @EnvironmentObject var controller: OverlayController - var animationDuration: Double { 0.1 } var body: some View { @@ -43,7 +41,6 @@ struct PopupView: View { isPresentedAnimated = false } try? await Task.sleep(seconds: animationDuration) - controller.dismiss() } } }