-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathControlWidgetsControl.swift
More file actions
78 lines (68 loc) · 2.55 KB
/
ControlWidgetsControl.swift
File metadata and controls
78 lines (68 loc) · 2.55 KB
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
import AppIntents
import SwiftUI
import WidgetKit
import NetworkExtension
struct ControlWidgetsControl: ControlWidget {
static let kind: String = "site.yinmo.easytier.controlwidgets"
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(
kind: Self.kind,
provider: VPNControlProvider()
) { isConnected in
ControlWidgetToggle(
"EasyTier",
isOn: isConnected,
action: ToggleVPNIntent()
) { isOn in
Label(isOn ? "vpn_connected" : "vpn_disconnected", systemImage: "network")
.controlWidgetActionHint(isOn ? "vpn_disconnect" : "vpn_connect")
}
}
.displayName("EasyTier")
.description("toggle_vpn_connection")
}
}
extension ControlWidgetsControl {
struct VPNControlProvider: ControlValueProvider {
var previewValue: Bool {
false
}
func currentValue() async throws -> Bool {
let managers = try await NETunnelProviderManager.loadAllFromPreferences()
guard let manager = managers.first else {
return false
}
return [.connecting, .connected, .reasserting].contains(manager.connection.status)
}
}
}
struct ToggleVPNIntent: SetValueIntent {
static let title: LocalizedStringResource = "toggle_vpn"
@Parameter(title: "vpn_connected")
var value: Bool
func perform() async throws -> some IntentResult {
let managers = try await NETunnelProviderManager.loadAllFromPreferences()
guard let manager = managers.first else {
return .result()
}
if value {
// Connect - need to load config from App Group
let defaults = UserDefaults(suiteName: "group.site.yinmo.easytier")
guard let configData = defaults?.data(forKey: "LastVPNConfig"),
let config = try? JSONDecoder().decode([String: String].self, from: configData) else {
// Try to start with empty options as fallback
try manager.connection.startVPNTunnel()
return .result()
}
// Convert to NSDictionary for VPN options
var options: [String: NSObject] = [:]
for (key, val) in config {
options[key] = val as NSString
}
try manager.connection.startVPNTunnel(options: options)
} else {
manager.connection.stopVPNTunnel()
}
return .result()
}
}