Public Access
The Shell shows the replies to its own commands and nothing else. The console knows who each line is printed for (Console::As, Console::origin): a command run from the Shell prints as the Shell's, and what answers it later from another task carries that along (ls, tasks, du, cp, update check, sd list, screenshot, gemini get). Ctrl+b shows everything instead. This replaces the ten-second window, which was a guess. An App's name with a capital opens it (Notes, Irc, Wifi, Gnss, Gemini, Lora, Storage, Shell, System, Settings), from the Shell and from the consoles. rm needs -r for a folder, here and over the consoles. In the Shell a file, or a folder with something in it, is asked about unless -f; an empty folder with -r goes without a word. The Shell now hands its line to the main loop to run: run from inside the key handler, rm on a folder overflowed the loop's stack and crashed the device. `info` says which App is in front. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
120 lines
3.1 KiB
C++
120 lines
3.1 KiB
C++
#include "app_manager.h"
|
|
|
|
#include "app_keys.h"
|
|
|
|
#include <cstring>
|
|
|
|
namespace roro {
|
|
|
|
AppManager::AppManager(App& launcher) : launcher_(launcher), foreground_(&launcher) {}
|
|
|
|
void AppManager::registerApp(const AppInfo& info) { apps_.push_back(info); }
|
|
|
|
std::vector<const AppInfo*> AppManager::visibleApps() const {
|
|
std::vector<const AppInfo*> visible;
|
|
for (auto& info : apps_)
|
|
if (!info.hidden) visible.push_back(&info);
|
|
return visible;
|
|
}
|
|
|
|
void AppManager::begin() {
|
|
foreground_ = &launcher_;
|
|
launcher_.onEnter();
|
|
redraw_ = true;
|
|
}
|
|
|
|
App* AppManager::find(const char* id) const {
|
|
for (auto& info : apps_)
|
|
if (std::strcmp(info.id, id) == 0) return info.app;
|
|
return nullptr;
|
|
}
|
|
|
|
bool AppManager::open(const char* id) {
|
|
App* app = find(id);
|
|
if (!app || modal_) return false;
|
|
switchTo(*app);
|
|
return true;
|
|
}
|
|
|
|
void AppManager::home() {
|
|
if (!modal_) switchTo(launcher_);
|
|
}
|
|
|
|
bool AppManager::openModal(const char* id) {
|
|
App* app = find(id);
|
|
if (!app) return false;
|
|
switchTo(*app);
|
|
modal_ = true;
|
|
return true;
|
|
}
|
|
|
|
void AppManager::endModal() {
|
|
modal_ = false;
|
|
switchTo(launcher_);
|
|
}
|
|
|
|
void AppManager::handleKey(const KeyEvent& event) {
|
|
if (help_.isOpen()) { // scrolls or closes; nothing reaches the App, Home included
|
|
help_.onKey(event);
|
|
redraw_ = true;
|
|
return;
|
|
}
|
|
if (event.key == Key::Help) {
|
|
std::vector<KeyHelp> rows;
|
|
foreground_->help(rows);
|
|
rows.push_back({"Everywhere", nullptr});
|
|
keys::add(rows, keys::kEverywhere);
|
|
const char* scope = foreground_->helpTitle();
|
|
const char* app = foregroundTitle();
|
|
help_.open(scope ? scope : app ? app : "Launcher", std::move(rows));
|
|
redraw_ = true;
|
|
return;
|
|
}
|
|
if (modal_) {
|
|
foreground_->onKey(event);
|
|
return;
|
|
}
|
|
if (event.key == Key::Home) {
|
|
home();
|
|
return;
|
|
}
|
|
bool consumed = foreground_->onKey(event);
|
|
if (!consumed && event.key == Key::Back) home();
|
|
}
|
|
|
|
std::string AppManager::commandFor(const char* id) {
|
|
std::string command;
|
|
for (const char* p = id; *p && *p != '-'; p++) command += *p;
|
|
if (!command.empty() && command[0] >= 'a' && command[0] <= 'z') command[0] = static_cast<char>(command[0] - 'a' + 'A');
|
|
return command;
|
|
}
|
|
|
|
const AppInfo* AppManager::byCommand(const std::string& command) const {
|
|
for (auto& info : apps_)
|
|
if (!info.hidden && commandFor(info.id) == command) return &info;
|
|
return nullptr;
|
|
}
|
|
|
|
const char* AppManager::foregroundTitle() const {
|
|
for (auto& info : apps_)
|
|
if (info.app == foreground_) return info.title;
|
|
return nullptr;
|
|
}
|
|
|
|
bool AppManager::takeRedraw() {
|
|
bool r = redraw_ | foreground_->consumeRedraw();
|
|
redraw_ = false;
|
|
return r;
|
|
}
|
|
|
|
void AppManager::switchTo(App& app) {
|
|
help_.close(); // an App opened from elsewhere (a Notification, a command): its keys, not the last one's
|
|
if (&app == foreground_) return;
|
|
foreground_->onExit();
|
|
foreground_ = &app;
|
|
foreground_->onEnter();
|
|
redraw_ = true;
|
|
}
|
|
|
|
} // namespace roro
|