Files
asepharyana 1cdb82a76f Sync config from arch
- hypr/apps.lua
- hypr/autostart.lua
- hypr/envs.lua
- hypr/hyprland.lua
- hypr/hyprsunset.conf
- hypr/input.lua
- hypr/looknfeel.lua
- hypr/omasettings.lua
- hypr/xdph.conf
- omarchy/branding/about.txt
- omarchy/branding/screensaver.txt
- omarchy/extensions/omarchy-menu.jsonc
- omarchy/hooks/battery-low.d/play-warning-sound.sample
- omarchy/hooks/font-set.d/show-font-notification.sample
- omarchy/hooks/post-boot.d/weather.sample
- omarchy/hooks/post-update.d/install-voxtype.hook
- omarchy/hooks/post-update.d/setup-agent.hook
- omarchy/hooks/post-update.d/setup-fingerprint.hook
- omarchy/hooks/post-update.d/show-update-notification.sample
- omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample
- omarchy/hooks/theme-set.d/show-theme-notification.sample
- omarchy/shell.json
- omarchy/shell.toml
- omarchy/theme.name
- omarchy/themes/azure-glow/README.md
- omarchy/themes/azure-glow/alacritty.toml
- omarchy/themes/azure-glow/btop.theme
- omarchy/themes/azure-glow/hyprland.conf
- omarchy/themes/azure-glow/hyprlock.conf
- omarchy/themes/azure-glow/icons.theme
- … 269 more
2026-09-23 15:19:12 +07:00

399 lines
15 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import qs.Commons
import qs.Ui
import "pathspark.js" as Spark
// laptop — router — internet, with per-leg latency on the connecting lines.
// The answer to "is it me or is it them", drawn rather than written.
Item {
id: root
property var live: null
// The configured anchor: the far node's fallback label when no WAN
// address has been proven yet (see middle/far node text below).
property string anchor: ""
property color textColor: Color.popups.text
property color dimColor: Color.muted
// A phone sharing its data, as detected by the daemon from the gateway
// range. `label` is what to call it — iPhone, Phone, Hotspot.
readonly property var metered: live && live.metered ? live.metered : null
readonly property bool tethered: !!(metered && metered.tethered)
readonly property string middleTitle: tethered ? metered.label : "Router"
readonly property string middleDetail: {
if (!live || !live.link) return ""
// On a hotspot the gateway is always the same fixed address for the
// platform, so it carries no information; the phone's own name does.
// iOS names the hotspot after the device, so the network name IS the
// handset's name.
if (tethered) return live.link.ssid || live.link.gateway || ""
return live.link.gateway || ""
}
// Three minutes of each leg for the connectors. The ISP leg arrives already
// subtracted per point — see score.wan_point_ms — so nothing here re-derives
// it and the inversion guard keeps one implementation.
readonly property var points: panel ? panel.recentPoints : []
readonly property var localSeries: Spark.slots(points, "local", Spark.SLOTS)
readonly property var wanSeries: Spark.slots(points, "wan", Spark.SLOTS)
// One zero-based scale for both, so a 2 ms wobble cannot outdraw the WAN.
readonly property real sparkMax: Spark.sharedMax([localSeries, wanSeries],
Spark.SCALE_FLOOR_MS)
// The panel already knows whether readings are arriving: the daemon writes
// live.json at 2 Hz and the bar widget calls it stale after five seconds.
// The ring is that fact drawn, not a second rule with a second clock.
readonly property bool sparkLive: !!(panel && !panel.stale)
readonly property var localMs: live && live.local ? live.local.p50 : null
readonly property var wanMs: live && live.wan ? live.wan.p50 : null
readonly property bool localDown: live && live.state === "local-down"
readonly property bool wanDown: live && live.state === "wan-down"
// The address this connection appears from, published by the daemon.
// Shown masked: Overview screenshots end up on forums, and a screenshot
// must not carry the poster's IP. Tapping the node reveals it; the
// reveal is never persisted anywhere.
readonly property var wanIp: live && live.wan_ip ? live.wan_ip : null
readonly property var seated: {
if (!live || !live.instruments) return []
return live.instruments.filter(function(i) { return i.active })
}
// What the info glyph on the Internet node explains on hover: which
// instruments hold the scored seats right now. A caption line said
// "2 probes live" here once — permanent height for a once-read fact.
function benchTip() {
var lines = []
for (var i = 0; i < seated.length; i++) {
var ins = seated[i]
lines.push(ins.kind + " \u00b7 " + ins.target
+ (ins.p50 !== null && ins.p50 !== undefined
? " \u2014 " + ins.p50.toFixed(1) + " ms" : ""))
}
var standby = live && live.instruments
? live.instruments.length - seated.length : 0
if (standby > 0)
lines.push(standby + " on standby \u2014 full bench on the Latency tab")
lines.push(detailOpen ? "tap to close" : "tap for detail")
return lines.join("\n")
}
// Opening the detail is the deliberate act that reveals the address, so
// the two are one gesture. Held by the Panel so switching tabs does not
// close it; it resets with the shell, which is the right lifetime for a
// view preference. Never persisted — an Overview screenshot taken
// without opening this carries a masked address.
// Held by the Panel, like the other disclosure toggles, so switching
// tabs does not close it. Null-guarded: without a panel the detail
// simply never opens rather than throwing on every tap.
property var panel: null
readonly property bool detailOpen: !!(panel && panel.wanDetailOpen)
readonly property bool revealIp: detailOpen
function ipLine() {
if (!wanIp || !wanIp.ip) return ""
var parts = [String(wanIp.ip)]
// Country and edge ride along in the response the reachability check
// already fetches. The edge is Cloudflare's datacentre, not the
// user's location, so it is labelled as the route and not as a place.
if (wanIp.country) parts.push(wanIp.country)
if (wanIp.edge) parts.push("via Cloudflare " + wanIp.edge)
return parts.join(" \u00b7 ")
}
function legLine() {
var l = localMs, w = wanMs
if ((l === null || l === undefined) && (w === null || w === undefined))
return ""
var f = function(v) {
return v === null || v === undefined ? "\u2014" : v.toFixed(2) + " ms"
}
return "local " + f(l) + " \u00b7 wan " + f(w)
}
function probeLine() {
if (seated.length === 0) return ""
var parts = []
for (var i = 0; i < seated.length; i++) {
var ins = seated[i]
parts.push(ins.kind + " " + ins.target
+ (ins.p50 !== null && ins.p50 !== undefined
? " " + ins.p50.toFixed(1) : ""))
}
var standby = live && live.instruments
? live.instruments.length - seated.length : 0
var out = parts.join(" \u00b7 ")
if (standby > 0) out += " (+" + standby + " standby)"
return out
}
function loadLine() {
var lag = live && live.lag ? live.lag : null
if (!lag || lag.idle === null || lag.idle === undefined
|| lag.loaded === null || lag.loaded === undefined) return ""
// The daemon withholds `inflation` when the two populations are too
// close to separate or the ratio came out backwards. Absent inflation
// means the pair is not trustworthy either, so the whole row goes —
// printing "idle 13.0 -> loaded 10.9" states that the link answers
// FASTER while busy, which queueing cannot do. A result that is wrong
// in direction is not a result, and it is not made safe by dropping
// only the ratio computed from it.
if (lag.inflation === null || lag.inflation === undefined) return ""
return "idle " + lag.idle.toFixed(1)
+ " \u2192 loaded " + lag.loaded.toFixed(1) + " ms"
+ " (" + lag.inflation.toFixed(2) + "\u00d7)"
}
function appsLine() {
var s = live && live.sockets ? live.sockets : null
if (!s || s.queue_p50 === null || s.queue_p50 === undefined) return ""
var out = "queue " + s.queue_p50.toFixed(1) + " ms typical"
if (s.queue_p95 !== null && s.queue_p95 !== undefined)
out += ", " + s.queue_p95.toFixed(1) + " worst"
if (s.sockets) out += " over " + s.sockets + " connections"
return out
}
function maskedIp(w) {
if (!w || !w.ip) return ""
var full = String(w.ip)
if (revealIp) return full
if (w.family === "v6")
return full.split(":").slice(0, 2).join(":") + ":\u2026"
return full.split(".").slice(0, 2).join(".") + ".\u2026"
}
function legColor(ms, down) {
if (down) return Color.urgent
if (ms === null || ms === undefined) return dimColor
if (ms <= 15) return "#9ece6a"
if (ms <= 50) return "#e0af68"
return Color.urgent
}
// One animator for both legs, stopped the moment the liveness claim stops
// being true: a panel left open must never keep pulsing over stale data.
property real ringPhase: 0
NumberAnimation on ringPhase {
running: root.sparkLive && root.motionOk
loops: Animation.Infinite
from: 0; to: 1; duration: 1400
}
// Omarchy's own animation preference; a user who turns the bar's motion off
// gets a static second circle rather than nothing, so the claim still reads.
readonly property bool motionOk: {
var b = panel ? panel.bar : null
if (!b || !("foregroundAnimationEnabled" in b)) return true
return b.foregroundAnimationEnabled === true
}
implicitHeight: stack.implicitHeight
Column {
id: stack
width: parent.width
spacing: Style.space(10)
Row {
id: row
width: parent.width
component Node: Column {
property string icon: ""
property string title: ""
property string detail: ""
width: Style.space(84)
spacing: Style.space(4)
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: parent.icon
color: root.textColor
font.family: Style.font.family
font.pixelSize: Style.font.iconLarge
}
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: parent.title
color: root.textColor
font.family: Style.font.family
font.pixelSize: Style.font.caption
}
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: parent.detail
color: root.dimColor
font.family: Style.font.family
font.pixelSize: Style.font.caption
elide: Text.ElideMiddle
width: parent.width
horizontalAlignment: Text.AlignHCenter
}
}
component Leg: Column {
property var ms: null
property bool down: false
property string label: ""
property var series: []
width: (row.width - Style.space(84) * 3) / 2
spacing: Style.space(4)
// Sits a little above the node centres so the line meets the icons.
topPadding: Style.space(8)
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: parent.down ? "down"
: (parent.ms === null || parent.ms === undefined
? "--" : parent.ms.toFixed(1) + " ms")
color: root.legColor(parent.ms, parent.down)
font.family: Style.font.family
font.pixelSize: Style.font.bodySmall
}
Canvas {
id: spark
width: parent.width - Style.space(12)
anchors.horizontalCenter: parent.horizontalCenter
// 16 left the plot 9 px tall with nothing spare, so the ring was
// cut on every side it could reach. The margin the ring needs is
// fixed; buying it out of the plot would have left a 3 px band.
// This keeps the same 9 px of plot and costs six pixels once —
// the connectors are side by side, so it is six for the panel,
// not six per leg.
height: Style.space(22)
antialiasing: true
// Repainting on every phase tick is what the ring costs; the series
// only changes every five seconds.
property real phase: root.ringPhase
property var series: parent.series
property real sparkScale: root.sparkMax
onPhaseChanged: requestPaint()
onSeriesChanged: requestPaint()
onSparkScaleChanged: requestPaint()
onPaint: {
var ctx = getContext("2d")
Spark.draw(ctx, width, height, series, {
max: sparkScale,
phase: phase,
live: root.sparkLive,
motion: root.motionOk,
downColor: Color.urgent,
colorFor: root.legColor
})
}
}
Text {
textFormat: Text.PlainText
anchors.horizontalCenter: parent.horizontalCenter
text: parent.label
color: root.dimColor
font.family: Style.font.family
font.pixelSize: Style.font.caption
font.letterSpacing: 1
}
}
Node {
icon: "󰌢" // nf-md-laptop
title: "This machine"
detail: root.live && root.live.link ? (root.live.link.iface || "") : ""
}
Leg {
ms: root.localMs
down: root.localDown
label: "LOCAL"
series: root.localSeries
}
// When the connection comes from a phone, this node is the phone. Drawing
// a router here mislabelled both legs at once: the local leg is the hop
// to the handset, and everything past it is cellular, not an ISP line.
Node {
icon: root.tethered ? "󰄜" : "󰑩" // nf-md-cellphone / nf-md-router_wireless
title: root.middleTitle
detail: root.middleDetail
}
Leg {
ms: root.wanMs
down: root.wanDown
label: "WAN"
series: root.wanSeries
}
Node {
icon: "󰖟" // nf-md-web
title: "Internet"
// Your address out there, not the probe target: with a bench of
// instruments there is no single anchor to name, and naming one
// read as "this monitors Cloudflare". Masked — screenshots end up
// on forums; tap to reveal, never persisted.
detail: (root.wanIp ? root.maskedIp(root.wanIp) : root.anchor)
+ (root.seated.length > 0 ? " 󰋽" : "")
TapHandler {
onTapped: if (root.panel) root.panel.wanDetailOpen = !root.panel.wanDetailOpen
}
HoverHandler { id: inetHover }
PanelToolTip {
visible: inetHover.hovered && root.seated.length > 0
text: root.benchTip()
}
}
}
// What the far node knows, shown only when asked for. Everything here
// is already measured — no extra request, no new destination — and it
// is deliberately what a single-number internet score cannot show: two
// legs, which instruments produced them, and what the machine's own
// connections are experiencing.
Column {
id: detail
width: parent.width
spacing: Style.space(4)
visible: root.detailOpen
// A visible:false child still takes its share of a Column's spacing.
height: visible ? implicitHeight : 0
component DetailRow: Row {
property string label: ""
property string value: ""
visible: value !== ""
height: visible ? implicitHeight : 0
spacing: Style.space(8)
Text {
textFormat: Text.PlainText
text: parent.label
color: root.dimColor
font.family: Style.font.family
font.pixelSize: Style.font.caption
font.letterSpacing: 1
width: Style.space(72)
}
Text {
textFormat: Text.PlainText
text: parent.value
color: root.textColor
font.family: Style.font.family
font.pixelSize: Style.font.caption
elide: Text.ElideRight
width: detail.width - Style.space(80)
}
}
DetailRow { label: "ADDRESS"; value: root.ipLine() }
DetailRow { label: "LEGS"; value: root.legLine() }
DetailRow { label: "PROBES"; value: root.probeLine() }
DetailRow { label: "UNDER LOAD"; value: root.loadLine() }
DetailRow { label: "APPS SEE"; value: root.appsLine() }
}
}
}