summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJon Petersson <jon.petersson@kvadrat.se>2024-06-03 08:35:15 +0200
committerJon Petersson <jon.petersson@kvadrat.se>2024-07-01 08:25:35 +0200
commit3173eb528d8f4de5671d6fd47ee9adbf8b0a4df8 (patch)
treeaa1b62fb50b24157dd40fc7ea9285b93fe6e930f
parent71d3cfa59f80dbe51b987f23b84a4a13a9eb01f5 (diff)
downloadmullvadvpn-settings-swift-ui.tar.xz
mullvadvpn-settings-swift-ui.zip
Create a settings view in swift uisettings-swift-ui
-rw-r--r--ios/MullvadTypes/Duration.swift160
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj84
-rw-r--r--ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift20
-rw-r--r--ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsView.swift167
-rw-r--r--ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsViewModel.swift11
-rwxr-xr-xios/build-wireguard-go.sh2
6 files changed, 332 insertions, 112 deletions
diff --git a/ios/MullvadTypes/Duration.swift b/ios/MullvadTypes/Duration.swift
index a2d30c5249..c842597eee 100644
--- a/ios/MullvadTypes/Duration.swift
+++ b/ios/MullvadTypes/Duration.swift
@@ -11,83 +11,83 @@ import Foundation
/// Custom implementation of iOS native `Duration` (available from iOS16). Meant as a
/// drop-in replacement until the app supports iOS16. Ideally this whole file can
/// then be deleted without affecting the rest of the code base.
-@available(iOS, introduced: 14.0, obsoleted: 16.0, message: "Replace with native Duration type.")
-public struct Duration {
- private(set) var components: (seconds: Int64, attoseconds: Int64)
-
- public init(secondsComponent: Int64, attosecondsComponent: Int64 = 0) {
- components = (
- seconds: Int64(secondsComponent),
- attoseconds: Int64(attosecondsComponent)
- )
- }
-
- public static func milliseconds(_ milliseconds: Int) -> Duration {
- let subSeconds = milliseconds % 1000
- let seconds = (milliseconds - subSeconds) / 1000
-
- return Duration(
- secondsComponent: Int64(seconds),
- attosecondsComponent: Int64(subSeconds) * Int64(1e15)
- )
- }
-
- public static func seconds(_ seconds: Int) -> Duration {
- return Duration(secondsComponent: Int64(seconds))
- }
-
- public func logFormat() -> String {
- let timeInterval = timeInterval
-
- guard timeInterval >= 1 else {
- return "\(milliseconds)ms"
- }
-
- let trailingZeroesSuffix = ".00"
- var string = String(format: "%.2f", timeInterval)
-
- if string.hasSuffix(trailingZeroesSuffix) {
- string.removeLast(trailingZeroesSuffix.count)
- }
-
- return "\(string)s"
- }
-}
-
-extension Duration: DurationProtocol {
- public static var zero: Duration {
- return .seconds(0)
- }
-
- public static func / (lhs: Duration, rhs: Int) -> Duration {
- return .milliseconds(lhs.milliseconds / max(rhs, 1))
- }
-
- public static func * (lhs: Duration, rhs: Int) -> Duration {
- return .milliseconds(lhs.milliseconds.saturatingMultiplication(rhs))
- }
-
- public static func / (lhs: Duration, rhs: Duration) -> Double {
- guard rhs != .zero else {
- return lhs.timeInterval
- }
-
- return lhs.timeInterval / rhs.timeInterval
- }
-
- public static func + (lhs: Duration, rhs: Duration) -> Duration {
- return .milliseconds(lhs.milliseconds.saturatingAddition(rhs.milliseconds))
- }
-
- public static func - (lhs: Duration, rhs: Duration) -> Duration {
- return .milliseconds(lhs.milliseconds.saturatingSubtraction(rhs.milliseconds))
- }
-
- public static func < (lhs: Duration, rhs: Duration) -> Bool {
- return lhs.timeInterval < rhs.timeInterval
- }
-
- public static func == (lhs: Duration, rhs: Duration) -> Bool {
- return lhs.timeInterval == rhs.timeInterval
- }
-}
+//@available(iOS, introduced: 14.0, obsoleted: 16.0, message: "Replace with native Duration type.")
+//public struct Duration {
+// private(set) var components: (seconds: Int64, attoseconds: Int64)
+//
+// public init(secondsComponent: Int64, attosecondsComponent: Int64 = 0) {
+// components = (
+// seconds: Int64(secondsComponent),
+// attoseconds: Int64(attosecondsComponent)
+// )
+// }
+//
+// public static func milliseconds(_ milliseconds: Int) -> Duration {
+// let subSeconds = milliseconds % 1000
+// let seconds = (milliseconds - subSeconds) / 1000
+//
+// return Duration(
+// secondsComponent: Int64(seconds),
+// attosecondsComponent: Int64(subSeconds) * Int64(1e15)
+// )
+// }
+//
+// public static func seconds(_ seconds: Int) -> Duration {
+// return Duration(secondsComponent: Int64(seconds))
+// }
+//
+// public func logFormat() -> String {
+// let timeInterval = timeInterval
+//
+// guard timeInterval >= 1 else {
+// return "\(milliseconds)ms"
+// }
+//
+// let trailingZeroesSuffix = ".00"
+// var string = String(format: "%.2f", timeInterval)
+//
+// if string.hasSuffix(trailingZeroesSuffix) {
+// string.removeLast(trailingZeroesSuffix.count)
+// }
+//
+// return "\(string)s"
+// }
+//}
+//
+//extension Duration: DurationProtocol {
+// public static var zero: Duration {
+// return .seconds(0)
+// }
+//
+// public static func / (lhs: Duration, rhs: Int) -> Duration {
+// return .milliseconds(lhs.milliseconds / max(rhs, 1))
+// }
+//
+// public static func * (lhs: Duration, rhs: Int) -> Duration {
+// return .milliseconds(lhs.milliseconds.saturatingMultiplication(rhs))
+// }
+//
+// public static func / (lhs: Duration, rhs: Duration) -> Double {
+// guard rhs != .zero else {
+// return lhs.timeInterval
+// }
+//
+// return lhs.timeInterval / rhs.timeInterval
+// }
+//
+// public static func + (lhs: Duration, rhs: Duration) -> Duration {
+// return .milliseconds(lhs.milliseconds.saturatingAddition(rhs.milliseconds))
+// }
+//
+// public static func - (lhs: Duration, rhs: Duration) -> Duration {
+// return .milliseconds(lhs.milliseconds.saturatingSubtraction(rhs.milliseconds))
+// }
+//
+// public static func < (lhs: Duration, rhs: Duration) -> Bool {
+// return lhs.timeInterval < rhs.timeInterval
+// }
+//
+// public static func == (lhs: Duration, rhs: Duration) -> Bool {
+// return lhs.timeInterval == rhs.timeInterval
+// }
+//}
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index 8e0a798948..07d41d26d2 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -499,6 +499,8 @@
7A3FD1B72AD54ABD0042BEA6 /* AnyTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BDEB982A98F4ED00F578F2 /* AnyTransport.swift */; };
7A3FD1B82AD54AE60042BEA6 /* TimeServerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BDEB9A2A98F58600F578F2 /* TimeServerProxy.swift */; };
7A42DEC92A05164100B209BE /* SettingsInputCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A42DEC82A05164100B209BE /* SettingsInputCell.swift */; };
+ 7A50EDB02C09B4EE00510246 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A50EDAF2C09B4EE00510246 /* SettingsView.swift */; };
+ 7A50EDB32C09B54F00510246 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A50EDB22C09B54F00510246 /* SettingsViewModel.swift */; };
7A516C2E2B6D357500BBD33D /* URL+Scoping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */; };
7A516C3A2B7111A700BBD33D /* IPOverrideWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */; };
7A516C3C2B712F0B00BBD33D /* IPOverrideWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */; };
@@ -1844,6 +1846,8 @@
7A3353962AAA0F8600F0A71C /* OperationBlockObserverSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationBlockObserverSupport.swift; sourceTree = "<group>"; };
7A3FD1B42AD4465A0042BEA6 /* AppMessageHandlerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageHandlerTests.swift; sourceTree = "<group>"; };
7A42DEC82A05164100B209BE /* SettingsInputCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInputCell.swift; sourceTree = "<group>"; };
+ 7A50EDAF2C09B4EE00510246 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
+ 7A50EDB22C09B54F00510246 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Scoping.swift"; sourceTree = "<group>"; };
7A516C392B7111A700BBD33D /* IPOverrideWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideWrapper.swift; sourceTree = "<group>"; };
7A516C3B2B712F0B00BBD33D /* IPOverrideWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPOverrideWrapperTests.swift; sourceTree = "<group>"; };
@@ -2767,6 +2771,7 @@
583FE01829C19709006E85F9 /* Settings */ = {
isa = PBXGroup;
children = (
+ 7A50EDB12C09B53100510246 /* SwiftUI */,
7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */,
7A1A264A2A29D65E00B978AA /* SelectableSettingsCell.swift */,
5819C2162729595500D6EC38 /* SettingsAddDNSEntryCell.swift */,
@@ -3780,6 +3785,15 @@
path = Alert;
sourceTree = "<group>";
};
+ 7A50EDB12C09B53100510246 /* SwiftUI */ = {
+ isa = PBXGroup;
+ children = (
+ 7A50EDAF2C09B4EE00510246 /* SettingsView.swift */,
+ 7A50EDB22C09B54F00510246 /* SettingsViewModel.swift */,
+ );
+ path = SwiftUI;
+ sourceTree = "<group>";
+ };
7A5869A92B55516700640D27 /* IPOverride */ = {
isa = PBXGroup;
children = (
@@ -5606,6 +5620,7 @@
586C0D8F2B03D88100E7CDD7 /* ProxyProtocolConfigurationItemIdentifier.swift in Sources */,
588527B2276B3F0700BAA373 /* LoadTunnelConfigurationOperation.swift in Sources */,
58DFF7D22B0256A300F864E0 /* MarkdownStylingOptions.swift in Sources */,
+ 7A50EDB32C09B54F00510246 /* SettingsViewModel.swift in Sources */,
5867770E29096984006F721F /* OutOfTimeInteractor.swift in Sources */,
F03580252A13842C00E5DAFD /* IncreasedHitButton.swift in Sources */,
5827B0BD2B14AC9200CCBBA1 /* AccessViewModel+TestingStatus.swift in Sources */,
@@ -5890,6 +5905,7 @@
58ACF64B26553C3F00ACE4B7 /* SettingsSwitchCell.swift in Sources */,
7AF9BE952A40461100DBFEDB /* RelayFilterView.swift in Sources */,
7A09C98129D99215000C2CAC /* String+FuzzyMatch.swift in Sources */,
+ 7A50EDB02C09B4EE00510246 /* SettingsView.swift in Sources */,
5827B0C52B14D3E800CCBBA1 /* NSDiffableDataSourceSnapshot+Reconfigure.swift in Sources */,
58A8EE5E2976DB00009C0F8D /* StorePaymentManagerError+Display.swift in Sources */,
58A8EE5A2976BFBB009C0F8D /* SKError+Localized.swift in Sources */,
@@ -6883,7 +6899,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -6940,7 +6956,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
@@ -6960,6 +6976,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "MullvadVPN/Supporting Files/MullvadVPN.entitlements";
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "MullvadVPN/Supporting Files/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -6968,6 +6987,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = minimal;
SWIFT_VERSION = 5.0;
@@ -7001,6 +7021,9 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnel.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = PacketTunnel/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -7010,6 +7033,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).PacketTunnel";
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = minimal;
SWIFT_VERSION = 5.0;
@@ -7446,7 +7470,7 @@
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.MullvadVPN.RoutingTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -7472,7 +7496,7 @@
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.MullvadVPN.RoutingTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -7610,7 +7634,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -7630,8 +7654,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "MullvadVPN/Supporting Files/MullvadVPN.entitlements";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "MullvadVPN/Supporting Files/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -7640,7 +7665,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER)";
PRODUCT_NAME = "$(TARGET_NAME)";
- "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Mullvad VPN Development";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = minimal;
SWIFT_VERSION = 5.0;
@@ -7668,8 +7693,9 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnel.entitlements;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = PacketTunnel/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -7679,7 +7705,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).PacketTunnel";
PRODUCT_NAME = "$(TARGET_NAME)";
- "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Packet Tunnel Development";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = minimal;
SWIFT_VERSION = 5.0;
@@ -8121,7 +8147,7 @@
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.MullvadVPN.RoutingTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -8203,7 +8229,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -8254,7 +8280,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -8306,7 +8332,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -8357,7 +8383,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -8430,7 +8456,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
@@ -8450,8 +8476,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "MullvadVPN/Supporting Files/MullvadVPN.entitlements";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "MullvadVPN/Supporting Files/Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
@@ -8460,7 +8487,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER)";
PRODUCT_NAME = "$(TARGET_NAME)";
- "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Mullvad VPN Development";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_STRICT_CONCURRENCY = minimal;
SWIFT_VERSION = 5.0;
};
@@ -8484,8 +8511,9 @@
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnel.entitlements;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- "DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = CKG9MXH72F;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = PacketTunnel/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@@ -8495,7 +8523,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).PacketTunnel";
PRODUCT_NAME = "$(TARGET_NAME)";
- "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Packet Tunnel Development";
+ PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_STRICT_CONCURRENCY = minimal;
SWIFT_VERSION = 5.0;
};
@@ -8932,7 +8960,7 @@
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = CKG9MXH72F;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = net.mullvad.MullvadVPN.RoutingTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -8968,7 +8996,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -9017,7 +9045,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -9066,7 +9094,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -9116,7 +9144,7 @@
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Mullvad VPN AB. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
- IPHONEOS_DEPLOYMENT_TARGET = 14.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
diff --git a/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift b/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift
index c9a44223ff..4a8d8d6c76 100644
--- a/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift
@@ -11,6 +11,7 @@ import MullvadSettings
import Operations
import Routing
import UIKit
+import SwiftUI
/// Settings navigation route.
enum SettingsNavigationRoute: Equatable {
@@ -82,10 +83,21 @@ final class SettingsCoordinator: Coordinator, Presentable, Presenting, SettingsV
navigationController.navigationBar.prefersLargeTitles = true
navigationController.delegate = self
- push(from: makeChild(for: .root), animated: false)
- if let initialRoute, initialRoute != .root {
- push(from: makeChild(for: initialRoute), animated: false)
- }
+ let hostingViewController = UIHostingController(rootView: SettingsView(
+ viewModel: SettingsViewModel(sections: [
+ SettingsSection(items: [.vpnSettings, .apiAccess]),
+ SettingsSection(items: [.version])
+ ])
+ ))
+// hostingViewController.view.backgroundColor = .secondaryColor
+// hostingViewController.modalPresentationStyle = .overFullScreen
+// hostingViewController.modalTransitionStyle = .crossDissolve
+ navigationController.pushViewController(hostingViewController, animated: true)
+
+// push(from: makeChild(for: .root), animated: false)
+// if let initialRoute, initialRoute != .root {
+// push(from: makeChild(for: initialRoute), animated: false)
+// }
}
// MARK: - Navigation
diff --git a/ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsView.swift b/ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsView.swift
new file mode 100644
index 0000000000..c4336c0ed0
--- /dev/null
+++ b/ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsView.swift
@@ -0,0 +1,167 @@
+//
+// SettingsView.swift
+// MullvadVPN
+//
+// Created by Jon Petersson on 2024-05-31.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import SwiftUI
+import UIKit
+
+// enum SettingsSection: String, Identifiable {
+// case main
+// case version
+// case problemReport
+//
+// var id: Self {
+// self
+// }
+// }
+
+struct SettingsSection: Identifiable {
+ let id = UUID()
+ let items: [SettingsItem]
+}
+
+struct SettingsViewModel {
+ let sections: [SettingsSection]
+}
+
+struct SettingsRowViewModel: Identifiable {
+ let id = UUID()
+ let item: SettingsItem
+}
+
+enum SettingsItem: String, CaseIterable, Identifiable {
+ case vpnSettings
+ case version
+ case problemReport
+ case faq
+ case apiAccess
+
+ var id: Self {
+ self
+ }
+
+ var title: String {
+ switch self {
+ case .vpnSettings:
+ return "VPN settings"
+ case .version:
+ return "App version"
+ case .problemReport:
+ return "Report a problem"
+ case .faq:
+ return "FAQs & Guides"
+ case .apiAccess:
+ return "API access"
+ }
+ }
+
+ var accessibilityIdentifier: AccessibilityIdentifier {
+ switch self {
+ case .vpnSettings:
+ return .vpnSettingsCell
+ case .version:
+ return .versionCell
+ case .problemReport:
+ return .problemReportCell
+ case .faq:
+ return .faqCell
+ case .apiAccess:
+ return .apiAccessCell
+ }
+ }
+}
+
+struct SettingsView: View {
+ var viewModel: SettingsViewModel
+
+ init(viewModel: SettingsViewModel) {
+ self.viewModel = viewModel
+ UITableView.appearance().backgroundColor = .clear
+ }
+
+ var body: some View {
+ ZStack {
+ Color(.secondaryColor).ignoresSafeArea()
+ List {
+ ForEach(viewModel.sections) { section in
+ Section {
+ ForEach(section.items) { item in
+ SettingsRow(viewModel: SettingsRowViewModel(item: item))
+ .background(
+ NavigationLink(destination: Text("Hello, World!")) {}
+ .opacity(0)
+ )
+ .listRowSeparatorTint(Color(UIColor.separator))
+ .listRowBackground(Color(UIColor.primaryColor))
+ .listRowInsets(EdgeInsets(
+ top: 0,
+ leading: UIMetrics.TableView.cellIndentationWidth,
+ bottom: 0,
+ trailing: UIMetrics.TableView.cellIndentationWidth)
+ )
+ .frame(height: 54)
+ }
+ }
+// } header: {
+//// Color.red
+//// .listRowInsets(.init())
+//// .frame(height: 1)
+// Text("")
+//// .font(.callout)
+//// .listRowInsets(.init())
+// }
+ }
+ }
+ .listStyle(.plain)
+ .navigationTitle("Settings")
+ .environment(\.defaultMinListHeaderHeight, 1)
+ }
+ }
+}
+
+struct SettingsRow: View {
+ let viewModel: SettingsRowViewModel
+
+ var body: some View {
+ HStack {
+ Text(viewModel.item.title)
+ .foregroundStyle(.white)
+ Spacer()
+ Image(systemName: "chevron.right")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(width: 7)
+ .foregroundStyle(.white)
+ }
+ }
+}
+
+struct SettingsView_Previews: PreviewProvider {
+ static var previews: some View {
+ SettingsView(viewModel: SettingsViewModel(sections: [
+ SettingsSection(items: [.vpnSettings, .apiAccess]),
+ SettingsSection(items: [.problemReport])
+ ]))
+ }
+}
+
+struct SettingsRow_Previews: PreviewProvider {
+ static var previews: some View {
+ SettingsRow(viewModel: SettingsRowViewModel(item: .apiAccess))
+ .background(Color(UIColor.primaryColor))
+ }
+}
+
+private struct CustomTextFieldStyle: TextFieldStyle {
+ func _body(configuration: TextField<Self._Label>) -> some View {
+ configuration
+ .padding(EdgeInsets(top: 6, leading: 8, bottom: 6, trailing: 8))
+ .background(Color.white)
+ .cornerRadius(4)
+ .font(.system(size: 15))
+ }
+}
diff --git a/ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsViewModel.swift b/ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsViewModel.swift
new file mode 100644
index 0000000000..05f2974777
--- /dev/null
+++ b/ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsViewModel.swift
@@ -0,0 +1,11 @@
+//
+// SettingsViewModel.swift
+// MullvadVPN
+//
+// Created by Jon Petersson on 2024-05-31.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import Foundation
+
+
diff --git a/ios/build-wireguard-go.sh b/ios/build-wireguard-go.sh
index 60b3b00784..29e9ffe5d4 100755
--- a/ios/build-wireguard-go.sh
+++ b/ios/build-wireguard-go.sh
@@ -21,6 +21,8 @@ if [ "$SOURCE_PACKAGES_PATH" == "" ]; then
# When archiving, Xcode sets the action to "install"
if [ "$ACTION" == "install" ]; then
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../../../../SourcePackages"
+ elif [ "$ENABLE_PREVIEWS" == "YES" ]; then
+ SOURCE_PACKAGES_PATH="$BUILD_DIR/../../../../../../SourcePackages"
else
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../SourcePackages"
fi