diff options
| author | Jon Petersson <jon.petersson@kvadrat.se> | 2024-06-03 08:35:15 +0200 |
|---|---|---|
| committer | Jon Petersson <jon.petersson@kvadrat.se> | 2024-07-01 08:25:35 +0200 |
| commit | 3173eb528d8f4de5671d6fd47ee9adbf8b0a4df8 (patch) | |
| tree | aa1b62fb50b24157dd40fc7ea9285b93fe6e930f | |
| parent | 71d3cfa59f80dbe51b987f23b84a4a13a9eb01f5 (diff) | |
| download | mullvadvpn-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.swift | 160 | ||||
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 84 | ||||
| -rw-r--r-- | ios/MullvadVPN/Coordinators/Settings/SettingsCoordinator.swift | 20 | ||||
| -rw-r--r-- | ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsView.swift | 167 | ||||
| -rw-r--r-- | ios/MullvadVPN/View controllers/Settings/SwiftUI/SettingsViewModel.swift | 11 | ||||
| -rwxr-xr-x | ios/build-wireguard-go.sh | 2 |
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 |
