Public Access
Settings: its rows in five groups
Settings had grown to 21 rows in one list. It opens on five groups (This device, Display, GNSS and radio, Network, System); Enter opens one, Back returns to the groups, and Back from the groups leaves Settings. SettingsMenu holds the groups and which one is open (host-tested: every setting is in exactly one group). The guide, the how-tos, the README, the scripts' messages and the firmware's own name the new paths, such as "Settings > System > Firmware". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace roro {
|
||||
|
||||
// Settings → Debug Console (ADR 0010): the switch, where to connect, and the token, which is shown
|
||||
// Settings → System → Debug Console (ADR 0010): the switch, where to connect, and the token, which is shown
|
||||
// here and nowhere else. Switching on makes a token if there's none; a new one, or one typed by
|
||||
// hand, ends the connection of whoever holds the old one.
|
||||
class DebugConsolePage {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace roro {
|
||||
|
||||
// Settings → Firmware: the running version and its Probation, where to push Firmware Updates, the
|
||||
// Settings → System → Firmware: the running version and its Probation, where to push Firmware Updates, the
|
||||
// project's releases on Gitea (the latest, and the ten before it), and the Update Files on the SD
|
||||
// card (in /updates) to install from.
|
||||
class FirmwarePage {
|
||||
|
||||
@@ -76,7 +76,7 @@ void GnssApp::draw(Canvas& c) {
|
||||
c.drawString(held ? "GNSS is paused" : "GNSS is off", 4, area.y + 4);
|
||||
c.setFont(&fonts::body);
|
||||
c.setTextColor(theme::kMuted);
|
||||
c.drawString(held ? "The LoRa radio is listening, and" : "Settings > GNSS turns it on.", 4, area.y + 22);
|
||||
c.drawString(held ? "The LoRa radio is listening, and" : "On: Settings > GNSS and radio > GNSS", 4, area.y + 22);
|
||||
if (held) c.drawString("Settings pauses GNSS for it.", 4, area.y + 22 + theme::kLineHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace roro {
|
||||
|
||||
// Home screen: the visible Apps as a grid of icons, with the selected one's name under it, or as
|
||||
// a list of names (Settings > Launcher). Select opens one. An App with something going on has a
|
||||
// a list of names (Settings > Display > Launcher). Select opens one. An App with something going on has a
|
||||
// dot on its tile (App::badge, issue #9).
|
||||
class LauncherApp : public App {
|
||||
public:
|
||||
|
||||
@@ -15,7 +15,9 @@ using Row = SettingsMenu::Row;
|
||||
|
||||
void SettingsApp::onEnter() {
|
||||
page_ = Page::Menu;
|
||||
menu_.close();
|
||||
list_.setCount(menu_.count());
|
||||
list_.select(0);
|
||||
}
|
||||
|
||||
void SettingsApp::warn(const std::string& text) {
|
||||
@@ -56,7 +58,12 @@ bool SettingsApp::onMenuKey(const KeyEvent& e) {
|
||||
if (menu_.kind(i) == Kind::Toggle) menu_.toggle(i);
|
||||
return true;
|
||||
case Key::Select: break;
|
||||
default: return false; // Back leaves Settings
|
||||
case Key::Back:
|
||||
if (!menu_.close()) return false; // from the groups, Back leaves Settings
|
||||
list_.setCount(menu_.count());
|
||||
list_.select(menu_.groupIndex());
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
editingRow_ = i;
|
||||
switch (menu_.kind(i)) {
|
||||
@@ -72,6 +79,11 @@ bool SettingsApp::onMenuKey(const KeyEvent& e) {
|
||||
break;
|
||||
case Kind::Toggle: menu_.toggle(i); break;
|
||||
case Kind::Slider: break;
|
||||
case Kind::Group:
|
||||
menu_.open(i);
|
||||
list_.setCount(menu_.count());
|
||||
list_.select(0);
|
||||
break;
|
||||
case Kind::Page:
|
||||
switch (menu_.row(i)) {
|
||||
case Row::Wifi:
|
||||
@@ -194,16 +206,27 @@ std::vector<std::string> SettingsApp::aboutLines() const {
|
||||
void SettingsApp::draw(Canvas& c) {
|
||||
const auto& area = theme::kContent;
|
||||
switch (page_) {
|
||||
case Page::Menu:
|
||||
case Page::Menu: {
|
||||
// An open group has its name on a line of its own, over its rows.
|
||||
theme::Rect rows = area;
|
||||
if (menu_.inGroup()) {
|
||||
c.setFont(&fonts::bold);
|
||||
c.setTextDatum(top_left);
|
||||
c.setTextColor(theme::kMuted);
|
||||
c.drawString(menu_.title().c_str(), 4, area.y + 1);
|
||||
rows.y += theme::kLineHeight;
|
||||
rows.h -= theme::kLineHeight;
|
||||
}
|
||||
widgets::list(
|
||||
c, list_, area, [this](int i) { return menu_.label(i); },
|
||||
c, list_, rows, [this](int i) { return menu_.label(i); },
|
||||
[this](int i) {
|
||||
auto kind = menu_.kind(i);
|
||||
if (kind == Kind::Page) return std::string(">");
|
||||
if (kind == Kind::Page || kind == Kind::Group) return std::string(">");
|
||||
if (kind == Kind::Slider) return "< " + menu_.value(i) + " >";
|
||||
return menu_.value(i);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Page::Text:
|
||||
c.setFont(&fonts::body);
|
||||
c.setTextColor(theme::kMuted);
|
||||
|
||||
@@ -35,7 +35,7 @@ struct SettingsAppDeps {
|
||||
VpnService& vpn;
|
||||
};
|
||||
|
||||
// Settings: every user-facing setting, plus the Wi-Fi, Firmware, Debug Console and About pages.
|
||||
// Settings: every user-facing setting, in groups, plus the Wi-Fi, VPN, Firmware, Debug Console and About pages.
|
||||
class SettingsApp : public App {
|
||||
public:
|
||||
explicit SettingsApp(const SettingsAppDeps& deps)
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace roro {
|
||||
|
||||
// Settings > VPN (issue #8): the switch, "Start with Wi-Fi", importing a `.conf` from the card
|
||||
// Settings > Network > VPN (issue #8): the switch, "Start with Wi-Fi", importing a `.conf` from the card
|
||||
// and forgetting it, and what the tunnel is doing. No key is ever on this page.
|
||||
class VpnPage {
|
||||
public:
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace roro {
|
||||
|
||||
// Settings → Wi-Fi: the On/Off switch, the connection and its details, DNS and NTP servers, and
|
||||
// Settings → Network → Wi-Fi: the On/Off switch, the connection and its details, DNS and NTP servers, and
|
||||
// the Saved Networks: adding one from a scan or by name (hidden), and each one's own page with its
|
||||
// IP setting, Automatic or Fixed (docs/milestones/S1.md, Q113). Owned by the Settings App.
|
||||
class WifiSettingsPage {
|
||||
|
||||
+6
-6
@@ -703,8 +703,8 @@ static const char* const kHelp =
|
||||
"uname the firmware, its version and the chip it is built for\n"
|
||||
"scp [-f] [-P port] <file on the card> user@host:path | scp [-f] [-P port] user@host:path <file on the card> one file over SSH, with this device's key or, in the Shell, a password, to a server the SSH App already trusts; -f replaces a file on the card; `cancel` stops it\n"
|
||||
"ssh user@host[:port] | ssh status | ssh stop a terminal on another machine, in the SSH App; the password is asked there, never here\n"
|
||||
"vpn status | vpn up [seconds] | vpn down | vpn import [path] | vpn forget | vpn auto on|off the WireGuard tunnel (Settings > VPN); import reads /vpn/wg0.conf; with seconds, it goes down by itself\n"
|
||||
"debug status | debug off [seconds] the Debug Console over Wi-Fi (Settings > Debug Console); with seconds, it comes back\n"
|
||||
"vpn status | vpn up [seconds] | vpn down | vpn import [path] | vpn forget | vpn auto on|off the WireGuard tunnel (Settings > Network > VPN); import reads /vpn/wg0.conf; with seconds, it goes down by itself\n"
|
||||
"debug status | debug off [seconds] the Debug Console over Wi-Fi (Settings > System > Debug Console); with seconds, it comes back\n"
|
||||
"debug on | debug token <16 to 64 characters> | debug token new (USB serial only) switch it on, set its token\n"
|
||||
"crash abort|wdt crash on purpose (to test crash reports and Safe Mode)\n"
|
||||
"wifi ip ... try <seconds> | wifi ip keep a trial IP setting: back to the previous one unless kept\n"
|
||||
@@ -897,13 +897,13 @@ static void debugCommand(const String& args, bool fromSerial) {
|
||||
debugResumes = true;
|
||||
console.printf("debug: off for %lu s\n", (unsigned long)seconds);
|
||||
} else if (!fromSerial) {
|
||||
console.println("debug: over USB serial only (or Settings > Debug Console)");
|
||||
console.println("debug: over USB serial only (or Settings > System > Debug Console)");
|
||||
} else if (args == "on") {
|
||||
DebugConsole::switchOn(settings);
|
||||
console.println("debug: on (the token is in Settings > Debug Console)");
|
||||
console.println("debug: on (the token is in Settings > System > Debug Console)");
|
||||
} else if (args == "token new") {
|
||||
settings.setString(Setting::DebugToken, DebugConsole::freshToken());
|
||||
console.println("debug: a new token (it is in Settings > Debug Console)");
|
||||
console.println("debug: a new token (it is in Settings > System > Debug Console)");
|
||||
} else if (args.startsWith("token ")) {
|
||||
std::string token = debug::tidyToken(args.substring(6).c_str());
|
||||
bool ok = debug::validToken(token) && settings.setString(Setting::DebugToken, token);
|
||||
@@ -1141,7 +1141,7 @@ static void runCommand(String line, bool fromSerial = false) {
|
||||
if (found) radioService->setPreset(p);
|
||||
console.printf("lora preset: %s\n", found ? p.name : "unknown (LongFast LongSlow MediumSlow MediumFast ShortSlow ShortFast LongMod MeshCore)");
|
||||
}
|
||||
if (line == "gnss quiet on" || line == "gnss quiet off") { // Settings > Pause GNSS for LoRa (issue #20)
|
||||
if (line == "gnss quiet on" || line == "gnss quiet off") { // Settings > GNSS and radio > Pause GNSS for LoRa (issue #20)
|
||||
settings.setBool(Setting::GnssQuietForLora, line.endsWith("on"));
|
||||
console.printf("gnss quiet: %s\n", line.endsWith("on") ? "GNSS pauses while the LoRa radio listens" : "GNSS stays on");
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace roro {
|
||||
|
||||
// The GNSS receiver on the Cap LoRa-1262 (see CONTEXT.md and docs/milestones/M2.md): reads its
|
||||
// NMEA from the main loop's tick (about 450 bytes/s, so a 512-byte UART buffer covers a second),
|
||||
// holds the current Fix, and sets the clock from it. Settings → GNSS switches it on and off.
|
||||
// holds the current Fix, and sets the clock from it. Settings → GNSS and radio → GNSS switches it on and off.
|
||||
class GnssService : public Service {
|
||||
public:
|
||||
static constexpr int kRxPin = 15, kTxPin = 13; // measured: M2 step 1
|
||||
|
||||
@@ -284,7 +284,7 @@ void UpdateService::serve() {
|
||||
if (r == Request::BackgroundCheck && gitea_.latest(latest) &&
|
||||
release::shouldAnnounce(latest, runningVersion(), failedVersion(), announced_)) {
|
||||
announced_ = latest.tag;
|
||||
notify(latest.tag + " is out: see Settings > Firmware", NotificationLevel::Info); // 48 bytes at most
|
||||
notify(latest.tag + " is out: Settings > System > Firmware", NotificationLevel::Info); // 48 bytes at most
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user