feat(ui): add persistent status bar and card grid launcher

The bar is host-owned chrome: the firmware clips apps into a viewport below
it, so no app can paint over it, while /lib/statusbar.lua owns the height,
repaint interval and painting. gui.fullscreen() lets touch calibration take
the physical panel back.

Launcher and settings become grids of square cards (3 across landscape, 2
portrait) via the new gui.setTextSize, ui.label and ui.cardSide. The one
function on the `app` table moves to sys.setTickInterval, alongside the new
sys.appName the bar needs.
This commit is contained in:
2026-08-01 22:50:19 -04:00
parent f5e44885db
commit 114c8c5f72
17 changed files with 356 additions and 96 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ Compared against crosspoint-reader at `src/util/lua/LuaBindings*.cpp`.
`fs.listDirs`, `fs.listFiles`, `fs.exists`, `fs.readFile`, `fs.writeFile`,
`gui.width`, `gui.height`, `gui.fillRect`, `gui.drawRect`, `gui.drawLine`,
`sys.millis`, `sys.delay`, `sys.exit`, `log.debug/info/error`, the whole `http` table,
`app.setTickInterval`, `wifi.status`, `wifi.isConnected`, `wifi.localIP`, and the
`sys.setTickInterval`, `wifi.status`, `wifi.isConnected`, `wifi.localIP`, and the
`init()` / `draw()` / `on_tick()` callbacks. `init()` is required in both, so a
misspelled entry point is an error rather than an app that quietly draws nothing.
@@ -27,7 +27,7 @@ strength a status screen wants. Its `state` vocabulary is a subset: crosspoint r
| Area | crosspoint-reader | slate32 | Why |
|---|---|---|---|
| Input | `input.wasPressed(button)` and friends, 8 named buttons | `input.getTouch`, `getRawTouch`, `touched` | Different hardware. A touch panel has no button names and a button device has no coordinates. |
| Drawing | `gui.drawText(font, x, y, text, color, style)`, `getTextWidth(font, text)` | `gui.drawText(text, x, y, color, bg)`, `textWidth(text)` | crosspoint ships several fonts; this firmware has one built-in font, and needs an opaque background colour because the panel is not e-ink. |
| Drawing | `gui.drawText(font, x, y, text, color, style)`, `getTextWidth(font, text)` | `gui.drawText(text, x, y, color, bg)`, `textWidth(text)` | crosspoint ships several fonts; this firmware has one built-in font scaled by `gui.setTextSize(n)`, and needs an opaque background colour because the panel is not e-ink. |
| Refresh | `gui.refresh(mode)`, `REFRESH_FULL/HALF/FAST` | none | An LCD has no waveform modes. |
| Colour | `COLOR_*` constants, 4 grey levels | `gui.color(r, g, b)` returning RGB565 | 16-bit colour has too many values to enumerate. |
| Shapes | `drawRoundedRect` + `fillRoundedRect` | one `gui.roundRect(...)` with gradient and border | Fill and border derive from a single distance field, so their edges cannot disagree. |