103 lines
3.8 KiB
Lua
103 lines
3.8 KiB
Lua
local request_in_flight = false
|
|
|
|
local function shell_quote(value)
|
|
return "'" .. string.gsub(value, "'", "'\\\"'\\\"'") .. "'"
|
|
end
|
|
|
|
local function ui_binary()
|
|
local configured = noctalia.getenv("PI_STATUS_UI_BINARY")
|
|
if configured ~= nil and configured ~= "" then return configured end
|
|
return (noctalia.getenv("HOME") or "") .. "/projects/pi-status-bridge/ui/src-tauri/target/release/pi-status-ui"
|
|
end
|
|
|
|
local function bridge_client_binary()
|
|
local configured = noctalia.getenv("PI_STATUS_BRIDGE_CLIENT")
|
|
if configured ~= nil and configured ~= "" then return shell_quote(configured) end
|
|
return "pi-status-bridge-client"
|
|
end
|
|
|
|
local function socket_path()
|
|
local runtime = noctalia.getenv("XDG_RUNTIME_DIR")
|
|
if runtime == nil or runtime == "" then return nil end
|
|
return runtime .. "/pi-status-bridge/bridge.sock"
|
|
end
|
|
|
|
local bridge_start_in_flight = false
|
|
local pending_ui_open = false
|
|
|
|
local function open_ui()
|
|
local binary = shell_quote(ui_binary())
|
|
local command = "if test -x " .. binary .. "; then setsid -f env TMPDIR=/tmp "
|
|
.. binary .. " --toggle >/tmp/pi-status-ui.log 2>&1; else exit 1; fi"
|
|
noctalia.runAsync(command, function(result)
|
|
if result.exitCode ~= 0 then
|
|
barWidget.setGlyph("alert-triangle")
|
|
barWidget.setText("Pi UI unavailable")
|
|
barWidget.setTooltip("Build Pi Status UI or set PI_STATUS_UI_BINARY")
|
|
end
|
|
end)
|
|
end
|
|
|
|
local function start_bridge(open_after_start)
|
|
if open_after_start then pending_ui_open = true end
|
|
if bridge_start_in_flight then return end
|
|
bridge_start_in_flight = true
|
|
barWidget.setGlyph("terminal-2")
|
|
barWidget.setText("Pi starting")
|
|
barWidget.setTooltip("Bridge is starting")
|
|
noctalia.runAsync("systemctl --user start pi-status-bridge.service", function(result)
|
|
bridge_start_in_flight = false
|
|
if result.exitCode ~= 0 then
|
|
pending_ui_open = false
|
|
barWidget.setGlyph("alert-triangle")
|
|
barWidget.setText("Pi offline")
|
|
barWidget.setTooltip("Could not start pi-status-bridge.service")
|
|
return
|
|
end
|
|
if pending_ui_open then pending_ui_open = false; open_ui() end
|
|
end)
|
|
end
|
|
|
|
local function json_count(payload, key)
|
|
local value = string.match(payload, '"' .. key .. '":(%d+)')
|
|
return tonumber(value) or 0
|
|
end
|
|
|
|
local function update_summary(payload)
|
|
local open = json_count(payload, "openCount")
|
|
local working = json_count(payload, "workingCount")
|
|
local attention = json_count(payload, "attentionCount")
|
|
local recovering = json_count(payload, "recoveringCount")
|
|
local errors = json_count(payload, "errorCount")
|
|
local glyph = errors > 0 and "alert-triangle" or attention > 0 and "circle-alert" or working > 0 and "terminal-2" or recovering > 0 and "refresh-cw" or "terminal"
|
|
local text = errors > 0 and "Pi needs attention" or working > 0 and "Pi working" or recovering > 0 and "Pi recovering" or "Pi ready"
|
|
local detail = open .. " open · " .. working .. " working · " .. attention .. " attention · " .. recovering .. " recovering · " .. errors .. " errors"
|
|
barWidget.setGlyph(glyph)
|
|
barWidget.setText(text)
|
|
barWidget.setTooltip(detail .. "; click to open Pi Status UI")
|
|
end
|
|
|
|
function update()
|
|
noctalia.setUpdateInterval(2000)
|
|
local socket = socket_path()
|
|
if socket == nil then start_bridge(false); return end
|
|
if request_in_flight then return end
|
|
request_in_flight = true
|
|
local command = bridge_client_binary() .. " --socket \"" .. socket .. "\" request '{\"op\":\"get_workspace_summary\"}'"
|
|
noctalia.runAsync(command, function(result)
|
|
request_in_flight = false
|
|
if result.exitCode ~= 0 then
|
|
start_bridge(false)
|
|
barWidget.setGlyph("terminal-2")
|
|
barWidget.setText("Pi reconnecting")
|
|
barWidget.setTooltip("Refreshing Pi workspace summary")
|
|
return
|
|
end
|
|
update_summary(result.stdout)
|
|
end)
|
|
end
|
|
|
|
function onClick()
|
|
start_bridge(true)
|
|
end
|