1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
//
// ChipFeature.swift
// MullvadVPN
//
// Created by Mojgan on 2024-12-06.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import MullvadSettings
import PacketTunnelCore
import SwiftUI
protocol ChipFeature: Identifiable {
var id: FeatureType { get }
var isEnabled: Bool { get }
var name: String { get }
}
enum FeatureType {
case daita
case multihop
case quantumResistance
case obfuscation
case dns
case ipOverrides
}
struct DaitaFeature: ChipFeature {
let id: FeatureType = .daita
let state: TunnelState
let settings: LatestTunnelSettings
var isEnabled: Bool {
state.isDaita ?? false
}
var name: String {
// When multihop is enabled via DAITA without being explicitly enabled
// by the user, display combined indicator instead.
state.isMultihop && !settings.tunnelMultihopState.isEnabled
? "\(NSLocalizedString("DAITA", comment: "")): \(NSLocalizedString("Multihop", comment: ""))"
: NSLocalizedString("DAITA", comment: "")
}
}
struct QuantumResistanceFeature: ChipFeature {
let id: FeatureType = .quantumResistance
let state: TunnelState
var isEnabled: Bool {
state.isPostQuantum ?? false
}
var name: String {
NSLocalizedString("Quantum resistance", comment: "")
}
}
struct MultihopFeature: ChipFeature {
let id: FeatureType = .multihop
let state: TunnelState
let settings: LatestTunnelSettings
var isEnabled: Bool {
// Multihop indicator should only be visible when user has explicitly turned on
// multihop, not when using multihop via DAITA.
state.isMultihop && settings.tunnelMultihopState.isEnabled
}
var name: String {
NSLocalizedString("Multihop", comment: "")
}
}
struct ObfuscationFeature: ChipFeature {
let id: FeatureType = .obfuscation
let settings: LatestTunnelSettings
let state: ObservedState
var actualObfuscationMethod: WireGuardObfuscationState {
state.connectionState.map { $0.obfuscationMethod } ?? .off
}
var isEnabled: Bool {
actualObfuscationMethod != .off
}
var isAutomatic: Bool {
settings.wireGuardObfuscation.state == .automatic
}
var name: String {
// This just currently says "Obfuscation".
// To add an automaticity indicator (a trailing " (automatic)"
// or a colour/border style or whatever), use the `isAutomatic` field.
// To say what type of obfuscation it is,
// we can look at `actualObfuscationMethod`
NSLocalizedString("Obfuscation", comment: "")
}
}
struct DNSFeature: ChipFeature {
let id: FeatureType = .dns
let settings: LatestTunnelSettings
var isEnabled: Bool {
settings.dnsSettings.enableCustomDNS || !settings.dnsSettings.blockingOptions.isEmpty
}
var name: String {
if !settings.dnsSettings.blockingOptions.isEmpty {
NSLocalizedString("DNS content blockers", comment: "")
} else {
NSLocalizedString("Custom DNS", comment: "")
}
}
}
struct IPOverrideFeature: ChipFeature {
let id: FeatureType = .ipOverrides
let state: TunnelState
let overrides: [IPOverride]
var isEnabled: Bool {
guard
let endpoint = state.relays?.ingress.endpoint
else { return false }
return overrides.contains { override in
(override.ipv4Address.map { $0 == endpoint.ipv4Relay.ip } ?? false)
|| (override.ipv6Address.map { $0 == endpoint.ipv6Relay?.ip } ?? false)
}
}
var name: String {
NSLocalizedString("Server IP override", comment: "")
}
}
|