summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2023-03-30 10:29:38 +0200
committerAndrej Mihajlov <and@mullvad.net>2023-03-30 10:29:38 +0200
commit46de2e1dd307d44ce117f4803c118a13ebbf3375 (patch)
tree429585991d4c701658b5ebea243288964fe69c3c
parent6a884cefdb78fa7cb34f51f2605a356b0db3e97f (diff)
parentdd7e0ed70f16744bf0570d672c9074e40b32de85 (diff)
downloadmullvadvpn-46de2e1dd307d44ce117f4803c118a13ebbf3375.tar.xz
mullvadvpn-46de2e1dd307d44ce117f4803c118a13ebbf3375.zip
Merge branch 'safari-coordinator'
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj4
-rw-r--r--ios/MullvadVPN/Coordinators/App/ApplicationCoordinator.swift4
-rw-r--r--ios/MullvadVPN/Coordinators/App/SafariCoordinator.swift39
-rw-r--r--ios/MullvadVPN/Coordinators/App/SettingsCoordinator.swift72
-rw-r--r--ios/MullvadVPN/Coordinators/App/TermsOfServiceCoordinator.swift12
-rw-r--r--ios/MullvadVPN/View controllers/TermsOfService/TermsOfServiceViewController.swift28
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?()
}
}