diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2023-05-05 12:26:51 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2023-05-05 16:27:25 +0200 |
| commit | 3e381288839d3a5a4e57c149daa13e518c215a62 (patch) | |
| tree | 4c02c54a92a24dd24622ac75dee6432deb26ee70 | |
| parent | 1140b09f99add401916bd91bfafa5006a13b9c3e (diff) | |
| download | mullvadvpn-3e381288839d3a5a4e57c149daa13e518c215a62.tar.xz mullvadvpn-3e381288839d3a5a4e57c149daa13e518c215a62.zip | |
Add notification controller into root container
4 files changed, 76 insertions, 31 deletions
diff --git a/ios/MullvadVPN/Containers/Root/RootContainerViewController.swift b/ios/MullvadVPN/Containers/Root/RootContainerViewController.swift index b1f742b982..1577c93020 100644 --- a/ios/MullvadVPN/Containers/Root/RootContainerViewController.swift +++ b/ios/MullvadVPN/Containers/Root/RootContainerViewController.swift @@ -707,6 +707,62 @@ class RootContainerViewController: UIViewController { // Tell accessibility that the significant part of screen was changed. UIAccessibility.post(notification: .screenChanged, argument: nil) } + + // MARK: - Notification controller support + + /** + An instance of notification controller presented within container. + */ + var notificationController: NotificationController? { + didSet { + guard oldValue != notificationController else { return } + + oldValue.flatMap { removeNotificationController($0) } + notificationController.flatMap { addNotificationController($0) } + } + } + + /** + Layout guide for notification view. + + When set, notification view follows the layout guide that defines its dimensions and position, otherwise it's + laid out within container's safe area. + */ + var notificationViewLayoutGuide: UILayoutGuide? { + didSet { + notificationController.flatMap { updateNotificationViewConstraints($0) } + } + } + + private var notificationViewConstraints: [NSLayoutConstraint] = [] + + private func updateNotificationViewConstraints(_ notificationController: NotificationController) { + let newConstraints = notificationController.view + .pinEdgesTo(notificationViewLayoutGuide ?? view.safeAreaLayoutGuide) + + NSLayoutConstraint.deactivate(notificationViewConstraints) + NSLayoutConstraint.activate(newConstraints) + + notificationViewConstraints = newConstraints + } + + private func addNotificationController(_ notificationController: NotificationController) { + guard let notificationView = notificationController.view else { return } + + notificationView.configureForAutoLayout() + + addChild(notificationController) + view.addSubview(notificationView) + notificationController.didMove(toParent: self) + + updateNotificationViewConstraints(notificationController) + } + + private func removeNotificationController(_ notificationController: NotificationController) { + notificationController.willMove(toParent: nil) + notificationController.view.removeFromSuperview() + notificationController.removeFromParent() + } } /// A UIViewController extension that gives view controllers an access to root container diff --git a/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift b/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift index 4b3816b630..7bdff9081a 100644 --- a/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift @@ -20,7 +20,7 @@ private let preferredFormSheetContentSize = CGSize(width: 480, height: 640) Application coordinator managing split view and two navigation contexts. */ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewControllerDelegate, - UISplitViewControllerDelegate, ApplicationRouterDelegate + UISplitViewControllerDelegate, ApplicationRouterDelegate, NotificationManagerDelegate { /** Application router. @@ -52,6 +52,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo transitioningDelegate: SecondaryContextTransitioningDelegate() ) + private let notificationController = NotificationController() + private let splitViewController: CustomSplitViewController = { let svc = CustomSplitViewController() svc.minimumPrimaryColumnWidth = UIMetrics.minimumSplitViewSidebarWidth @@ -104,6 +106,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo router = ApplicationRouter(self) addTunnelObserver() + + NotificationManager.shared.delegate = self } func start() { @@ -111,6 +115,8 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo setupSplitView() } + primaryNavigationContainer.notificationController = notificationController + continueFlow(animated: false) } @@ -384,6 +390,9 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo primaryNavigationContainer.setViewControllers([splitViewController], animated: false) + primaryNavigationContainer.notificationViewLayoutGuide = tunnelCoordinator.rootViewController.view + .safeAreaLayoutGuide + tunnelCoordinator.start() selectLocationCoordinator.start() } @@ -790,6 +799,15 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo return true } + // MARK: - NotificationManagerDelegate + + func notificationManagerDidUpdateInAppNotifications( + _ manager: NotificationManager, + notifications: [InAppNotificationDescriptor] + ) { + notificationController.setNotifications(notifications, animated: true) + } + // MARK: - Presenting var presentationContext: UIViewController { diff --git a/ios/MullvadVPN/Coordinators/App/TunnelCoordinator.swift b/ios/MullvadVPN/Coordinators/App/TunnelCoordinator.swift index c63b0f80ef..bd35d79558 100644 --- a/ios/MullvadVPN/Coordinators/App/TunnelCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/App/TunnelCoordinator.swift @@ -8,7 +8,7 @@ import UIKit -class TunnelCoordinator: Coordinator, NotificationManagerDelegate { +class TunnelCoordinator: Coordinator { private let tunnelManager: TunnelManager private let controller: TunnelViewController @@ -44,8 +44,6 @@ class TunnelCoordinator: Coordinator, NotificationManagerDelegate { tunnelManager.addObserver(tunnelObserver) updateVisibility(animated: false) - - NotificationManager.shared.delegate = self } private func updateVisibility(animated: Bool) { @@ -53,13 +51,4 @@ class TunnelCoordinator: Coordinator, NotificationManagerDelegate { controller.setMainContentHidden(!deviceState.isLoggedIn, animated: animated) } - - // MARK: - NotificationManagerDelegate - - func notificationManagerDidUpdateInAppNotifications( - _ manager: NotificationManager, - notifications: [InAppNotificationDescriptor] - ) { - controller.notificationController.setNotifications(notifications, animated: true) - } } diff --git a/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift b/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift index 4ec24fd400..8f6cc10a18 100644 --- a/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift +++ b/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift @@ -20,7 +20,6 @@ class TunnelViewController: UIViewController, RootContainment { var shouldShowSelectLocationPicker: (() -> Void)? - let notificationController = NotificationController() private let mapViewController = MapViewController() override var preferredStatusBarStyle: UIStatusBarStyle { @@ -82,7 +81,6 @@ class TunnelViewController: UIViewController, RootContainment { addMapController() addContentView() - addNotificationController() tunnelState = interactor.tunnelStatus.state updateContentView(animated: false) @@ -180,22 +178,6 @@ class TunnelViewController: UIViewController, RootContainment { ]) } - private func addNotificationController() { - let notificationView = notificationController.view! - notificationView.translatesAutoresizingMaskIntoConstraints = false - - addChild(notificationController) - view.addSubview(notificationView) - notificationController.didMove(toParent: self) - - NSLayoutConstraint.activate([ - notificationView.topAnchor.constraint(equalTo: view.topAnchor), - notificationView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - notificationView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - notificationView.bottomAnchor.constraint(equalTo: view.bottomAnchor), - ]) - } - private func addContentView() { contentView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(contentView) |
