Add exit nodes to the panel
This commit is contained in:
@@ -52,6 +52,21 @@ function accountLabel(account) {
|
||||
return String(account.id || "Unknown account")
|
||||
}
|
||||
|
||||
function peerFromStatus(id, peer) {
|
||||
return {
|
||||
id: id,
|
||||
HostName: displayHostName(peer.HostName, peer.DNSName),
|
||||
DNSName: cleanDnsName(peer.DNSName),
|
||||
TailscaleIPs: filterIPv4(peer.TailscaleIPs || []),
|
||||
TailscaleIPv6: filterIPv6(peer.TailscaleIPs || []),
|
||||
Online: peer.Online === true,
|
||||
OS: String(peer.OS || ""),
|
||||
Tags: peer.Tags || [],
|
||||
ExitNodeOption: peer.ExitNodeOption === true,
|
||||
ExitNode: peer.ExitNode === true
|
||||
}
|
||||
}
|
||||
|
||||
function parseStatus(raw) {
|
||||
var text = String(raw || "").trim()
|
||||
if (text === "") return { ok: true, unavailable: true, message: "Disconnected" }
|
||||
@@ -62,28 +77,24 @@ function parseStatus(raw) {
|
||||
var self = data.Self || {}
|
||||
var selfIps = filterIPv4(self.TailscaleIPs || data.TailscaleIPs || [])
|
||||
var peers = []
|
||||
var exitNodes = []
|
||||
var rawPeers = data.Peer || {}
|
||||
|
||||
for (var id in rawPeers) {
|
||||
var peer = rawPeers[id] || {}
|
||||
if (peer.Online !== true) continue
|
||||
peers.push({
|
||||
id: id,
|
||||
HostName: displayHostName(peer.HostName, peer.DNSName),
|
||||
DNSName: cleanDnsName(peer.DNSName),
|
||||
TailscaleIPs: filterIPv4(peer.TailscaleIPs || []),
|
||||
TailscaleIPv6: filterIPv6(peer.TailscaleIPs || []),
|
||||
Online: true,
|
||||
OS: String(peer.OS || ""),
|
||||
Tags: peer.Tags || [],
|
||||
ExitNodeOption: peer.ExitNodeOption === true,
|
||||
ExitNode: peer.ExitNode === true
|
||||
})
|
||||
var normalized = peerFromStatus(id, peer)
|
||||
if (normalized.Online) {
|
||||
peers.push(normalized)
|
||||
if (normalized.ExitNodeOption) exitNodes.push(normalized)
|
||||
}
|
||||
}
|
||||
|
||||
peers.sort(function(a, b) {
|
||||
return String(a.HostName).localeCompare(String(b.HostName))
|
||||
})
|
||||
exitNodes.sort(function(a, b) {
|
||||
return String(a.HostName).localeCompare(String(b.HostName))
|
||||
})
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
@@ -95,7 +106,8 @@ function parseStatus(raw) {
|
||||
selfName: displayHostName(self.HostName, self.DNSName),
|
||||
selfDnsName: cleanDnsName(self.DNSName),
|
||||
selfIp: selfIps.length > 0 ? selfIps[0] : "",
|
||||
peers: peers
|
||||
peers: peers,
|
||||
exitNodes: exitNodes
|
||||
}
|
||||
} catch (e) {
|
||||
return { ok: false, unavailable: true, message: "Status error", error: "Failed to parse tailscale status" }
|
||||
@@ -143,6 +155,7 @@ if (typeof module !== "undefined") {
|
||||
displayHostName: displayHostName,
|
||||
osIcon: osIcon,
|
||||
accountLabel: accountLabel,
|
||||
peerFromStatus: peerFromStatus,
|
||||
parseStatus: parseStatus,
|
||||
parseAccounts: parseAccounts
|
||||
}
|
||||
|
||||
@@ -39,14 +39,7 @@ Panel {
|
||||
readonly property string fontFamily: bar ? bar.fontFamily : Style.font.family
|
||||
readonly property bool showConnections: tailscale.accounts.length > 1 || tailscale.accountsAccessDenied
|
||||
readonly property bool showPeers: tailscale.running && tailscale.peers.length > 0
|
||||
readonly property var exitNodes: {
|
||||
var nodes = []
|
||||
for (var i = 0; i < tailscale.peers.length; i++) {
|
||||
var peer = tailscale.peers[i]
|
||||
if (peer && peer.ExitNodeOption === true) nodes.push(peer)
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
readonly property var exitNodes: tailscale.exitNodes
|
||||
readonly property bool showExitNodes: tailscale.running && exitNodes.length > 0
|
||||
readonly property color iconColor: tailscale.running ? foreground : dim
|
||||
readonly property color hoverFill: bar ? Style.hoverFillFor(bar.foreground, Color.accent) : "transparent"
|
||||
@@ -877,7 +870,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
id: exitNodeGlyph
|
||||
text: tailscale.osIcon(peer ? peer.OS : "")
|
||||
text: ""
|
||||
color: exitNodeRow.activeExitNode || exitNodeRow.settingExitNode ? root.foreground : root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
|
||||
@@ -20,6 +20,7 @@ Item {
|
||||
property string selfIp: ""
|
||||
property string authUrl: ""
|
||||
property var peers: []
|
||||
property var exitNodes: []
|
||||
property var accounts: []
|
||||
property string selectedAccountId: ""
|
||||
property string selectedAccountLabel: ""
|
||||
@@ -158,6 +159,7 @@ Item {
|
||||
selfIp = ""
|
||||
authUrl = ""
|
||||
peers = []
|
||||
exitNodes = []
|
||||
accounts = []
|
||||
selectedAccountId = ""
|
||||
selectedAccountLabel = ""
|
||||
@@ -188,6 +190,7 @@ Item {
|
||||
selfDnsName = parsed.selfDnsName
|
||||
selfIp = parsed.selfIp
|
||||
peers = parsed.running ? parsed.peers : []
|
||||
exitNodes = parsed.running ? parsed.exitNodes : []
|
||||
|
||||
if (needsLogin) statusText = "Needs login"
|
||||
else if (running) {
|
||||
@@ -253,8 +256,9 @@ Item {
|
||||
|
||||
function setExitNode(peer) {
|
||||
if (!installed || !running || !peer || exitNodeProcess.running) return
|
||||
var target = exitNodeTarget(peer)
|
||||
if (target === "") return
|
||||
var active = peer.ExitNode === true
|
||||
var target = active ? "" : exitNodeTarget(peer)
|
||||
if (!active && target === "") return
|
||||
_exitNodeOutput = ""
|
||||
_exitNodeError = ""
|
||||
settingExitNodeId = String(peer.id || "")
|
||||
|
||||
Reference in New Issue
Block a user