Fix/gamelauncher nixos build (#225)
* game-launcher: bundle self-contained SQLite reader, drop libsqlite3 dependency Fixes building gamelauncher.c on NixOS where the runtime env lacks sqlite3.h/libsqlite3. scan_lutris now reads Lutris' pga.db through a bundled read-only SQLite file parser instead of linking sqlite3. * game-launcher: rework /g provider to reuse panel scan results The launcher provider now reads the games the panel already scanned via state/cache, trims the query, and surfaces status/error rows instead of duplicating the scan. --------- Co-authored-by: Ahmed5Emad <ahmed5emad@users.noreply.github.com>
This commit is contained in:
+71
-56
@@ -1,78 +1,92 @@
|
||||
local games = {}
|
||||
local ready = false
|
||||
local binary = noctalia.pluginDir() .. "/gamelauncher"
|
||||
local cSource = noctalia.pluginDir() .. "/gamelauncher.c"
|
||||
local lastQuery = ""
|
||||
|
||||
local function statusRow(title, subtitle, glyph)
|
||||
return { id = "", title = title, subtitle = subtitle, glyph = glyph }
|
||||
end
|
||||
|
||||
local function isRunnerEnabled(runner)
|
||||
local ok, val = pcall(noctalia.getConfig, runner .. "_enabled")
|
||||
if ok then return val == true or val == "true" end
|
||||
if ok and val ~= nil then return val == true or val == "true" end
|
||||
return true
|
||||
end
|
||||
|
||||
local function getRunnerFlags()
|
||||
local flags = ""
|
||||
if isRunnerEnabled("steam") then flags = flags .. " --steam" end
|
||||
if isRunnerEnabled("lutris") then flags = flags .. " --lutris" end
|
||||
if isRunnerEnabled("heroic") then flags = flags .. " --heroic" end
|
||||
return flags
|
||||
local function loadGames()
|
||||
local ok, v = pcall(noctalia.state.get, "games")
|
||||
if ok and type(v) == "table" and #v > 0 then
|
||||
games = v
|
||||
return true
|
||||
end
|
||||
local base = noctalia.getenv("XDG_CACHE_HOME")
|
||||
if not base or #base == 0 then
|
||||
local home = noctalia.getenv("HOME") or ""
|
||||
base = home .. "/.cache"
|
||||
end
|
||||
local raw = noctalia.readFile(base .. "/gamelauncher/games.json")
|
||||
if raw then
|
||||
local parsed = noctalia.json.decode(raw)
|
||||
if type(parsed) == "table" and #parsed > 0 then
|
||||
games = parsed
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function ensureGames(cb)
|
||||
local function runScan()
|
||||
local ok = noctalia.runAsync(binary .. getRunnerFlags() .. " --force", function(res)
|
||||
if res.exitCode == 0 and res.stdout and #res.stdout > 0 then
|
||||
local parsed, err = noctalia.json.decode(res.stdout)
|
||||
if parsed then
|
||||
games = parsed
|
||||
ready = true
|
||||
end
|
||||
end
|
||||
cb()
|
||||
end)
|
||||
if not ok then cb() end
|
||||
local function filterRows(text)
|
||||
local lower = noctalia.string.trim(text):lower()
|
||||
local results = {}
|
||||
for _, g in ipairs(games) do
|
||||
if g.name and g.runner and g.name:lower():find(lower, 1, true) and isRunnerEnabled(g.runner) then
|
||||
local meta = { steam = { glyph = "brand-steam", color = "steam" }, lutris = { glyph = "device-gamepad", color = "warning" }, heroic = { glyph = "app-window", color = "heroic" } }
|
||||
local m = meta[g.runner] or { glyph = "app-window", color = "on_surface" }
|
||||
table.insert(results, {
|
||||
id = g.id,
|
||||
title = g.name,
|
||||
subtitle = "Launch via " .. g.runner,
|
||||
glyph = m.glyph,
|
||||
})
|
||||
end
|
||||
end
|
||||
if ready then
|
||||
cb()
|
||||
return
|
||||
if #results == 0 then
|
||||
if #games == 0 then
|
||||
return {
|
||||
statusRow("No games found", "Open the Game Launcher panel to scan your games first.", "app-window"),
|
||||
}
|
||||
end
|
||||
return {
|
||||
statusRow("No games found", "Nothing matches \"" .. text .. "\". Try a different name.", "app-window"),
|
||||
}
|
||||
end
|
||||
if not noctalia.fileExists(binary) then
|
||||
local ok = noctalia.runAsync("cc -o " .. binary .. " " .. cSource .. " -lsqlite3", function(res)
|
||||
if res.exitCode == 0 then
|
||||
runScan()
|
||||
else
|
||||
cb()
|
||||
end
|
||||
end)
|
||||
if not ok then cb() end
|
||||
return
|
||||
end
|
||||
runScan()
|
||||
return results
|
||||
end
|
||||
|
||||
pcall(function()
|
||||
noctalia.state.watch("games", function(v)
|
||||
if type(v) == "table" then
|
||||
games = v
|
||||
if lastQuery ~= "" then
|
||||
launcher.setResults(lastQuery, filterRows(lastQuery))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
function onQuery(text)
|
||||
lastQuery = text
|
||||
if text == "" then
|
||||
launcher.setResults(text, {
|
||||
{ id = "hint", title = "Type a game name to search", glyph = "device-gamepad-2" },
|
||||
statusRow("Type a game name to search", "Searches Steam, Lutris, and Heroic.", "device-gamepad-2"),
|
||||
})
|
||||
return
|
||||
end
|
||||
ensureGames(function()
|
||||
local lower = text:lower()
|
||||
local results = {}
|
||||
for _, g in ipairs(games) do
|
||||
if g.name:lower():find(lower, 1, true) and isRunnerEnabled(g.runner) then
|
||||
local meta = { steam = { glyph = "brand-steam", color = "steam" }, lutris = { glyph = "device-gamepad", color = "warning" }, heroic = { glyph = "app-window", color = "heroic" } }
|
||||
local m = meta[g.runner] or { glyph = "app-window", color = "on_surface" }
|
||||
table.insert(results, {
|
||||
id = g.id,
|
||||
title = g.name,
|
||||
subtitle = "Launch via " .. g.runner,
|
||||
glyph = m.glyph,
|
||||
})
|
||||
end
|
||||
end
|
||||
launcher.setResults(text, results)
|
||||
end)
|
||||
if not loadGames() then
|
||||
launcher.setResults(text, {
|
||||
statusRow("No games loaded", "Open the Game Launcher panel first so it can scan your games.", "device-gamepad-2"),
|
||||
})
|
||||
return
|
||||
end
|
||||
launcher.setResults(text, filterRows(text))
|
||||
end
|
||||
|
||||
local function isValidProtocol(cmd)
|
||||
@@ -87,6 +101,7 @@ local function isValidProtocol(cmd)
|
||||
end
|
||||
|
||||
function onActivate(id)
|
||||
if id == "" then return end
|
||||
for _, g in ipairs(games) do
|
||||
if g.id == id and g.run_command and #g.run_command > 0 and isValidProtocol(g.run_command) then
|
||||
noctalia.runAsync('xdg-open "' .. g.run_command .. '"')
|
||||
|
||||
Reference in New Issue
Block a user