feat(lua): pass an argument to init() and let apps name themselves
sys.launch(path, arg) carries a string to the next app's init(arg), nil when there is none. States share no memory, so one string is the whole handoff; anything structured travels as a Lua literal the receiver loads. This is what a screen split across apps needs to say "collect a password for this network". sys.setAppName() retitles the status bar, defaulting to the directory name as before. A setter rather than a declared constant, so one app can retitle per screen. The bar needs no new invalidation path for it -- the name joins rotation and theme in the cache key -- and clips a name wide enough to reach the memory slot.
This commit is contained in:
+17
-5
@@ -31,6 +31,10 @@ LuaApp app(tft, touch);
|
||||
|
||||
bool halted = false;
|
||||
String nextApp;
|
||||
// Carried beside the path, because sys.launch()'s argument has to outlive the state that
|
||||
// passed it: the sender is torn down before the receiver exists.
|
||||
String nextArg;
|
||||
bool nextArgSet = false;
|
||||
|
||||
// Last resort only: the UI lives in Lua, so this exists purely to explain why
|
||||
// nothing else could run.
|
||||
@@ -46,12 +50,12 @@ void fallbackScreen(const char* message) {
|
||||
halted = true;
|
||||
}
|
||||
|
||||
void startApp(const String& path) {
|
||||
void startApp(const String& path, const char* arg) {
|
||||
// Full panel until the app's own status bar module reports its height in load().
|
||||
tft.setRotation(settings.rotationIndex()); // apps may have rotated the frame
|
||||
tft.resetViewport(); // load() re-clips once the new app's bar reports its height
|
||||
Serial.printf("launching %s free=%u largest=%u\n", path.c_str(), ESP.getFreeHeap(), ESP.getMaxAllocHeap());
|
||||
if (app.load(path.c_str(), path == HOME)) return;
|
||||
if (app.load(path.c_str(), path == HOME, arg)) return;
|
||||
if (path == HOME) fallbackScreen("home failed to start");
|
||||
}
|
||||
|
||||
@@ -70,7 +74,7 @@ void setup() {
|
||||
}
|
||||
settings.load(); // absent file keeps the built-in defaults
|
||||
net::begin();
|
||||
startApp(HOME);
|
||||
startApp(HOME, nullptr);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@@ -83,15 +87,23 @@ void loop() {
|
||||
|
||||
if (app.running()) {
|
||||
app.loop();
|
||||
if (!app.running()) nextApp = app.takePendingLaunch();
|
||||
if (!app.running()) {
|
||||
nextApp = app.takePendingLaunch();
|
||||
nextArgSet = app.hasPendingArg();
|
||||
nextArg = app.takePendingArg();
|
||||
}
|
||||
} else {
|
||||
// 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(HOME);
|
||||
bool hasArg = nextApp.length() > 0 && nextArgSet;
|
||||
String arg = nextArg;
|
||||
nextApp = "";
|
||||
startApp(path);
|
||||
nextArg = "";
|
||||
nextArgSet = false;
|
||||
startApp(path, hasArg ? arg.c_str() : nullptr);
|
||||
}
|
||||
|
||||
// Hands the core to the idle task instead of spinning between polls: touch reads are
|
||||
|
||||
Reference in New Issue
Block a user