Compare commits

..

No commits in common. "d85c4b914e3f82882bc89ef39c039de305e2ce88" and "978588ecffdfb5862f4f5cc9dbd47414bbc696b8" have entirely different histories.

3 changed files with 22 additions and 20 deletions

View file

@ -12,6 +12,7 @@ PluginComponent {
property bool isConnected: false
property string tailscaleIP: ""
property string _pendingToggleAction: ""
property string currentExitNode: ""
property var peers: []
property string cachedClipboardTool: ""
@ -24,15 +25,10 @@ PluginComponent {
popoutHeight: 400
Timer {
id: refreshTimer
interval: 5000
running: true
repeat: true
onTriggered: {
if (!statusCheck.running) {
statusCheck.running = true
}
}
onTriggered: statusCheck.running = true
}
Component.onCompleted: {
@ -46,10 +42,11 @@ PluginComponent {
onExited: (code, status) => {
if (code !== 0) {
var action = root.isConnected ? "disconnect" : "connect"
var action = root._pendingToggleAction || (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
}
}
@ -95,16 +92,18 @@ PluginComponent {
command: ["tailscale", "status", "--json"]
stdout: StdioCollector {}
onExited: (code, status) => {
if (code === 0) {
const state = TailscaleLib.parseStatusResult(statusCheck.stdout.text)
stdout: StdioCollector {
onStreamFinished: {
const state = TailscaleLib.parseStatusResult(this.text)
root.isConnected = state.isConnected
root.tailscaleIP = state.tailscaleIP
root.currentExitNode = state.currentExitNode
root.peers = state.peers
} else {
}
}
onExited: (code, status) => {
if (code !== 0) {
root.isConnected = false
root.tailscaleIP = ""
root.currentExitNode = ""
@ -115,11 +114,14 @@ 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
}
@ -302,9 +304,14 @@ PluginComponent {
}
}
// propagateComposedEvents: true so that right-clicks both trigger our context menu
// *and* bubble to any parent MouseArea (e.g. for shell-level drag handling).
// Documented because the default (false) is far more common and this choice
// frequently surprises future maintainers.
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.RightButton
propagateComposedEvents: true
onClicked: {
root.toggleTailscale()
}

View file

@ -1,7 +1,6 @@
function parsePeers(peerMap) {
if (!peerMap) return []
return Object.keys(peerMap).map(function (key) {
if (!Object.prototype.hasOwnProperty.call(peerMap, key)) return null
var p = peerMap[key]
return {
hostname: p.HostName || key,
@ -9,20 +8,16 @@ function parsePeers(peerMap) {
online: p.Online || false,
exitNode: p.ExitNodeOption || false
}
}).filter(function (peer) { return peer !== null })
})
}
function makeExitNodeCommand(hostname) {
if (hostname === "") {
return ["tailscale", "set", "--exit-node="]
}
return ["tailscale", "set", "--exit-node=" + hostname]
}
function findActiveExitNode(peerMap) {
if (!peerMap) return ""
for (const key in peerMap) {
if (!Object.prototype.hasOwnProperty.call(peerMap, key)) continue
const p = peerMap[key]
if (p.ExitNode) {
return p.HostName || key

View file

@ -3,7 +3,7 @@
"name": "Tailscale",
"description": "Tailscale status and controls on the Dank Bar",
"version": "0.1.0",
"author": "John Morris",
"author": "John Morris & Vybe (AI Slop... er... Coding Assistant)",
"icon": "vpn_key",
"type": "widget",
"component": "./TailscaleWidget.qml",