Skip to content
2 changes: 1 addition & 1 deletion w-engine/plugin.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 3 additions & 1 deletion w-engine/start.luau
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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,
Expand Down
Binary file modified w-engine/thumbnail.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
114 changes: 108 additions & 6 deletions w-engine/w-engine-panel.luau
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1291,6 +1392,7 @@ end

function onOpen(_context)
isOpen = true
loadFavoriteList()
outputName = noctalia.focusedOutputName() or outputName
if not outputName then
local outputs = noctalia.outputs()
Expand Down