-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathControlWidgetsControl.swift
More file actions
85 lines (74 loc) · 2.76 KB
/
ControlWidgetsControl.swift
File metadata and controls
85 lines (74 loc) · 2.76 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
79
80
81
82
83
84
85
//
// ControlWidgetsControl.swift
// ControlWidgets
//
// Created by YinMo19 on 2026/1/13.
//
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 ? LocalizedStringResource("vpn_connected") : LocalizedStringResource("vpn_disconnected"), systemImage: "network")
.controlWidgetActionHint(isOn ? LocalizedStringResource("vpn_disconnect") : LocalizedStringResource("vpn_connect"))
}
}
.displayName("EasyTier")
.description(LocalizedStringResource("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 manager.connection.status == .connected
}
}
}
struct ToggleVPNIntent: SetValueIntent {
static let title: LocalizedStringResource = "toggle_vpn"
@Parameter(title: LocalizedStringResource("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()
}
}