Feature: Show public IP in network panel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -575,6 +575,40 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Public (WAN-side) IP — nothing local knows this, the address on the
|
||||||
|
// interface is the LAN one behind NAT, so it has to come from an
|
||||||
|
// outside service. Polled much more slowly than the local stats since
|
||||||
|
// it's a real HTTP request and rarely changes.
|
||||||
|
property string publicIp: "—"
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: publicIpProc
|
||||||
|
command: ["curl", "-s", "--max-time", "5", "https://api.ipify.org"]
|
||||||
|
stdout: StdioCollector {
|
||||||
|
id: publicIpCollector
|
||||||
|
onStreamFinished: {
|
||||||
|
const ip = publicIpCollector.text.trim()
|
||||||
|
root.publicIp = /^[\d.]+$|^[0-9a-fA-F:]+$/.test(ip) ? ip : "—"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switching networks almost always changes the public IP, so don't
|
||||||
|
// leave the old one up until the next slow poll.
|
||||||
|
onConnectedNetworkNameChanged: {
|
||||||
|
root.publicIp = "—"
|
||||||
|
if (panel.visible && root.connectedDevice !== null && !publicIpProc.running)
|
||||||
|
publicIpProc.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 60000
|
||||||
|
repeat: true
|
||||||
|
triggeredOnStart: true
|
||||||
|
running: panel.visible && root.connectedDevice !== null
|
||||||
|
onTriggered: if (!publicIpProc.running) publicIpProc.running = true
|
||||||
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: bytesProc
|
id: bytesProc
|
||||||
command: root.ifaceName
|
command: root.ifaceName
|
||||||
@@ -994,6 +1028,27 @@ Item {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
width: parent.width
|
||||||
|
spacing: 4
|
||||||
|
visible: root.connectedDevice !== null
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Public IP:"
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
color: Colors.muted
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: root.publicIp
|
||||||
|
font.family: Appearance.fontFamily
|
||||||
|
font.pixelSize: Appearance.fontSizeSmall
|
||||||
|
color: Colors.foreground
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Captive portal banner — shown when the connectivity probe
|
// Captive portal banner — shown when the connectivity probe
|
||||||
// above finds either a confirmed sign-in page or a
|
// above finds either a confirmed sign-in page or a
|
||||||
// "limited" result standing between this network and the
|
// "limited" result standing between this network and the
|
||||||
|
|||||||
Reference in New Issue
Block a user