Files
community-plugins/rss-notifier/panel.luau
T
NilsonlinuxandGitHub d32a20cd32 fix(plugin): Feed text encoding fix and panel UI improvements V1.0.2 (#271)
* fix(plugin): Feed text encoding fix and panel UI improvements V1.0.2

* fix(plugin): Feed text encoding fix and panel UI improvements V1.0.2

* Add xdg-open dependency to plugin.toml

Added 'xdg-open' as a dependency for the plugin.
2026-08-06 10:16:22 -04:00

154 lines
4.7 KiB
Luau

-- panel.luau
-- Janela pop-up mostrada ao clicar no widget da barra: lista os itens mais
-- recentes, ou um estado vazio com icone quando nao ha nada novo.
local items = {}
local hoveredKey = nil
-- declaradas antes para permitir referencia cruzada entre elas
local render
local dismissItem
local itemRow
local emptyState
local function openLink(link)
if not link or link == "" then
return
end
-- escapa aspas simples pra evitar quebrar o comando do shell
local safe = link:gsub("'", "'\\''")
noctalia.runAsync("xdg-open '" .. safe .. "'")
end
dismissItem = function(item)
-- remove localmente (resposta imediata) e avisa o service pra nao
-- reaparecer nas proximas atualizacoes
for i, it in ipairs(items) do
if it == item then
table.remove(items, i)
break
end
end
render()
local id = item.id or item.link or item.title
if id then
local safe = tostring(id):gsub("'", "'\\''")
noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all dismiss '" .. safe .. "'")
end
end
itemRow = function(item)
local key = item.id or item.link or item.title
local hovered = hoveredKey == key
return ui.row({
key = key,
gap = 6,
padding = 10,
radius = 8,
fill = "surface_variant/0.4",
align = "center",
border = "outline",
borderWidth = hovered and 1 or 0,
onHover = function(isHovering)
hoveredKey = isHovering and key or nil
render()
end,
}, {
ui.column({
gap = 2,
flexGrow = 1,
onClick = function() openLink(item.link) end,
}, {
ui.label({ text = item.title or "(sem titulo)", fontWeight = "bold", maxLines = 2 }),
ui.label({ text = item.feedTitle or "", fontSize = 12, color = "outline" }),
}),
ui.button({
glyph = "close",
variant = "outline",
controlSize = "sm",
tooltip = "Dispensar",
onClick = function() dismissItem(item) end,
}),
})
end
emptyState = function()
return ui.column({ gap = 10, align = "center", padding = 32, flexGrow = 1, justify = "center" }, {
ui.glyph({ name = "rss", size = 32, color = "outline" }),
ui.label({ text = "Nenhuma atualização", color = "outline" }),
})
end
render = function()
local body
if #items == 0 then
body = emptyState()
else
local rows = {}
for _, item in ipairs(items) do
table.insert(rows, itemRow(item))
end
-- flexGrow preenche o espaco que sobrar dentro da coluna raiz - so
-- funciona se essa coluna tiver uma altura definida (ver abaixo).
body = ui.scroll({ gap = 6, flexGrow = 1 }, rows)
end
local headerButtons = {}
if #items > 0 then
table.insert(headerButtons, ui.button({ glyph = "trash", variant = "outline", controlSize = "sm", tooltip = "Limpar tudo", onClick = "onClearAllClicked" }))
end
table.insert(headerButtons, ui.button({ glyph = "refresh", variant = "outline", controlSize = "sm", tooltip = "Atualizar agora", onClick = "onRefreshClicked" }))
table.insert(headerButtons, ui.button({ glyph = "close", variant = "outline", controlSize = "sm", onClick = "onCloseClicked" }))
-- um pouco menor que os 415 do painel (ver plugin.toml) para sobrar uma
-- margem de seguranca antes da borda arredondada, em vez de encostar nela
panel.render(ui.column({ gap = 10, padding = 12, height = 415 }, {
ui.row({ align = "center", justify = "space_between" }, {
ui.label({ text = "RSS/Atom Notifier", fontSize = 15, fontWeight = "bold" }),
ui.row({ gap = 4 }, headerButtons),
}),
ui.separator({}),
body,
}))
end
noctalia.state.watch("items", function(raw)
local ok, decoded = pcall(noctalia.json.decode, raw or "[]")
items = (ok and decoded) or {}
render()
end)
function onOpen(_context)
-- o painel so e criado na primeira vez que e aberto - se o service ja
-- tinha publicado itens antes disso (ex: na checagem de boot), o watch()
-- sozinho nao pega esse valor antigo. Busca o estado atual na abertura.
local ok, raw = pcall(noctalia.state.get, "items")
if ok and raw then
local decodeOk, decoded = pcall(noctalia.json.decode, raw)
if decodeOk and decoded then
items = decoded
end
end
render()
-- abrir o painel conta como "li as novidades": zera o badge no service
noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all mark-read")
end
function onRefreshClicked()
noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all refresh")
end
function onClearAllClicked()
items = {}
render()
noctalia.runAsync("noctalia msg plugin nilsonlinux/rss-notifier:fetcher all clear-all")
end
function onCloseClicked()
panel.close()
end