feat: app-only settings on the device: privacy, adding contacts, advanced radio

- Settings schema gains Privacy (position in adverts, who can ask for
  status / location / sensors), Adding contacts (all or by type, max
  hops, replace oldest) and Advanced radio (path hash size, double ACK,
  listen before talk, interference threshold, RX boost, RX delay,
  airtime factor); both UIs build their rows from it
- Auto-advert carries position only when Position in adverts is on
- ui-new accordion holds 16 sections and 128 rows
- docs: settings, tools, feature matrix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-10 00:47:03 +02:00
co-authored by Claude Opus 5.5
parent a0a76fbc60
commit 6fba3dfca7
10 changed files with 181 additions and 30 deletions
@@ -96,13 +96,19 @@ void UITask::buildRadio() {
paramRows(g, p, radioctl::currentPreset(p), p->freq, p->sf, p->bw, p->cr, onRadioDropdown, IDS, onRadioFreq,
"Higher = longer range");
groupNote(body, "Everyone you talk to needs the same settings.");
fill(&UITask::radioGroup, 1, 3); // the rest as the loop goes
fill(&UITask::radioGroup, 1, 4); // the rest as the loop goes
}
void UITask::radioGroup(int i) {
using namespace radioview;
NodePrefs* p = _prefs;
if (i == 2) { buildRadioExtras(_body); return; } // my presets, scopes (RadioExtras.h)
if (i == 3) { // the schema's advanced options, a page of their own
lv_obj_t* g = group(_body, nullptr);
listRow(g, LV_SYMBOL_SETTINGS " Advanced", "Path hash size, ACKs, listen before talk, delays",
onOpenSchemaPage, (void*)(uintptr_t)settings::PG_RADIO);
return;
}
lv_obj_t* g = group(_body, "TRANSMIT");
int o = 0;
for (int v = TX_MIN; v <= TX_MAX; v++) o += snprintf(s_opts + o, OPTS_LEN - o, v > TX_MIN ? "\n%d dBm" : "%d dBm", v);
+9 -2
View File
@@ -2399,6 +2399,8 @@ void UITask::back() {
if (_settings_page == settings::PG_NAV && s_opts_from_map) {
openMap(true);
if (s_nav_section >= 0) navToolsPopup(); // one section's options: back into Map tools
} else if (_settings_page == settings::PG_RADIO) {
showRadio();
} else {
showSettings();
}
@@ -3548,6 +3550,7 @@ static lv_obj_t* switchRow(lv_obj_t* parent, const char* text, const char* sub,
#include "MapRegions.h"
#include "HomeScreen.h"
#include "ClockScreen.h"
static void onOpenSchemaPage(lv_event_t* e); // Radio > Advanced
#include "RadioScreen.h"
#include "WifiScreen.h"
#include "ChannelScreen.h"
@@ -4536,11 +4539,13 @@ void UITask::buildAboutPage(lv_obj_t* body) {
// (fill); a popup's list gets them all now.
static lv_obj_t* s_schema_body = nullptr;
static bool s_schema_one = false; // one section: its own page, no heading
static bool s_schema_bare = false; // no section headings
void UITask::schemaRows(lv_obj_t* body, uint8_t page) {
for (lv_obj_t*& c : s_sec_card) c = nullptr;
s_schema_body = body;
s_schema_one = page == settings::PG_NAV && s_nav_section >= 0;
s_schema_bare = s_schema_one || page == settings::PG_RADIO; // one section: the page title says it
uint8_t sec = 0xFF;
bool first = true;
for (int i = 0; i < settings::COUNT; i++) {
@@ -4557,7 +4562,7 @@ void UITask::schemaRows(lv_obj_t* body, uint8_t page) {
// The group of the section setting i starts, with its rows.
void UITask::schemaSection(int i) {
uint8_t sec = settings::ALL[i].section;
lv_obj_t* card = s_sec_card[sec] = group(s_schema_body, s_schema_one ? nullptr : settings::sectionTitle(sec));
lv_obj_t* card = s_sec_card[sec] = group(s_schema_body, s_schema_bare ? nullptr : settings::sectionTitle(sec));
if (sec == settings::SEC_SOUND) buildSoundRows(card, true); // On / Off / Auto
for (int k = i; k < settings::COUNT && settings::ALL[k].section == sec; k++) {
if (settings::ALL[k].offset == offsetof(NodePrefs, lock_compact)) continue; // ui-new's lock look; the slide card has one
@@ -4684,7 +4689,7 @@ void UITask::settingsGroup(int i) {
snprintf(sub, sizeof(sub), aa == ma ? "%s" : "%s + %s", SCRIPT[ma], SCRIPT[aa]);
}
listRow(g, LV_SYMBOL_KEYBOARD " Keyboard", sub, onOpenSchemaPage, (void*)(uintptr_t)PG_KEYBOARD);
listRow(g, LV_SYMBOL_ENVELOPE " Messages & contacts", "Resend, expiry, quick messages",
listRow(g, LV_SYMBOL_ENVELOPE " Messages & contacts", "Resend, adding, expiry, quick messages",
onOpenSchemaPage, (void*)(uintptr_t)settings::PG_MESSAGES);
break;
@@ -4696,6 +4701,8 @@ void UITask::settingsGroup(int i) {
if (pi >= 0) radioctl::presetAt(_prefs, pi, pn, f, b, sf, cr);
snprintf(sub, sizeof(sub), "%s - %.3f MHz, %d dBm", pn, _prefs->freq, _prefs->tx_power_dbm);
listRow(g, UI_SYMBOL_RADIO " Radio", sub, onOpenRadio, NULL);
listRow(g, LV_SYMBOL_EYE_CLOSE " Privacy", "Position in adverts, who can ask for telemetry",
onOpenSchemaPage, (void*)(uintptr_t)settings::PG_PRIVACY);
}
bluetoothRow(g);
wifiRow(g);