feat(ui): add a home button to the status bar, rename launcher to home

Leaving an app was the app's own responsibility, so one that shipped without
an exit could only be escaped with a reset. The bar now paints a back button
into its leading square and the firmware treats that rect as home, acting on
release so a press sliding into the app cancels. The app it returns to is
/apps/home, which is what it is to the user.

Card grids in home and settings centre left to right as a unit.
This commit is contained in:
2026-08-01 23:13:20 -04:00
parent 6bbe192081
commit b9b620ad2b
10 changed files with 76 additions and 27 deletions
+8 -8
View File
@@ -16,7 +16,7 @@ static constexpr int SD_MOSI = 23;
static constexpr int SD_MISO = 19;
static constexpr int TOUCH_CS = 33;
static const char* LAUNCHER = "/apps/launcher/main.lua";
static const char* HOME = "/apps/home/main.lua";
static constexpr uint32_t ERROR_HOLD_MS = 5000;
// Arduino's default 8KB loop stack is not enough once a TLS handshake runs inside a
@@ -42,7 +42,7 @@ void fallbackScreen(const char* message) {
tft.setTextColor(TFT_RED, TFT_WHITE);
tft.drawString(message, 10, 10);
tft.setTextColor(TFT_BLACK, TFT_WHITE);
tft.drawString("expected /apps/launcher/main.lua", 10, 30);
tft.drawString("expected /apps/home/main.lua", 10, 30);
Serial.printf("halted: %s\n", message);
halted = true;
}
@@ -52,8 +52,8 @@ void startApp(const String& path) {
tft.setRotation(settings.rotationIndex()); // apps may have rotated the frame
statusbar::apply(tft, 0);
Serial.printf("launching %s\n", path.c_str());
if (app.load(path.c_str())) return;
if (path == LAUNCHER) fallbackScreen("launcher failed to start");
if (app.load(path.c_str(), path == HOME)) return;
if (path == HOME) fallbackScreen("home failed to start");
}
void setup() {
@@ -71,7 +71,7 @@ void setup() {
}
settings.load(); // absent file keeps the built-in defaults
net::begin();
startApp(LAUNCHER);
startApp(HOME);
}
void loop() {
@@ -86,11 +86,11 @@ void loop() {
app.loop();
if (!app.running()) nextApp = app.takePendingLaunch();
} else {
// An app that died left its message on screen, and the launcher is about to paint
// over it. Serial alone is no help to anyone holding the device.
// An app that died left its message on screen, and home is about to paint over it.
// Serial alone is no help to anyone holding the device.
if (app.takeFailure()) delay(ERROR_HOLD_MS);
String path = nextApp.length() > 0 ? nextApp : String(LAUNCHER);
String path = nextApp.length() > 0 ? nextApp : String(HOME);
nextApp = "";
startApp(path);
}