fix: remove binaryAvailable, fix statusCheck parser location, add timer guard

- Revert binaryAvailable property: reintroduced stale-state anti-pattern
  already rejected in #11. All error paths already handled by Process
  onExited handlers.
- Move statusCheck parsing from onStreamFinished to onExited (#38):
  parser now only runs after exit code validation, preventing stale
  data from being applied on failure.
- Add refreshTimer guard (#44): timer no longer spawns new statusCheck
  while one is already running.

Closes #38, #44. Reverts #52 partial fix.
This commit is contained in:
Vybe (Coding Agent) 2026-05-21 20:58:47 +00:00
parent a789ab615f
commit e2a3315b08

View file

@ -12,7 +12,6 @@ PluginComponent {
property bool isConnected: false
property string tailscaleIP: ""
property string _pendingToggleAction: ""
property string currentExitNode: ""
property var peers: []
property string cachedClipboardTool: ""
@ -25,10 +24,15 @@ PluginComponent {
popoutHeight: 400
Timer {
id: refreshTimer
interval: 5000
running: true
repeat: true
onTriggered: statusCheck.running = true
onTriggered: {
if (!statusCheck.running) {
statusCheck.running = true
}
}
}
Component.onCompleted: {
@ -42,11 +46,10 @@ PluginComponent {
onExited: (code, status) => {
if (code !== 0) {
var action = root._pendingToggleAction || (root.isConnected ? "disconnect" : "connect")
var action = root.isConnected ? "disconnect" : "connect"
var detail = toggleProcess.stderr.text.trim().slice(0, 120)
ToastService.showError("tailscalectl", TailscaleLib.errorMessage(action) + (detail ? " — " + detail : ""))
}
root._pendingToggleAction = ""
statusCheck.running = true
}
}
@ -92,18 +95,16 @@ PluginComponent {
command: ["tailscale", "status", "--json"]
stdout: StdioCollector {
onStreamFinished: {
const state = TailscaleLib.parseStatusResult(this.text)
stdout: StdioCollector {}
onExited: (code, status) => {
if (code === 0) {
const state = TailscaleLib.parseStatusResult(statusCheck.stdout.text)
root.isConnected = state.isConnected
root.tailscaleIP = state.tailscaleIP
root.currentExitNode = state.currentExitNode
root.peers = state.peers
}
}
onExited: (code, status) => {
if (code !== 0) {
} else {
root.isConnected = false
root.tailscaleIP = ""
root.currentExitNode = ""
@ -114,14 +115,11 @@ PluginComponent {
}
function toggleTailscale() {
if (toggleProcess.running) return
root._pendingToggleAction = root.isConnected ? "disconnect" : "connect"
toggleProcess.command = TailscaleLib.buildToggleCommand(root.isConnected)
toggleProcess.running = true
}
function setExitNode(hostname) {
if (exitNodeProcess.running) return
exitNodeProcess.command = TailscaleLib.makeExitNodeCommand(hostname)
exitNodeProcess.running = true
}