Compare commits
No commits in common. "d85c4b914e3f82882bc89ef39c039de305e2ce88" and "978588ecffdfb5862f4f5cc9dbd47414bbc696b8" have entirely different histories.
d85c4b914e
...
978588ecff
3 changed files with 22 additions and 20 deletions
|
|
@ -12,6 +12,7 @@ PluginComponent {
|
||||||
|
|
||||||
property bool isConnected: false
|
property bool isConnected: false
|
||||||
property string tailscaleIP: ""
|
property string tailscaleIP: ""
|
||||||
|
property string _pendingToggleAction: ""
|
||||||
property string currentExitNode: ""
|
property string currentExitNode: ""
|
||||||
property var peers: []
|
property var peers: []
|
||||||
property string cachedClipboardTool: ""
|
property string cachedClipboardTool: ""
|
||||||
|
|
@ -24,15 +25,10 @@ PluginComponent {
|
||||||
popoutHeight: 400
|
popoutHeight: 400
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: refreshTimer
|
|
||||||
interval: 5000
|
interval: 5000
|
||||||
running: true
|
running: true
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: {
|
onTriggered: statusCheck.running = true
|
||||||
if (!statusCheck.running) {
|
|
||||||
statusCheck.running = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|
@ -46,10 +42,11 @@ PluginComponent {
|
||||||
|
|
||||||
onExited: (code, status) => {
|
onExited: (code, status) => {
|
||||||
if (code !== 0) {
|
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)
|
var detail = toggleProcess.stderr.text.trim().slice(0, 120)
|
||||||
ToastService.showError("tailscalectl", TailscaleLib.errorMessage(action) + (detail ? " — " + detail : ""))
|
ToastService.showError("tailscalectl", TailscaleLib.errorMessage(action) + (detail ? " — " + detail : ""))
|
||||||
}
|
}
|
||||||
|
root._pendingToggleAction = ""
|
||||||
statusCheck.running = true
|
statusCheck.running = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,16 +92,18 @@ PluginComponent {
|
||||||
|
|
||||||
command: ["tailscale", "status", "--json"]
|
command: ["tailscale", "status", "--json"]
|
||||||
|
|
||||||
stdout: StdioCollector {}
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
onExited: (code, status) => {
|
const state = TailscaleLib.parseStatusResult(this.text)
|
||||||
if (code === 0) {
|
|
||||||
const state = TailscaleLib.parseStatusResult(statusCheck.stdout.text)
|
|
||||||
root.isConnected = state.isConnected
|
root.isConnected = state.isConnected
|
||||||
root.tailscaleIP = state.tailscaleIP
|
root.tailscaleIP = state.tailscaleIP
|
||||||
root.currentExitNode = state.currentExitNode
|
root.currentExitNode = state.currentExitNode
|
||||||
root.peers = state.peers
|
root.peers = state.peers
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: (code, status) => {
|
||||||
|
if (code !== 0) {
|
||||||
root.isConnected = false
|
root.isConnected = false
|
||||||
root.tailscaleIP = ""
|
root.tailscaleIP = ""
|
||||||
root.currentExitNode = ""
|
root.currentExitNode = ""
|
||||||
|
|
@ -115,11 +114,14 @@ PluginComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleTailscale() {
|
function toggleTailscale() {
|
||||||
|
if (toggleProcess.running) return
|
||||||
|
root._pendingToggleAction = root.isConnected ? "disconnect" : "connect"
|
||||||
toggleProcess.command = TailscaleLib.buildToggleCommand(root.isConnected)
|
toggleProcess.command = TailscaleLib.buildToggleCommand(root.isConnected)
|
||||||
toggleProcess.running = true
|
toggleProcess.running = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function setExitNode(hostname) {
|
function setExitNode(hostname) {
|
||||||
|
if (exitNodeProcess.running) return
|
||||||
exitNodeProcess.command = TailscaleLib.makeExitNodeCommand(hostname)
|
exitNodeProcess.command = TailscaleLib.makeExitNodeCommand(hostname)
|
||||||
exitNodeProcess.running = true
|
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 {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
acceptedButtons: Qt.RightButton
|
acceptedButtons: Qt.RightButton
|
||||||
|
propagateComposedEvents: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.toggleTailscale()
|
root.toggleTailscale()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
function parsePeers(peerMap) {
|
function parsePeers(peerMap) {
|
||||||
if (!peerMap) return []
|
if (!peerMap) return []
|
||||||
return Object.keys(peerMap).map(function (key) {
|
return Object.keys(peerMap).map(function (key) {
|
||||||
if (!Object.prototype.hasOwnProperty.call(peerMap, key)) return null
|
|
||||||
var p = peerMap[key]
|
var p = peerMap[key]
|
||||||
return {
|
return {
|
||||||
hostname: p.HostName || key,
|
hostname: p.HostName || key,
|
||||||
|
|
@ -9,20 +8,16 @@ function parsePeers(peerMap) {
|
||||||
online: p.Online || false,
|
online: p.Online || false,
|
||||||
exitNode: p.ExitNodeOption || false
|
exitNode: p.ExitNodeOption || false
|
||||||
}
|
}
|
||||||
}).filter(function (peer) { return peer !== null })
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeExitNodeCommand(hostname) {
|
function makeExitNodeCommand(hostname) {
|
||||||
if (hostname === "") {
|
|
||||||
return ["tailscale", "set", "--exit-node="]
|
|
||||||
}
|
|
||||||
return ["tailscale", "set", "--exit-node=" + hostname]
|
return ["tailscale", "set", "--exit-node=" + hostname]
|
||||||
}
|
}
|
||||||
|
|
||||||
function findActiveExitNode(peerMap) {
|
function findActiveExitNode(peerMap) {
|
||||||
if (!peerMap) return ""
|
if (!peerMap) return ""
|
||||||
for (const key in peerMap) {
|
for (const key in peerMap) {
|
||||||
if (!Object.prototype.hasOwnProperty.call(peerMap, key)) continue
|
|
||||||
const p = peerMap[key]
|
const p = peerMap[key]
|
||||||
if (p.ExitNode) {
|
if (p.ExitNode) {
|
||||||
return p.HostName || key
|
return p.HostName || key
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Tailscale",
|
"name": "Tailscale",
|
||||||
"description": "Tailscale status and controls on the Dank Bar",
|
"description": "Tailscale status and controls on the Dank Bar",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"author": "John Morris",
|
"author": "John Morris & Vybe (AI Slop... er... Coding Assistant)",
|
||||||
"icon": "vpn_key",
|
"icon": "vpn_key",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
"component": "./TailscaleWidget.qml",
|
"component": "./TailscaleWidget.qml",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue