feat: add shelly plugin (#2)
* feat: add shelly plugin * docs: document click action * add license * feat: add setting to hide when there are no updates * remove some tags * address tags feedback * Update tags in plugin.toml for clarity --------- Co-authored-by: Lemmy <studio@quadbyte.net>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Shelly
|
||||
|
||||
Shelly is a plugin that uses the [Shelly Arch Package Manager](https://github.com/Seafoam-Labs/Shelly-ALPM) to display package update information in a bar widget.
|
||||
|
||||
## Plugin
|
||||
|
||||
| Field | Value |
|
||||
| ------- | --------------------------------------- |
|
||||
| ID | `joshuaslate/shelly` |
|
||||
| Entries | Service: `poller`; bar widget: `shelly` |
|
||||
|
||||
## Requirements
|
||||
|
||||
Install the Shelly Arch Package Manager from the [AUR](https://aur.archlinux.org/packages/shelly).
|
||||
|
||||
Test that it works by running `shelly check-updates` in a terminal. If it returns a list of packages, then it is working correctly.
|
||||
|
||||
## Settings
|
||||
|
||||
| Setting | Type | Default | Description |
|
||||
| ---------------------- | -------- | ------------ | -------------------------------------------------------------------------------------------------- |
|
||||
| `interval` | `int` | `300` | The interval (in seconds) between update checks |
|
||||
| `notify` | `bool` | `false` | Whether or not you want to receive notifications when there are new package updates available |
|
||||
| `color` | `color` | `on_surface` | The text color for the bar widget |
|
||||
| `glyph_color` | `color` | `on_surface` | The color of the glyph on the bar widget |
|
||||
| `glyph` | `glyph` | `package` | Bar widget icon. |
|
||||
| `click_action` | `select` | `open_gui` | The action to perform when the bar widget is clicked. Options: `open_gui`, `open_updater`, `none`. |
|
||||
| `hide_when_up_to_date` | `bool` | `false` | Whether or not to hide the bar widget when there are no package updates available |
|
||||
@@ -0,0 +1,74 @@
|
||||
id = "joshuaslate/shelly"
|
||||
name = "Shelly"
|
||||
icon = "package"
|
||||
version = "1.0.0"
|
||||
min_noctalia = "5.0.0"
|
||||
license = "MIT"
|
||||
author = "joshuaslate"
|
||||
dependencies = ["shelly"]
|
||||
description = "A plugin that provides a widget for displaying system update information."
|
||||
tags = ["system", "arch"]
|
||||
deprecated = false
|
||||
|
||||
[[setting]]
|
||||
key = "interval"
|
||||
type = "int"
|
||||
label_key = "settings.interval.label"
|
||||
description_key = "settings.interval.description"
|
||||
default = 300
|
||||
min = 0
|
||||
|
||||
[[setting]]
|
||||
key = "notify"
|
||||
type = "bool"
|
||||
label_key = "settings.notify.label"
|
||||
description_key = "settings.notify.description"
|
||||
default = false
|
||||
|
||||
[[service]]
|
||||
id = "update_poller"
|
||||
entry = "poller.luau"
|
||||
|
||||
[[widget]]
|
||||
id = "shelly"
|
||||
entry = "widget.luau"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "hide_when_up_to_date"
|
||||
type = "bool"
|
||||
label_key = "settings.hide_when_up_to_date.label"
|
||||
description_key = "settings.hide_when_up_to_date.description"
|
||||
default = false
|
||||
|
||||
[[widget.setting]]
|
||||
key = "color"
|
||||
type = "color"
|
||||
label_key = "settings.color.label"
|
||||
description_key = "settings.color.description"
|
||||
default = "on_surface"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "glyph"
|
||||
type = "glyph"
|
||||
label_key = "settings.glyph.label"
|
||||
description_key = "settings.glyph.description"
|
||||
default = "package"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "glyph_color"
|
||||
type = "color"
|
||||
label_key = "settings.glyph_color.label"
|
||||
description_key = "settings.glyph_color.description"
|
||||
default = "on_surface"
|
||||
|
||||
[[widget.setting]]
|
||||
key = "click_action"
|
||||
type = "select"
|
||||
label_key = "settings.click_action.label"
|
||||
description_key = "settings.click_action.description"
|
||||
default = "open_gui"
|
||||
options = [
|
||||
{ value = "none", label_key = "settings.click_action.options.none" },
|
||||
{ value = "open_gui", label_key = "settings.click_action.options.open_gui" },
|
||||
{ value = "open_updater", label_key = "settings.click_action.options.open_updater" }
|
||||
]
|
||||
@@ -0,0 +1,57 @@
|
||||
--!nonstrict
|
||||
|
||||
type Update = { Name: string, Version: string, OldVersion: string?, DownloadSize: string? }
|
||||
|
||||
type UpdateResult = {
|
||||
Packages: { [number]: Update },
|
||||
Aur: { [number]: Update },
|
||||
Flatpak: { [number]: Update },
|
||||
}
|
||||
|
||||
local updates: UpdateResult = { Packages = {}, Aur = {}, Flatpak = {} }
|
||||
local updateError: string | nil = nil
|
||||
local updateInterval = (noctalia.getConfig("interval") or 300)*1000
|
||||
local isPolling = false
|
||||
|
||||
noctalia.setUpdateInterval(updateInterval)
|
||||
|
||||
function refresh()
|
||||
isPolling = true
|
||||
|
||||
noctalia.runAsync("shelly check-updates --json", function(result)
|
||||
isPolling = false
|
||||
|
||||
if result.exitCode ~= 0 then
|
||||
updateError = result.stderr
|
||||
noctalia.state.set("updates", nil)
|
||||
noctalia.state.set("update_error", updateError)
|
||||
return
|
||||
end
|
||||
|
||||
local decoded = noctalia.json.decode(result.stdout)
|
||||
if type(decoded) ~= "table" then
|
||||
updateError = noctalia.tr("bar.tooltip.error.decode_json")
|
||||
noctalia.state.set("update_error", updateError)
|
||||
return
|
||||
end
|
||||
|
||||
updates = {
|
||||
Packages = decoded.Packages or {},
|
||||
Aur = decoded.Aur or {},
|
||||
Flatpak = decoded.Flatpak or {},
|
||||
}
|
||||
|
||||
noctalia.state.set("updates", updates)
|
||||
noctalia.state.set("update_error", nil)
|
||||
end)
|
||||
end
|
||||
|
||||
function update()
|
||||
if isPolling then
|
||||
return
|
||||
end
|
||||
|
||||
refresh()
|
||||
end
|
||||
|
||||
refresh()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"title": "Shelly",
|
||||
"notify": {
|
||||
"new_updates": {
|
||||
"title": "New Updates Available",
|
||||
"description": "There are {count} new updates available for your system."
|
||||
}
|
||||
},
|
||||
"bar": {
|
||||
"text": {
|
||||
"error": "?",
|
||||
"updates": {
|
||||
"one": "{count} Update",
|
||||
"other": "{count} Updates"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"aur_title": "AUR",
|
||||
"flatpak_title": "Flatpak",
|
||||
"packages_title": "Packages",
|
||||
"no_updates": "System is up to date",
|
||||
"error": {
|
||||
"decode_json": "Failed to decode output from `shelly check-updates --json`"
|
||||
}
|
||||
},
|
||||
"click_handler": {
|
||||
"error": {
|
||||
"missing_gui": "Shelly GUI is not installed. Please install it to use this feature.",
|
||||
"missing_cli": "Shelly CLI is not installed. Please install it to use this feature."
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"interval": {
|
||||
"label": "Refresh Seconds",
|
||||
"description": "How often the service checks for updates in the background."
|
||||
},
|
||||
"notify": {
|
||||
"label": "Notify",
|
||||
"description": "Whether to show a notification when new updates are available."
|
||||
},
|
||||
"click_action": {
|
||||
"label": "Click Action",
|
||||
"description": "What happens when you click on the bar.",
|
||||
"options": {
|
||||
"none": "Nothing",
|
||||
"open_gui": "Open Shelly GUI",
|
||||
"open_updater": "Start Update in Terminal"
|
||||
}
|
||||
},
|
||||
"hide_when_up_to_date": {
|
||||
"label": "Hide When Up-to-Date",
|
||||
"description": "Whether to hide the bar when there are no updates available."
|
||||
},
|
||||
"color": {
|
||||
"label": "Color",
|
||||
"description": "The color of the bar text."
|
||||
},
|
||||
"glyph": {
|
||||
"label": "Glyph",
|
||||
"description": "The glyph shown before the label."
|
||||
},
|
||||
"glyph_color": {
|
||||
"label": "Glyph Color",
|
||||
"description": "The color of the glyph."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
--!nonstrict
|
||||
local glyph = barWidget.getConfig("glyph")
|
||||
local color = barWidget.getConfig("color") or "on_surface"
|
||||
local glyphColor = barWidget.getConfig("glyph_color") or color
|
||||
local updateError = noctalia.state.get("update_error")
|
||||
local notifyOnNewUpdates = barWidget.getConfig("notify")
|
||||
local hideWhenUpToDate = barWidget.getConfig("hide_when_up_to_date")
|
||||
local click_action = barWidget.getConfig("click_action") or "open_gui"
|
||||
local updates = noctalia.state.get("updates") or { Packages = {}, Aur = {}, Flatpak = {} }
|
||||
|
||||
local function countUpdates(scopedUpdates)
|
||||
return #scopedUpdates.Packages + #scopedUpdates.Aur + #scopedUpdates.Flatpak
|
||||
end
|
||||
|
||||
local function getUpdateLabel(update)
|
||||
if update.OldVersion then
|
||||
return string.format("%s → %s", update.OldVersion, update.Version)
|
||||
else
|
||||
return update.Version
|
||||
end
|
||||
end
|
||||
|
||||
local function appendUpdateSection(rows, title, list)
|
||||
if #list == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
table.insert(rows, {
|
||||
key = title,
|
||||
value = string.format("%d", #list),
|
||||
})
|
||||
|
||||
for _, pkg in ipairs(list) do
|
||||
table.insert(rows, {
|
||||
key = " " .. pkg.Name,
|
||||
value = getUpdateLabel(pkg),
|
||||
})
|
||||
|
||||
if pkg.DownloadSize then
|
||||
table.insert(rows, {
|
||||
key = "",
|
||||
value = pkg.DownloadSize,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateTooltip(count)
|
||||
if updateError then
|
||||
barWidget.setTooltip(updateError)
|
||||
return
|
||||
end
|
||||
|
||||
if count == 0 then
|
||||
barWidget.setTooltip(noctalia.tr("bar.tooltip.no_updates"))
|
||||
return
|
||||
end
|
||||
|
||||
local rows = {}
|
||||
|
||||
appendUpdateSection(rows, noctalia.tr("bar.tooltip.packages_title"), updates.Packages)
|
||||
appendUpdateSection(rows, noctalia.tr("bar.tooltip.aur_title"), updates.Aur)
|
||||
appendUpdateSection(rows, noctalia.tr("bar.tooltip.flatpak_title"), updates.Flatpak)
|
||||
|
||||
barWidget.setTooltip(rows)
|
||||
end
|
||||
|
||||
local function render()
|
||||
local container = barWidget.isVertical() and ui.column or ui.row
|
||||
|
||||
local count = countUpdates(updates)
|
||||
|
||||
barWidget.render(container({ gap = 6, align = "center", visible = not hideWhenUpToDate or count > 0 }, {
|
||||
ui.glyph({ name = glyph, size = 14, color = glyphColor, visible = glyph ~= "" }),
|
||||
ui.label({ text = noctalia.trp("bar.text.updates", count), color = color }),
|
||||
}))
|
||||
|
||||
updateTooltip(count)
|
||||
end
|
||||
|
||||
noctalia.state.watch("updates", function(value)
|
||||
local prevCount = countUpdates(updates)
|
||||
local newCount = countUpdates(value)
|
||||
|
||||
updates = value
|
||||
|
||||
if notifyOnNewUpdates and newCount > prevCount then
|
||||
noctalia.notify(noctalia.tr("notify.new_updates.title"), noctalia.trp("notify.new_updates.description", newCount))
|
||||
end
|
||||
|
||||
render()
|
||||
end)
|
||||
|
||||
function onClick()
|
||||
if click_action == "open_gui" then
|
||||
local cmd = "shelly-ui"
|
||||
|
||||
if not noctalia.commandExists(cmd) then
|
||||
noctalia.notifyError("Shelly", noctalia.tr("bar.click_handler.error.missing_gui"))
|
||||
return
|
||||
end
|
||||
|
||||
noctalia.runAsync(cmd)
|
||||
elseif click_action == "open_updater" then
|
||||
local cmd = "shelly"
|
||||
|
||||
if not noctalia.commandExists(cmd) then
|
||||
noctalia.notifyError("Shelly", noctalia.tr("bar.click_handler.error.missing_cli"))
|
||||
return
|
||||
end
|
||||
|
||||
noctalia.runInTerminal(cmd .. " upgrade-all")
|
||||
end
|
||||
end
|
||||
|
||||
render()
|
||||
Reference in New Issue
Block a user