feat(noctalia): add portable status widgets and idle monitoring
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
-- Compact, two-line network throughput widget. It samples the interface used
|
||||
-- by the default route so virtual and physical interfaces are not double-counted.
|
||||
local command = [[
|
||||
iface=$(ip route show default 2>/dev/null | awk '$1 == "default" { for (i = 1; i <= NF; i++) if ($i == "dev") { print $(i + 1); exit } }')
|
||||
|
||||
if [ -z "$iface" ]; then
|
||||
for path in /sys/class/net/*; do
|
||||
candidate=${path##*/}
|
||||
[ "$candidate" = "lo" ] && continue
|
||||
[ "$(cat "$path/carrier" 2>/dev/null)" = "1" ] || continue
|
||||
iface=$candidate
|
||||
break
|
||||
done
|
||||
fi
|
||||
|
||||
[ -n "$iface" ] || exit 1
|
||||
awk -v iface="$iface" '$1 ~ ("^" iface ":") { sub(":", "", $1); print iface "\t" $2 "\t" $10; exit }' /proc/net/dev
|
||||
]]
|
||||
|
||||
local previous = nil
|
||||
local request_in_flight = false
|
||||
-- 82px accommodates the longest fixed field ("1023 KiB/s") at 10px while
|
||||
-- removing the excess side padding from the original 112px capsule.
|
||||
local label_width = 82
|
||||
|
||||
local function formatRate(bytes_per_second)
|
||||
local units = { "B/s", "KiB/s", "MiB/s", "GiB/s" }
|
||||
local value = bytes_per_second
|
||||
local unit_index = 1
|
||||
|
||||
while value >= 1024 and unit_index < #units do
|
||||
value = value / 1024
|
||||
unit_index = unit_index + 1
|
||||
end
|
||||
|
||||
if unit_index == 1 then
|
||||
return string.format("%d %s", math.floor(value + 0.5), units[unit_index])
|
||||
end
|
||||
|
||||
if value >= 100 then
|
||||
return string.format("%.0f %s", value, units[unit_index])
|
||||
end
|
||||
|
||||
return string.format("%.1f %s", value, units[unit_index])
|
||||
end
|
||||
|
||||
local function renderLines(download, upload)
|
||||
-- The explicit minimum width and fixed ten-character value field keep the
|
||||
-- capsule width stable while inheriting the bar font used by other modules.
|
||||
barWidget.render(ui.column({ gap = 0, align = "center", minWidth = label_width }, {
|
||||
ui.label({
|
||||
text = string.format("↓ %10s", download),
|
||||
maxLines = 1,
|
||||
fontSize = 10,
|
||||
}),
|
||||
ui.label({
|
||||
text = string.format("↑ %10s", upload),
|
||||
maxLines = 1,
|
||||
fontSize = 10,
|
||||
}),
|
||||
}))
|
||||
end
|
||||
|
||||
function update()
|
||||
noctalia.setUpdateInterval(2000)
|
||||
|
||||
if request_in_flight then
|
||||
return
|
||||
end
|
||||
|
||||
request_in_flight = true
|
||||
noctalia.runAsync(command, function(result)
|
||||
request_in_flight = false
|
||||
|
||||
if result.exitCode ~= 0 then
|
||||
previous = nil
|
||||
renderLines("—", "—")
|
||||
barWidget.setTooltip("Network throughput unavailable: no active interface")
|
||||
return
|
||||
end
|
||||
|
||||
local iface, received, sent = string.match(
|
||||
result.stdout,
|
||||
"^([^\t]+)\t(%d+)\t(%d+)"
|
||||
)
|
||||
received = tonumber(received)
|
||||
sent = tonumber(sent)
|
||||
|
||||
if iface == nil or received == nil or sent == nil then
|
||||
previous = nil
|
||||
renderLines("—", "—")
|
||||
barWidget.setTooltip("Network throughput unavailable")
|
||||
return
|
||||
end
|
||||
|
||||
local now = os.time()
|
||||
if previous == nil or previous.iface ~= iface or now <= previous.time then
|
||||
previous = { iface = iface, received = received, sent = sent, time = now }
|
||||
renderLines("Sampling…", "Sampling…")
|
||||
barWidget.setTooltip("Sampling network throughput on " .. iface)
|
||||
return
|
||||
end
|
||||
|
||||
local elapsed = now - previous.time
|
||||
local download = math.max(0, (received - previous.received) / elapsed)
|
||||
local upload = math.max(0, (sent - previous.sent) / elapsed)
|
||||
previous = { iface = iface, received = received, sent = sent, time = now }
|
||||
|
||||
renderLines(formatRate(download), formatRate(upload))
|
||||
barWidget.setTooltip(
|
||||
string.format(
|
||||
"%s · Download %s · Upload %s",
|
||||
iface,
|
||||
formatRate(download),
|
||||
formatRate(upload)
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user