feat(tailscalectl): add periodic status polling and reactive state

Add Timer (5s interval) that runs tailscale status --json, parsing
BackendState, Self.TailscaleIPs[0], and CurrentExitNode.HostName into
isConnected, tailscaleIP, and currentExitNode properties. Parse errors
surface via ToastService.showError. Initial check runs on load.

Closes #4
This commit is contained in:
John Morris 2026-05-15 19:19:01 -07:00
parent 9c691ccc64
commit 8dd7562d35

View file

@ -9,6 +9,17 @@ PluginComponent {
id: root id: root
property bool isConnected: false property bool isConnected: false
property string tailscaleIP: ""
property string currentExitNode: ""
Timer {
interval: 5000
running: true
repeat: true
onTriggered: statusCheck.running = true
}
Component.onCompleted: statusCheck.running = true
Process { Process {
id: toggleProcess id: toggleProcess
@ -28,8 +39,13 @@ PluginComponent {
try { try {
const data = JSON.parse(this.text) const data = JSON.parse(this.text)
root.isConnected = data.BackendState === "Running" root.isConnected = data.BackendState === "Running"
root.tailscaleIP = (data.Self?.TailscaleIPs?.[0]) || ""
root.currentExitNode = data.CurrentExitNode?.HostName || ""
} catch (e) { } catch (e) {
root.isConnected = false root.isConnected = false
root.tailscaleIP = ""
root.currentExitNode = ""
ToastService.showError("tailscalectl", "Failed to parse Tailscale status")
} }
} }
} }
@ -37,6 +53,8 @@ PluginComponent {
onExited: (code, status) => { onExited: (code, status) => {
if (code !== 0) { if (code !== 0) {
root.isConnected = false root.isConnected = false
root.tailscaleIP = ""
root.currentExitNode = ""
} }
} }
} }