Улучши удаление и строку статуса VPN

This commit is contained in:
2026-05-19 14:13:33 +03:00
parent 4187cb6544
commit 417138b3b1
6 changed files with 224 additions and 40 deletions

View File

@@ -30,6 +30,12 @@ struct StatusBarLabel: View {
private var iconName: String {
switch vpnManager.state {
case .disconnected:
if vpnManager.moduleStatusSystemImage == "exclamationmark.triangle" {
return "exclamationmark.shield"
}
if vpnManager.moduleStatusSystemImage == "questionmark.circle" {
return "questionmark.circle"
}
return "shield.slash"
case .unlocking, .connecting:
return "shield.lefthalf.filled"
@@ -63,7 +69,7 @@ struct VPNMenuView: View {
}
Divider()
Label(vpnManager.moduleSummary, systemImage: "puzzlepiece.extension")
Label(vpnManager.moduleSummary, systemImage: vpnManager.moduleStatusSystemImage)
.disabled(true)
Button("Обновить статус модулей") {
vpnManager.refreshStatus()
@@ -174,4 +180,3 @@ struct VPNMenuView: View {
}
}
}

View File

@@ -58,15 +58,35 @@ struct ModuleStatus: Decodable {
var patches: Patches
var app: AppModule?
var hasWarnings: Bool {
let coreReady = core.openconnect && core.openconnect_lite && core.openconnect_lite_config
let bitwardenReady = !bitwarden.enabled || bitwarden.installed
let touchReady = !touchid.enabled || touchid.installed
let keychainReady = keychain.password && keychain.totp_seed
let appReady = app?.installed ?? true
return !coreReady
|| !bitwardenReady
|| !touchReady
|| !keychainReady
|| !dns_cleanup.installed
|| !patches.active
|| !appReady
}
var systemImage: String {
hasWarnings ? "exclamationmark.triangle" : "checkmark.circle"
}
var summary: String {
let coreState = core.openconnect && core.openconnect_lite && core.openconnect_lite_config ? "core ok" : "core missing"
let bwState = bitwarden.enabled ? (bitwarden.installed ? "bw on" : "bw missing") : "bw off"
let touchState = touchid.enabled ? (touchid.installed ? "touch on" : "touch missing") : "touch off"
let dnsState = dns_cleanup.installed ? "dns on" : "dns missing"
let appState = app.map { $0.installed ? "app on" : "app missing" } ?? "app unknown"
let autostartState = app.map { $0.autostart ? "autostart on" : "autostart off" } ?? "autostart unknown"
let patchState = patches.active ? "patches active" : "patches pending"
let keychainState = "kc \(keychain.password ? "pass" : "-")/\(keychain.totp_seed ? "totp" : "-")"
let coreState = core.openconnect && core.openconnect_lite && core.openconnect_lite_config ? "core" : "⚠️ core"
let bwState = bitwarden.enabled ? (bitwarden.installed ? "bw" : "⚠️ bw") : "⏭️ bw"
let touchState = touchid.enabled ? (touchid.installed ? "touch" : "⚠️ touch") : "⏭️ touch"
let dnsState = dns_cleanup.installed ? "dns" : "⚠️ dns"
let appState = app.map { $0.installed ? "app" : "⚠️ app" } ?? "app"
let autostartState = app.map { $0.autostart ? "autostart" : "⏭️ autostart" } ?? "autostart"
let patchState = patches.active ? "patches" : "⚠️ patches"
let keychainState = "\(keychain.password && keychain.totp_seed ? "" : "⚠️") kc \(keychain.password ? "pass" : "-")/\(keychain.totp_seed ? "totp" : "-")"
return [coreState, bwState, touchState, dnsState, appState, autostartState, patchState, keychainState].joined(separator: " | ")
}
}
@@ -97,6 +117,7 @@ class VPNManager: ObservableObject {
@Published var lastError: String?
@Published var tunnelHealthy: Bool = true
@Published var moduleSummary: String = "modules loading..."
@Published var moduleStatusSystemImage: String = "hourglass"
private var process: Process?
private var outputPipe: Pipe?
@@ -166,6 +187,7 @@ class VPNManager: ObservableObject {
Task { @MainActor in
guard !lastLine.isEmpty, let jsonData = lastLine.data(using: .utf8) else {
self.moduleSummary = "modules unavailable"
self.moduleStatusSystemImage = "questionmark.circle"
self.log("[modules] status refresh returned no JSON output")
return
}
@@ -175,6 +197,7 @@ class VPNManager: ObservableObject {
response = try JSONDecoder().decode(VPNStatusResponse.self, from: jsonData)
} catch {
self.moduleSummary = "modules unavailable"
self.moduleStatusSystemImage = "exclamationmark.triangle"
let compact = text.replacingOccurrences(of: "\n", with: "\\n")
let preview = compact.count > 500 ? String(compact.prefix(500)) + "..." : compact
self.log("[modules] status decode failed: \(error.localizedDescription); output=\(preview)")
@@ -183,11 +206,13 @@ class VPNManager: ObservableObject {
guard let modules = response.modules else {
self.moduleSummary = "modules unavailable: update CLI"
self.moduleStatusSystemImage = "exclamationmark.triangle"
self.log("[modules] status has no modules field; reinstall CLI with install.sh")
return
}
self.moduleSummary = modules.summary
self.moduleStatusSystemImage = modules.systemImage
}
}
@@ -307,6 +332,7 @@ class VPNManager: ObservableObject {
if let modules = event.modules {
moduleSummary = modules.summary
moduleStatusSystemImage = modules.systemImage
}
log("[event] \(event.event)" + {