Files
slate32/sdcard/apps/launcher/main.lua
T
evan 4e5796fd51 feat(ui): layout toolkit, Lua launcher and touch press events
Apps describe nesting instead of coordinates: /lib/ui.lua borrows CSS block flow,
the box model and auto sizing, and owns hit testing, press capture and the pressed
repaint. The runtime gains require backed by the SD card, on_touch_down/on_touch_up,
text metrics and rounded gradient fills, so the launcher becomes an ordinary Lua app
and the firmware keeps only a fallback screen for an unreadable card.
2026-07-31 22:27:34 -04:00

50 lines
1.4 KiB
Lua

local ui = require("ui")
local BLACK, WHITE = gui.color(0, 0, 0), gui.color(255, 255, 255)
local ACCENT, MUTED = gui.color(0, 120, 255), gui.color(120, 120, 120)
local FACE = {gui.color(255, 255, 255), gui.color(222, 228, 236)}
local FACE_PRESSED = {gui.color(0, 140, 255), gui.color(0, 96, 220)}
local screen
-- Rows are interactive containers rather than plain buttons, so each can carry a
-- name plus secondary text (and an icon later) while still being one tap target.
local function appRow(name)
return ui.button{
pad = {t = 8, r = 10, b = 8, l = 10},
align = "start",
on_press = function() sys.launch("/apps/" .. name .. "/main.lua") end,
ui.text(name),
}
end
function setup()
local items = {
pad = 12,
gap = 8,
color = BLACK,
bg = WHITE,
press_bg = ACCENT,
press_color = WHITE,
gradient = FACE,
press_gradient = FACE_PRESSED,
ui.text("esp32-lcd"),
}
local names = fs.listDirs("/apps")
table.sort(names)
for _, name in ipairs(names) do
if name ~= "launcher" then items[#items + 1] = appRow(name) end
end
if #names <= 1 then
items[#items + 1] = ui.text("no apps in /apps", {color = MUTED})
end
screen = ui.screen(ui.box(items))
log.info("launcher ready")
end
function draw() screen:draw() end
function on_touch_down(x, y) screen:down(x, y) end
function on_touch_up(x, y) screen:up(x, y) end