feat(l1): Status page and screen replace Radio/GPS/Sensors pages and Diagnostics

Home's Radio, GPS and Sensors pages become one Status page: four tiles split
by dotted rules (radio, GPS, battery, nodes), each a headline over a detail.
Enter opens the Status screen, tabs Radio / GPS / Sky / Power / Mesh /
System, which also takes over Tools > Diagnostics and Tools > Satellites
(the sky plot now lives in SkyView.h). GPS on/off moves to Enter on its tab.

New InfoKit.h holds the shared pieces, sized from the font: label/value row
(a long value takes its own line), centred section title, meter, chip, big
number with unit, switch, history line (one sample a minute) and a block
flow that scrolls a tab by whole blocks.

The Status page keeps the old Radio bit and shows when any of the three old
pages did; the save format is unchanged. The L1 degree sign was a cp437
byte the UTF-8 renderer drew as a box; now U+00B0. The perf walk covers
every Home page and Status tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-01 23:51:47 +02:00
co-authored by Claude Opus 5.5
parent 061e5ba36b
commit 4d8724dcc5
9 changed files with 734 additions and 399 deletions
@@ -13,9 +13,9 @@ class ToolsScreen : public UIScreen {
UITask* _task;
enum Action {
ACT_NEARBY, ACT_LIVESHARE, ACT_TRAIL, ACT_LOCATOR, ACT_COMPASS, ACT_SATELLITES,
ACT_NEARBY, ACT_LIVESHARE, ACT_TRAIL, ACT_LOCATOR, ACT_COMPASS,
ACT_BOT, ACT_AUTOADVERT, ACT_REPEATER, ACT_ADMIN,
ACT_CLOCK, ACT_RINGTONE, ACT_DIAGNOSTICS
ACT_CLOCK, ACT_RINGTONE
#if defined(PIN_GPIO1)
, ACT_GPIO
#endif
@@ -54,14 +54,12 @@ class ToolsScreen : public UIScreen {
case ACT_TRAIL: _task->gotoTrailScreen(); break;
case ACT_LOCATOR: _task->gotoLocatorScreen(); break;
case ACT_COMPASS: _task->gotoCompassScreen(); break;
case ACT_SATELLITES: _task->gotoSatellitesScreen(); break;
case ACT_BOT: _task->gotoBotScreen(); break;
case ACT_AUTOADVERT: _task->gotoAutoAdvertScreen(); break;
case ACT_REPEATER: _task->gotoRepeaterScreen(); break;
case ACT_ADMIN: _task->pickAdminTarget(); break; // Admin is remote-only: pick a node first
case ACT_CLOCK: _task->gotoClockTools(); break;
case ACT_RINGTONE: _task->gotoRingtoneEditor(); break;
case ACT_DIAGNOSTICS: _task->gotoDiagnosticsScreen(); break;
#if defined(PIN_GPIO1)
case ACT_GPIO: _task->gotoGpioScreen(); break;
#endif
@@ -129,9 +127,6 @@ const ToolsScreen::Tool ToolsScreen::LOCATION_TOOLS[] = {
{ "Trail", &ICON_TRAIL, ACT_TRAIL },
{ "Locator", &ICON_MAP_WAYPOINT, ACT_LOCATOR },
{ "Compass", &ICON_MAP_NORTH, ACT_COMPASS },
#if ENV_INCLUDE_GPS == 1 && defined(GPS_SKYVIEW)
{ "Satellites", &ICON_GPS, ACT_SATELLITES },
#endif
};
const ToolsScreen::Tool ToolsScreen::COMMS_TOOLS[] = {
{ "Remote Bot", &ICON_BOT, ACT_BOT },
@@ -142,7 +137,6 @@ const ToolsScreen::Tool ToolsScreen::COMMS_TOOLS[] = {
const ToolsScreen::Tool ToolsScreen::SYSTEM_TOOLS[] = {
{ "Clock Tools", &ICON_ALARM, ACT_CLOCK },
{ "Ringtone Editor", &ICON_NOTE, ACT_RINGTONE },
{ "Diagnostics", &ICON_CHART, ACT_DIAGNOSTICS },
#if defined(PIN_GPIO1)
{ "GPIO", &ICON_PINS, ACT_GPIO },
#endif