feat: bar widget shows battery with scroll-sidetone control

This commit is contained in:
loki committed 2026-08-31 12:25:55 +02:00
1 parent d77dc7eff4
commit 1011d43b2e
1 file changed
+128
+128
View File
@@ -0,0 +1,128 @@
local hsc = require("./lib/hsc.luau")
local battery = { status = "BATTERY_UNAVAILABLE", level = -1 }
local chatmix = 0
local caps = {}
local device = nil
local errorState = ""
local sidetoneValue = nil
local sidetoneFlashUntil = 0
local function statusKey(status)
if status == "BATTERY_CHARGING" then return "status.charging" end
if status == "BATTERY_FULL" then return "status.full" end
if status == "BATTERY_DISCHARGING" then return "status.discharging" end
return "status.normal"
end
local function batteryGlyph()
if battery.status == "BATTERY_CHARGING" then return "battery-charging" end
if battery.level < 0 then return "battery-off" end
if battery.level <= 25 then return "battery-1" end
if battery.level <= 50 then return "battery-2" end
if battery.level <= 75 then return "battery-3" end
return "battery-4"
end
local function batteryColor()
local low = noctalia.getConfig("battery_low") or 20
if battery.level < 0 then return "#6e7681" end
if battery.level <= low then return "#e5484d" end
if battery.status == "BATTERY_CHARGING" then return "#3fb950" end
return "#7ee787"
end
local function render()
if errorState == "no_binary" then
barWidget.setGlyph("alert-triangle")
barWidget.setColor("#e5484d")
barWidget.setGlyphColor("#e5484d")
barWidget.setText("")
barWidget.setTooltip(noctalia.tr("error.no_binary"))
return
end
if noctalia.nowMs() < sidetoneFlashUntil and sidetoneValue ~= nil then
barWidget.setGlyph("music")
barWidget.setColor("#e6edf3")
barWidget.setGlyphColor("#e6edf3")
barWidget.setText(tostring(sidetoneValue))
else
barWidget.setGlyph(batteryGlyph())
local col = batteryColor()
barWidget.setColor(col)
barWidget.setGlyphColor(col)
if battery.level < 0 then
barWidget.setText("--")
else
barWidget.setText(tostring(battery.level) .. "%")
end
end
local parts = {}
if device and device.name then
table.insert(parts, device.name)
end
if battery.level >= 0 then
table.insert(parts, noctalia.tr(statusKey(battery.status)) .. " " .. battery.level .. "%")
elseif errorState == "unavailable" then
table.insert(parts, noctalia.tr("status.unavailable"))
end
if caps.chatmix then
table.insert(parts, noctalia.tr("widget.chatmix") .. ": " .. hsc.chatmixText(chatmix))
end
barWidget.setTooltip(table.concat(parts, " "))
end
local function sendSidetone(value)
value = math.clamp(value, 0, 128)
hsc.sendCommand({ "-s", tostring(value) }, function(res)
if res.exitCode ~= 0 then
noctalia.notifyError(noctalia.tr("error.command_failed"), string.sub(res.stderr or "", 1, 200))
return
end
noctalia.state.set("sidetone", value)
end)
sidetoneValue = value
sidetoneFlashUntil = noctalia.nowMs() + 2000
render()
end
function onScroll(axis, steps)
if axis ~= "vertical" then return end
local current = sidetoneValue or noctalia.getConfig("sidetone_default") or 64
sendSidetone(current + steps * 4)
end
function onClick()
noctalia.togglePanel("loki/headsetcontrol:control")
end
function update()
noctalia.setUpdateInterval(1000)
render()
end
local function syncState()
local v = noctalia.state.get("battery")
if v then battery = v end
v = noctalia.state.get("chatmix")
if v ~= nil then chatmix = v end
v = noctalia.state.get("caps")
if v then caps = v end
v = noctalia.state.get("device")
if v then device = v end
v = noctalia.state.get("error")
if v ~= nil then errorState = v end
v = noctalia.state.get("sidetone")
if v ~= nil then sidetoneValue = v end
end
noctalia.state.watch("battery", function(v) battery = v or battery; render() end)
noctalia.state.watch("chatmix", function(v) chatmix = v or 0; render() end)
noctalia.state.watch("caps", function(v) caps = v or {}; render() end)
noctalia.state.watch("device", function(v) device = v; render() end)
noctalia.state.watch("error", function(v) errorState = v or ""; render() end)
noctalia.state.watch("sidetone", function(v) if v ~= nil then sidetoneValue = v end end)
syncState()