summaryrefslogtreecommitdiffhomepage
path: root/ios/MullvadVPN
diff options
context:
space:
mode:
authorJon Petersson <jon.petersson@mullvad.net>2025-10-24 08:13:18 +0200
committerJon Petersson <jon.petersson@mullvad.net>2025-10-24 08:13:18 +0200
commit3fd0813021ce79818d39996ff089dfb8a5697ad4 (patch)
tree289ecb097e4eca02b78bbecfb72d93215c173873 /ios/MullvadVPN
parent63e9eb92c6e7a1aee6b682ed885d10a6f6fc699c (diff)
parente1f357ea3b261265dca2ce0712b265f632079c37 (diff)
downloadmullvadvpn-3fd0813021ce79818d39996ff089dfb8a5697ad4.tar.xz
mullvadvpn-3fd0813021ce79818d39996ff089dfb8a5697ad4.zip
Merge branch 'fetch-current-location-asynchronously-upon-first-start-of-ios-1328'
Diffstat (limited to 'ios/MullvadVPN')
-rw-r--r--ios/MullvadVPN/AppDelegate.swift45
-rw-r--r--ios/MullvadVPN/Classes/AppPreferences.swift14
-rw-r--r--ios/MullvadVPN/Classes/FirstTimeLaunch.swift21
-rw-r--r--ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift1
-rw-r--r--ios/MullvadVPN/Protocols/URLSessionProtocol.swift15
5 files changed, 55 insertions, 41 deletions
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 4871b07e5a..1072b57a6e 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -48,7 +48,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
private var migrationManager: MigrationManager!
nonisolated(unsafe) private(set) var accessMethodRepository = AccessMethodRepository()
- private(set) var appPreferences = AppPreferences()
+ nonisolated(unsafe) private(set) var appPreferences = AppPreferences()
private(set) var shadowsocksLoader: ShadowsocksLoader!
private(set) var ipOverrideRepository = IPOverrideRepository()
private(set) var relaySelector: RelaySelectorWrapper!
@@ -491,16 +491,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
private func startInitialization(application: UIApplication) {
let wipeSettingsOperation = getWipeSettingsOperation()
+ let defaultLocationOperation = getDefaultLocationOperation()
let loadTunnelStoreOperation = getLoadTunnelStoreOperation()
let migrateSettingsOperation = getMigrateSettingsOperation(application: application)
let initTunnelManagerOperation = getInitTunnelManagerOperation()
+ defaultLocationOperation.addDependency(wipeSettingsOperation)
migrateSettingsOperation.addDependencies([wipeSettingsOperation, loadTunnelStoreOperation])
initTunnelManagerOperation.addDependency(migrateSettingsOperation)
operationQueue.addOperations(
[
wipeSettingsOperation,
+ defaultLocationOperation,
loadTunnelStoreOperation,
migrateSettingsOperation,
initTunnelManagerOperation,
@@ -593,8 +596,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
/// compatible, thus triggering a settings wipe.
private func getWipeSettingsOperation() -> AsyncBlockOperation {
AsyncBlockOperation {
- let appHasNeverBeenLaunched = !FirstTimeLaunch.hasFinished && !SettingsManager.getShouldWipeSettings()
- let appWasLaunchedAfterReinstall = !FirstTimeLaunch.hasFinished && SettingsManager.getShouldWipeSettings()
+ let appHasNeverBeenLaunched =
+ !self.appPreferences.hasDoneFirstTimeLaunch && !SettingsManager.getShouldWipeSettings()
+ let appWasLaunchedAfterReinstall =
+ !self.appPreferences.hasDoneFirstTimeLaunch && SettingsManager.getShouldWipeSettings()
if appHasNeverBeenLaunched {
try? SettingsManager.writeSettings(LatestTunnelSettings())
@@ -622,11 +627,43 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
try? self.relayCacheTracker.refreshCachedRelays()
}
- FirstTimeLaunch.setHasFinished()
SettingsManager.setShouldWipeSettings()
}
}
+ private func getDefaultLocationOperation() -> AsyncBlockOperation {
+ AsyncBlockOperation {
+ guard !self.appPreferences.hasDoneFirstTimeLaunch else {
+ return
+ }
+ self.appPreferences.hasDoneFirstTimeLaunch = true
+
+ // No need to keep the handle since we're not waiting or cancelling the completion anyway.
+ _ = self.relayCacheTracker.updateRelays { _ in
+ Task {
+ guard let cachedRelays = try? self.relayCacheTracker.getCachedRelays() else {
+ return
+ }
+
+ let locationService = DefaultLocationService(
+ urlSession: URLSession.shared, relayCache: cachedRelays)
+ let locationIdentifier = try? await locationService.fetchCurrentLocationIdentifier()
+
+ let constraint = RelayConstraint.only(
+ UserSelectedRelays(
+ locations: [.country(locationIdentifier?.country ?? "se")]
+ ))
+
+ if !self.appPreferences.hasDoneFirstTimeLogin {
+ self.tunnelManager.updateSettings([
+ .relayConstraints(RelayConstraints(entryLocations: constraint, exitLocations: constraint))
+ ])
+ }
+ }
+ }
+ }
+ }
+
// MARK: - StorePaymentManagerDelegate
nonisolated func storePaymentManager(
diff --git a/ios/MullvadVPN/Classes/AppPreferences.swift b/ios/MullvadVPN/Classes/AppPreferences.swift
index 31778ee742..103f17766a 100644
--- a/ios/MullvadVPN/Classes/AppPreferences.swift
+++ b/ios/MullvadVPN/Classes/AppPreferences.swift
@@ -10,16 +10,28 @@ import Foundation
import MullvadSettings
protocol AppPreferencesDataSource {
+ var hasDoneFirstTimeLaunch: Bool { get set }
+ var hasDoneFirstTimeLogin: Bool { get set }
var isShownOnboarding: Bool { get set }
var isAgreedToTermsOfService: Bool { get set }
var lastSeenChangeLogVersion: String { get set }
}
enum AppStorageKey: String {
- case isShownOnboarding, isAgreedToTermsOfService, lastSeenChangeLogVersion
+ case hasDoneFirstTimeLaunch = "hasFinishedFirstTimeLaunch"
+ case hasDoneFirstTimeLogin
+ case isShownOnboarding
+ case isAgreedToTermsOfService
+ case lastSeenChangeLogVersion
}
final class AppPreferences: AppPreferencesDataSource {
+ @AppStorage(key: AppStorageKey.hasDoneFirstTimeLaunch.rawValue, container: .standard)
+ var hasDoneFirstTimeLaunch: Bool = false
+
+ @AppStorage(key: AppStorageKey.hasDoneFirstTimeLogin.rawValue, container: .standard)
+ var hasDoneFirstTimeLogin: Bool = false
+
@AppStorage(key: AppStorageKey.isShownOnboarding.rawValue, container: .standard)
var isShownOnboarding = true
diff --git a/ios/MullvadVPN/Classes/FirstTimeLaunch.swift b/ios/MullvadVPN/Classes/FirstTimeLaunch.swift
deleted file mode 100644
index d7ee4ec5fa..0000000000
--- a/ios/MullvadVPN/Classes/FirstTimeLaunch.swift
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// FirstTimeLaunch.swift
-// MullvadVPN
-//
-// Created by Jon Petersson on 2023-04-04.
-// Copyright © 2025 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-enum FirstTimeLaunch {
- private static let userDefaultsKey = "hasFinishedFirstTimeLaunch"
-
- static var hasFinished: Bool {
- UserDefaults.standard.bool(forKey: userDefaultsKey)
- }
-
- static func setHasFinished() {
- UserDefaults.standard.set(true, forKey: userDefaultsKey)
- }
-}
diff --git a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
index e7121b28ef..f135633a3e 100644
--- a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
@@ -466,6 +466,7 @@ final class ApplicationCoordinator: Coordinator, Presenting, @preconcurrency Roo
coordinator.preferredAccountNumberPublisher = preferredAccountNumberSubject.eraseToAnyPublisher()
coordinator.didFinish = { [weak self] _ in
+ self?.appPreferences.hasDoneFirstTimeLogin = true
self?.continueFlow(animated: true)
}
coordinator.didCreateAccount = { [weak self] in
diff --git a/ios/MullvadVPN/Protocols/URLSessionProtocol.swift b/ios/MullvadVPN/Protocols/URLSessionProtocol.swift
deleted file mode 100644
index b3ca239120..0000000000
--- a/ios/MullvadVPN/Protocols/URLSessionProtocol.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// URLSessionProtocol.swift
-// MullvadVPN
-//
-// Created by Jon Petersson on 2023-11-16.
-// Copyright © 2025 Mullvad VPN AB. All rights reserved.
-//
-
-import Foundation
-
-protocol URLSessionProtocol {
- func data(for request: URLRequest) async throws -> (Data, URLResponse)
-}
-
-extension URLSession: URLSessionProtocol {}