diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2023-03-30 10:29:38 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2023-03-30 10:29:38 +0200 |
| commit | 46de2e1dd307d44ce117f4803c118a13ebbf3375 (patch) | |
| tree | 429585991d4c701658b5ebea243288964fe69c3c | |
| parent | 6a884cefdb78fa7cb34f51f2605a356b0db3e97f (diff) | |
| parent | dd7e0ed70f16744bf0570d672c9074e40b32de85 (diff) | |
| download | mullvadvpn-46de2e1dd307d44ce117f4803c118a13ebbf3375.tar.xz mullvadvpn-46de2e1dd307d44ce117f4803c118a13ebbf3375.zip | |
Merge branch 'safari-coordinator'
6 files changed, 100 insertions, 59 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 00ea634a9d..622cfc0fc5 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -132,6 +132,7 @@ 5867771429097BCD006F721F /* PaymentState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5867771329097BCD006F721F /* PaymentState.swift */; }; 5867771629097C5B006F721F /* ProductState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5867771529097C5B006F721F /* ProductState.swift */; }; 5868585524054096000B8131 /* AppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5868585424054096000B8131 /* AppButton.swift */; }; + 586891CD29D452E4002A8278 /* SafariCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 586891CC29D452E4002A8278 /* SafariCoordinator.swift */; }; 586A950C290125EE007BAF2B /* AlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58B9EB122488ED2100095626 /* AlertPresenter.swift */; }; 586A950D290125F0007BAF2B /* PresentAlertOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5820675D26E6839900655B05 /* PresentAlertOperation.swift */; }; 586A950E290125F3007BAF2B /* ProductsRequestOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846226426E0D9630035F7C2 /* ProductsRequestOperation.swift */; }; @@ -758,6 +759,7 @@ 5867771329097BCD006F721F /* PaymentState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentState.swift; sourceTree = "<group>"; }; 5867771529097C5B006F721F /* ProductState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductState.swift; sourceTree = "<group>"; }; 5868585424054096000B8131 /* AppButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppButton.swift; sourceTree = "<group>"; }; + 586891CC29D452E4002A8278 /* SafariCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariCoordinator.swift; sourceTree = "<group>"; }; 586A95112901321B007BAF2B /* IPv6Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPv6Endpoint.swift; sourceTree = "<group>"; }; 586A951329013235007BAF2B /* AnyIPEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPEndpoint.swift; sourceTree = "<group>"; }; 586E54FA27A2DF6D0029B88B /* SendTunnelProviderMessageOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTunnelProviderMessageOperation.swift; sourceTree = "<group>"; }; @@ -1601,6 +1603,7 @@ 5847D58C29B7740F008C3808 /* RevokedCoordinator.swift */, 583FE00D29C0D586006E85F9 /* OutOfTimeCoordinator.swift */, 5878F50129CDB989003D4BE2 /* ChangeLogCoordinator.swift */, + 586891CC29D452E4002A8278 /* SafariCoordinator.swift */, ); path = App; sourceTree = "<group>"; @@ -2725,6 +2728,7 @@ 5878A27329091D6D0096FC88 /* TunnelBlockObserver.swift in Sources */, 5872D6E8286304DE00DB5F4E /* TermsOfService.swift in Sources */, 58E0A98827C8F46300FE6BDD /* Tunnel.swift in Sources */, + 586891CD29D452E4002A8278 /* SafariCoordinator.swift in Sources */, 58ACF64F26567A7100ACE4B7 /* CustomSwitchContainer.swift in Sources */, 5857F24324C8662600CF6F47 /* SelectLocationHeaderView.swift in Sources */, 58EE2E3A272FF814003BFF93 /* SettingsDataSource.swift in Sources */, diff --git a/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift b/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift index ba03323d0d..4a745e385c 100644 --- a/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift @@ -569,9 +569,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo } } - coordinator.navigate(to: route ?? .root, animated: false) - - coordinator.start() + coordinator.start(initialRoute: route) presentChild( coordinator, diff --git a/ios/MullvadVPN/Coordinators/App/SafariCoordinator.swift b/ios/MullvadVPN/Coordinators/App/SafariCoordinator.swift new file mode 100644 index 0000000000..0d97bd6d3e --- /dev/null +++ b/ios/MullvadVPN/Coordinators/App/SafariCoordinator.swift @@ -0,0 +1,39 @@ +// +// SafariCoordinator.swift +// MullvadVPN +// +// Created by pronebird on 29/03/2023. +// Copyright © 2023 Mullvad VPN AB. All rights reserved. +// + +import Foundation +import SafariServices + +class SafariCoordinator: Coordinator, Presentable, SFSafariViewControllerDelegate { + var didFinish: (() -> Void)? + + var presentedViewController: UIViewController { + return safariController + } + + private let safariController: SFSafariViewController + + init(url: URL) { + safariController = SFSafariViewController(url: url) + super.init() + + safariController.delegate = self + } + + func safariViewControllerDidFinish(_ controller: SFSafariViewController) { + dismiss(animated: true) { + self.didFinish?() + } + } + + func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController) { + dismiss(animated: false) { + self.didFinish?() + } + } +} diff --git a/ios/MullvadVPN/Coordinators/App/SettingsCoordinator.swift b/ios/MullvadVPN/Coordinators/App/SettingsCoordinator.swift index 498a55b7bd..89fffaf2c7 100644 --- a/ios/MullvadVPN/Coordinators/App/SettingsCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/App/SettingsCoordinator.swift @@ -8,7 +8,6 @@ import MullvadLogging import Operations -import SafariServices import UIKit enum SettingsNavigationRoute: Equatable { @@ -24,13 +23,14 @@ enum SettingsDismissReason: Equatable { case userLoggedOut } -final class SettingsCoordinator: Coordinator, Presentable, SettingsViewControllerDelegate, - AccountViewControllerDelegate, UINavigationControllerDelegate, SFSafariViewControllerDelegate +final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsViewControllerDelegate, + AccountViewControllerDelegate, UINavigationControllerDelegate { private let logger = Logger(label: "SettingsNavigationCoordinator") private let interactorFactory: SettingsInteractorFactory private var currentRoute: SettingsNavigationRoute? + private var modalRoute: SettingsNavigationRoute? let navigationController: UINavigationController @@ -38,6 +38,10 @@ final class SettingsCoordinator: Coordinator, Presentable, SettingsViewControlle return navigationController } + var presentationContext: UIViewController { + return navigationController + } + var willNavigate: (( _ coordinator: SettingsCoordinator, _ from: SettingsNavigationRoute?, @@ -54,27 +58,46 @@ final class SettingsCoordinator: Coordinator, Presentable, SettingsViewControlle self.interactorFactory = interactorFactory } - func start() { + func start(initialRoute: SettingsNavigationRoute? = nil) { navigationController.navigationBar.prefersLargeTitles = true navigationController.delegate = self - navigationController.pushViewController(makeViewController(for: .root), animated: false) + + if let rootController = makeViewController(for: .root) { + navigationController.pushViewController(rootController, animated: false) + } + + if let initialRoute = initialRoute, initialRoute != .root, + let nextController = makeViewController(for: initialRoute) + { + navigationController.pushViewController(nextController, animated: false) + } } // MARK: - Navigation - func navigate( - to route: SettingsNavigationRoute, - animated: Bool, - completion: (() -> Void)? = nil - ) { + func navigate(to route: SettingsNavigationRoute, animated: Bool, completion: (() -> Void)? = nil) { switch route { case .root: navigationController.popToRootViewController(animated: animated) + completion?() case .faq: - let safariController = makeViewController(for: route) + guard modalRoute == nil else { + completion?() + return + } + + modalRoute = route + + logger.debug("Show modal \(route)") - navigationController.present(safariController, animated: true) + let safariCoordinator = SafariCoordinator(url: ApplicationConfiguration.faqAndGuidesURL) + + safariCoordinator.didFinish = { [weak self] in + self?.modalRoute = nil + } + + presentChild(safariCoordinator, animated: animated, completion: completion) default: let nextViewController = makeViewController(for: route) @@ -82,12 +105,14 @@ final class SettingsCoordinator: Coordinator, Presentable, SettingsViewControlle if let rootController = viewControllers.first, viewControllers.count > 1 { navigationController.setViewControllers( - [rootController, nextViewController], + [rootController, nextViewController].compactMap { $0 }, animated: animated ) - } else { + } else if let nextViewController = nextViewController { navigationController.pushViewController(nextViewController, animated: animated) } + + completion?() } } @@ -128,19 +153,9 @@ final class SettingsCoordinator: Coordinator, Presentable, SettingsViewControlle didFinish?(self, .userLoggedOut) } - // MARK: - SFSafariViewControllerDelegate - - func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController) { - controller.dismiss(animated: false) - } - - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - controller.dismiss(animated: true) - } - // MARK: - Route mapping - private func makeViewController(for route: SettingsNavigationRoute) -> UIViewController { + private func makeViewController(for route: SettingsNavigationRoute) -> UIViewController? { switch route { case .root: let controller = SettingsViewController( @@ -167,12 +182,7 @@ final class SettingsCoordinator: Coordinator, Presentable, SettingsViewControlle ) case .faq: - let safariController = SFSafariViewController( - url: ApplicationConfiguration - .faqAndGuidesURL - ) - safariController.delegate = self - return safariController + return nil } } diff --git a/ios/MullvadVPN/Coordinators/App/TermsOfServiceCoordinator.swift b/ios/MullvadVPN/Coordinators/App/TermsOfServiceCoordinator.swift index 61d0b8ff31..95cd9079dd 100644 --- a/ios/MullvadVPN/Coordinators/App/TermsOfServiceCoordinator.swift +++ b/ios/MullvadVPN/Coordinators/App/TermsOfServiceCoordinator.swift @@ -8,9 +8,13 @@ import UIKit -class TermsOfServiceCoordinator: Coordinator { +class TermsOfServiceCoordinator: Coordinator, Presenting { private let navigationController: RootContainerViewController + var presentationContext: UIViewController { + return navigationController + } + var didFinish: ((TermsOfServiceCoordinator) -> Void)? init(navigationController: RootContainerViewController) { @@ -20,7 +24,11 @@ class TermsOfServiceCoordinator: Coordinator { func start() { let controller = TermsOfServiceViewController() - controller.completionHandler = { [weak self] controller in + controller.showPrivacyPolicy = { [weak self] in + self?.presentChild(SafariCoordinator(url: ApplicationConfiguration.privacyPolicyURL), animated: true) + } + + controller.completionHandler = { [weak self] in guard let self = self else { return } TermsOfService.setAgreed() diff --git a/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceViewController.swift b/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceViewController.swift index 3dd909fa06..e9d7bfbc72 100644 --- a/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceViewController.swift +++ b/ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceViewController.swift @@ -6,13 +6,11 @@ // Copyright © 2020 Mullvad VPN AB. All rights reserved. // -import SafariServices import UIKit -class TermsOfServiceViewController: UIViewController, RootContainment, - SFSafariViewControllerDelegate -{ - var completionHandler: ((UIViewController) -> Void)? +class TermsOfServiceViewController: UIViewController, RootContainment { + var showPrivacyPolicy: (() -> Void)? + var completionHandler: (() -> Void)? override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent @@ -58,26 +56,10 @@ class TermsOfServiceViewController: UIViewController, RootContainment, // MARK: - Actions @objc private func handlePrivacyPolicyButton(_ sender: Any) { - let safariController = SFSafariViewController( - url: ApplicationConfiguration - .privacyPolicyURL - ) - safariController.delegate = self - - present(safariController, animated: true) + showPrivacyPolicy?() } @objc private func handleAgreeButton(_ sender: Any) { - completionHandler?(self) - } - - // MARK: - SFSafariViewControllerDelegate - - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - controller.dismiss(animated: true) - } - - func safariViewControllerWillOpenInBrowser(_ controller: SFSafariViewController) { - controller.dismiss(animated: false) + completionHandler?() } } |
