feat(w-engine): Add favorite section (#270)

* feat!: add favorite section

* fix: change visual for 1 scroll: wallpaper and favorite wallpaper

* feat!: update for v1.2.0

* fix: rm line downgrade quality

* fix: add downgrade quality for improve storage cache

* feat!: update thumbnail

* feat!: add favorites list in data.json

* feat!: add save favorites list across start plugin
This commit is contained in:
Tadomika-Ari
2026-08-07 22:24:22 -04:00
committed by GitHub
parent 3319112aed
commit 7fa96aceef
4 changed files with 112 additions and 8 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
id = "tadomika_ari/w-engine"
name = "W Engine"
version = "1.1.1"
version = "1.2.0"
# Tile and control callbacks are Luau closures rather than named globals, which
# the host resolves from plugin API 9 onwards.
plugin_api = 9
+3 -1
View File
@@ -27,6 +27,7 @@ local data = {
saved_wallpaper = {}, -- output -> the Noctalia wallpaper from before we took over
options = {}, -- id -> { engine = {...}, properties = {...} }, see buildLaunchArgs
defaults = {}, -- { engine = {...} } applied to every wallpaper, see optionsFor
favorites = {}, -- favorites wallpapers list
}
-- linux-wallpaperengine switches that take no value. Stored as booleans; the
@@ -103,6 +104,7 @@ local function loadData()
data.saved_wallpaper = asTable(decoded.saved_wallpaper)
data.options = asTable(decoded.options)
data.defaults = asTable(decoded.defaults)
data.favorites = asTable(decoded.favorites)
end
local function saveData()
@@ -233,7 +235,7 @@ local function resolveColorSource(id, callback)
-- names contain spaces and non-ASCII, so paths are quoted.
local cmd = "ffmpeg -y -loglevel error -ss 1 -i "
.. shellQuote(dir .. file)
.. " -frames:v 1 -vf scale=960:-2 "
.. " -frames:v 1 -vf scale=960:-2"
.. shellQuote(frame)
noctalia.runAsync(cmd, function(result)
-- A wallpaper shorter than the seek offset produces no output and no error,
Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 56 KiB

+108 -6
View File
@@ -1170,12 +1170,83 @@ local function tilePreview(item, isSelected, isCurrent)
})
end
-- Favorite list
local FavoriteList = {}
local function getDataPath()
return noctalia.pluginDataDir() .. "/data.json"
end
local function loadData()
local raw = noctalia.readFile(getDataPath())
if not raw then
return {}
end
local ok, decoded = pcall(function()
return noctalia.json.decode(raw)
end)
if not ok or type(decoded) ~= "table" then
return {}
end
return decoded
end
local function saveData(data)
return noctalia.writeFile(getDataPath(), noctalia.json.encode(data))
end
local function loadFavoriteList()
local data = loadData()
FavoriteList = data.favorites or {}
end
local function persistFavoriteList()
local data = loadData() -- récupère les autres clés existantes (ex: settingsPath)
data.favorites = FavoriteList
saveData(data)
end
local function addFavoriteList(item)
noctalia.notify("Add Favorite")
table.insert(FavoriteList, item)
persistFavoriteList()
end
local function removeFavoriteList(item, nb)
noctalia.notify("Remove Favorite")
table.remove(FavoriteList, nb)
persistFavoriteList()
end
local function checkInFavoriteList(item)
local nb = 1
for _, entryName in ipairs(FavoriteList) do
if entryName.name == item.name then
removeFavoriteList(item, nb)
return
end
nb = nb + 1
end
addFavoriteList(item)
end
local function tileCaption(item, index, isSelected)
-- Numbered to show rotation order.
local caption = isSelected and (tostring(index) .. ". " .. item.name) or item.name
-- A fixed label width keeps every tile the same size; long titles truncate.
return ui.row({ gap = 2, align = "center" }, {
ui.button({
glyph = "star",
variant = "ghost",
controlSize = "sm",
tooltip = "Add at your favorite wallpaper",
onClick = function()
checkInFavoriteList(item)
render()
end
}),
ui.label({
text = caption,
fontSize = 11,
@@ -1239,15 +1310,45 @@ render = function()
if #catalog == 0 then
table.insert(body, ui.label({ text = tr("panel.no_wallpapers"), fontSize = 12, color = "on_surface_variant" }))
end
-- paddingRight keeps the last column clear of the scrollbar.
table.insert(
body,
ui.scroll({ key = "grid-scroll", gap = 12, paddingRight = 8, align = "stretch", flexGrow = 1 }, rows)
)
local favoriteRows = {}
local favoriteRow = {}
for index, item in ipairs(FavoriteList) do
table.insert(favoriteRow, tile(item, state))
if #favoriteRow == columns or index == #FavoriteList then
table.insert(favoriteRows, ui.row({ gap = 12, align = "start" }, favoriteRow))
favoriteRow = {}
end
end
-- Single scroll for all list (Wallpaper and Favorite Wallpaper)
local scrollContent = {}
table.insert(scrollContent, ui.label({ text = "Favorites", fontSize = 13, fontWeight = "bold", color = "on_surface" }))
if #FavoriteList == 0 then
table.insert(scrollContent, ui.label({ text = "No favorite", fontSize = 12, color = "on_surface_variant" }))
else
for _, r in ipairs(favoriteRows) do
table.insert(scrollContent, r)
end
end
table.insert(scrollContent,
ui.separator({ spacing = 12 }
))
table.insert(scrollContent,
ui.label({ text = "All wallpapers", fontSize = 13, fontWeight = "bold", color = "on_surface" }
))
for _, r in ipairs(rows) do
table.insert(scrollContent, r)
end
table.insert(body,
ui.scroll({ key = "grid-scroll", gap = 12, paddingRight = 8, align = "stretch", flexGrow = 1 }, scrollContent))
panel.render(ui.column({ flexGrow = 1, gap = 12 }, body))
end
-- ── Handlers ─────────────────────────────────────────────────────────────────
-- Adopts the service's view of this output. Selection, interval and order are
@@ -1291,6 +1392,7 @@ end
function onOpen(_context)
isOpen = true
loadFavoriteList()
outputName = noctalia.focusedOutputName() or outputName
if not outputName then
local outputs = noctalia.outputs()