Skip to content

Commit

Permalink
Generalise WireGuardObfuscationSettings-based SwiftUI view model
Browse files Browse the repository at this point in the history
  • Loading branch information
acb-mv committed Nov 7, 2024
1 parent 7730da7 commit 02843c8
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 39 deletions.
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
06AC116228F94C450037AF9A /* ApplicationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */; };
44075DFB2CDA4F7400F61139 /* UDPTCPObfuscationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44075DFA2CDA4F7400F61139 /* UDPTCPObfuscationSettingsViewModel.swift */; };
440E5AB02CDBD67D00B09614 /* StatefulPreviewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 440E5AAF2CDBD67D00B09614 /* StatefulPreviewWrapper.swift */; };
440E5AB42CDCF24500B09614 /* TunnelObfuscationSettingsWatchingObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 440E5AB32CDCF24500B09614 /* TunnelObfuscationSettingsWatchingObservableObject.swift */; };
4422C0712CCFF6790001A385 /* UDPTCPObfuscationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4422C0702CCFF6790001A385 /* UDPTCPObfuscationSettingsView.swift */; };
4424CDD32CDBD4A6009D8C9F /* SingleChoiceList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4424CDD22CDBD4A6009D8C9F /* SingleChoiceList.swift */; };
449275422C3570CA000526DE /* ICMP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449275412C3570CA000526DE /* ICMP.swift */; };
Expand Down Expand Up @@ -1391,6 +1392,7 @@
06FAE67D28F83CA50033DD93 /* RESTTransport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RESTTransport.swift; sourceTree = "<group>"; };
44075DFA2CDA4F7400F61139 /* UDPTCPObfuscationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPTCPObfuscationSettingsViewModel.swift; sourceTree = "<group>"; };
440E5AAF2CDBD67D00B09614 /* StatefulPreviewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatefulPreviewWrapper.swift; sourceTree = "<group>"; };
440E5AB32CDCF24500B09614 /* TunnelObfuscationSettingsWatchingObservableObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelObfuscationSettingsWatchingObservableObject.swift; sourceTree = "<group>"; };
4422C0702CCFF6790001A385 /* UDPTCPObfuscationSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UDPTCPObfuscationSettingsView.swift; sourceTree = "<group>"; };
4424CDD22CDBD4A6009D8C9F /* SingleChoiceList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleChoiceList.swift; sourceTree = "<group>"; };
449275412C3570CA000526DE /* ICMP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICMP.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2594,6 +2596,7 @@
children = (
4422C0702CCFF6790001A385 /* UDPTCPObfuscationSettingsView.swift */,
44075DFA2CDA4F7400F61139 /* UDPTCPObfuscationSettingsViewModel.swift */,
440E5AB32CDCF24500B09614 /* TunnelObfuscationSettingsWatchingObservableObject.swift */,
);
path = Obfuscation;
sourceTree = "<group>";
Expand Down Expand Up @@ -5884,6 +5887,7 @@
58CEB2FD2AFD19D300E6E088 /* UITableView+ReuseIdentifier.swift in Sources */,
F0FADDEA2BE90AAA000D0B02 /* LaunchArguments.swift in Sources */,
5835B7CC233B76CB0096D79F /* TunnelManager.swift in Sources */,
440E5AB42CDCF24500B09614 /* TunnelObfuscationSettingsWatchingObservableObject.swift in Sources */,
588D7EDE2AF3A585005DF40A /* ListAccessMethodItem.swift in Sources */,
5827B0B02B0F4CCD00CCBBA1 /* ListAccessMethodViewControllerDelegate.swift in Sources */,
588D7EE02AF3A595005DF40A /* ListAccessMethodInteractor.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// TunnelObfuscationSettingsWatchingObservableObject.swift
// MullvadVPN
//
// Created by Andrew Bulhak on 2024-11-07.
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//

import Foundation
import MullvadSettings

/// a generic ObservableObject that binds to obfuscation settings in TunnelManager.
/// Used as the basis for ViewModels for SwiftUI interfaces for these settings.

class TunnelObfuscationSettingsWatchingObservableObject<T: Equatable>: ObservableObject {
let tunnelManager: TunnelManager
let keyPath: WritableKeyPath<WireGuardObfuscationSettings, T>
private var tunnelObserver: TunnelObserver?

// this is essentially @Published from scratch
var value: T {
willSet(newValue) {
guard newValue != self.value else { return }
objectWillChange.send()
var obfuscationSettings = tunnelManager.settings.wireGuardObfuscation
obfuscationSettings[keyPath: keyPath] = newValue
}
}

init(tunnelManager: TunnelManager, keyPath: WritableKeyPath<WireGuardObfuscationSettings, T>, _ initialValue: T) {
self.tunnelManager = tunnelManager
self.keyPath = keyPath
self.value = initialValue
tunnelObserver =
TunnelBlockObserver(didUpdateTunnelSettings: { [weak self] _, newSettings in
guard let self else { return }
updateValueFromSettings(newSettings.wireGuardObfuscation)
})
}

private func updateValueFromSettings(_ settings: WireGuardObfuscationSettings) {
let newValue = settings
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct UDPTCPObfuscationSettingsView<VM>: View where VM: UDPTCPObfuscationSettin
SingleChoiceList(
title: "Port",
options: [WireGuardObfuscationUdpOverTcpPort.automatic, .port80, .port5001],
value: $viewModel.udpTcpPort
value: $viewModel.value
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,28 @@ import Foundation
import MullvadSettings

protocol UDPTCPObfuscationSettingsViewModel: ObservableObject {
var udpTcpPort: WireGuardObfuscationUdpOverTcpPort { get set }
var value: WireGuardObfuscationUdpOverTcpPort { get set }
}

/** A simple mock view model for use in Previews and similar */
class MockUDPTCPObfuscationSettingsViewModel: UDPTCPObfuscationSettingsViewModel {
@Published var udpTcpPort: WireGuardObfuscationUdpOverTcpPort
@Published var value: WireGuardObfuscationUdpOverTcpPort

init(udpTcpPort: WireGuardObfuscationUdpOverTcpPort = .automatic) {
self.udpTcpPort = udpTcpPort
self.value = udpTcpPort
}
}

/** The live view model which interfaces with the TunnelManager */
class TunnelUDPTCPObfuscationSettingsViewModel: UDPTCPObfuscationSettingsViewModel {
let tunnelManager: TunnelManager
private var tunnelObserver: TunnelObserver?

// this is essentially @Published from scratch
var udpTcpPort: WireGuardObfuscationUdpOverTcpPort = .automatic {
willSet(newValue) {
guard newValue != self.udpTcpPort else { return }
objectWillChange.send()
setPortInSettings(newValue)
}
}

class TunnelUDPTCPObfuscationSettingsViewModel: TunnelObfuscationSettingsWatchingObservableObject<
WireGuardObfuscationUdpOverTcpPort
>,
UDPTCPObfuscationSettingsViewModel {
init(tunnelManager: TunnelManager) {
self.tunnelManager = tunnelManager
tunnelObserver =
TunnelBlockObserver(didUpdateTunnelSettings: { [weak self] _, newSettings in
guard let self else { return }
updatePortFromSettings(newSettings)
})

updatePortFromSettings(tunnelManager.settings)
}

private func updatePortFromSettings(_ settings: LatestTunnelSettings) {
let portValue = settings.wireGuardObfuscation.udpOverTcpPort
if portValue != self.udpTcpPort {
self.udpTcpPort = portValue
}
}

// update the settings if there is anything to change
private func setPortInSettings(_ port: WireGuardObfuscationUdpOverTcpPort) {
var obfuscationSettings = tunnelManager.settings.wireGuardObfuscation
obfuscationSettings.udpOverTcpPort = port
tunnelManager.updateSettings([.obfuscation(obfuscationSettings)])
super.init(
tunnelManager: tunnelManager,
keyPath: \.udpOverTcpPort,
.automatic
)
}
}

0 comments on commit 02843c8

Please sign in to comment.