feat(ui): on-device channel management, remote admin tool, per-language keyboards

Messages:
- Add/edit/delete channels on-device (new ChannelsView, owned by the renamed
  MessagesScreen — was QuickMsgScreen, whose name no longer matched its scope).
  Channel secret entry supports a typed passphrase (SHA-256'd, same primitive
  the library already uses for the routing hash) or a raw 32-hex-char key.
- MyMesh::setChannelLocal() factors out the setChannel/saveChannels/
  onChannelRemoved sequence previously duplicated across the two
  CMD_SET_CHANNEL branches, shared now by the BLE and on-device paths.

Tools > Admin (new):
- Log into a repeater/room server's admin account and send CLI commands,
  the on-device equivalent of the app's repeater-admin feature.
- Commands are organised into category tabs (System/Radio/Routing/Actions)
  with common get/set fields (name, radio profile, tx power, repeat, advert
  intervals, ...) plus a free-text "Custom command..." fallback for anything
  else. A field row fetches the current value, opens it pre-filled for
  editing, and sends the change — falling back to a blank editor if the
  fetch fails or times out.
- The admin password persists and self-heals exactly like room logins in
  Messages: saved on a confirmed admin-level login, forgotten on a failed
  one, left alone if merely under-privileged.
- New MyMesh::sendAdminCommand()/AbstractUITask::onAdminReply() plumbing so
  a reply reaches the UI without touching the existing BLE/app CLI-terminal
  path (queueMessage's should_display gate is untouched).

Shared TabBar.h extracted from NearbyScreen/BotScreen's independently
duplicated tab-carousel rendering (now a third consumer via Admin) — also
fixes neighbouring tabs vanishing outright when they didn't fully fit;
they now truncate with an ellipsis instead.

Keyboard: the combined "Ext.Latin" alphabet split into 8 separate,
linguistically complete per-language keyboards (Polish, Czech, Slovak,
German, French, Spanish, Portuguese, Nordic), and fixed an OLED-only bug
where tall accented glyphs overlapped the keyboard's separator line
(SH1106's Lemon-font ascent constant was 2-3px short for them).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-07-12 19:40:53 +02:00
co-authored by Claude Sonnet 5
parent 62e82e8740
commit f399298fa6
21 changed files with 1117 additions and 214 deletions
+17
View File
@@ -247,6 +247,22 @@ public:
bool getRoomPassword(const uint8_t* pub_key, char* out_password, uint8_t max_len);
void forgetRoomPassword(const uint8_t* pub_key);
// On-device channel add/edit/delete (Messages > Channels). Shares the exact
// setChannel + saveChannels + onChannelRemoved-cleanup sequence the
// CMD_SET_CHANNEL BLE handler already performs, so both paths stay in sync.
bool setChannelLocal(uint8_t idx, const ChannelDetails& ch);
// On-device "remote admin" (Tools > Admin): send a CLI command to a node
// you're logged into with admin permission (see ClientACL::isAdmin()). The
// reply is a text frame (TXT_TYPE_CLI_DATA) delivered via onCommandDataRecv();
// this just tracks which contact's reply AdminScreen is currently waiting on.
bool sendAdminCommand(const ContactInfo& contact, const char* cmd_text, uint32_t& est_timeout) {
if (sendCommandData(contact, rtc_clock.getCurrentTime(), 0, cmd_text, est_timeout) == MSG_SEND_FAILED)
return false;
memcpy(&ui_pending_admin_reply, contact.id.pub_key, 4);
return true;
}
void savePrefs() { _store->savePrefs(_prefs, sensors.node_lat, sensors.node_lon); }
void saveRTCTime() { _store->saveRTCTime(); }
DataStore* getDataStore() const { return _store; }
@@ -344,6 +360,7 @@ private:
uint32_t pending_login;
uint32_t ui_pending_login; // like pending_login, but triggered by on-device UI instead of BLE/USB app
char pending_login_pw[16]; // password of the in-flight app/USB login, persisted on success for ADV_TYPE_ROOM (see saveRoomPassword)
uint32_t ui_pending_admin_reply; // pub_key prefix of the contact AdminScreen's sendAdminCommand() is awaiting a CLI reply from
uint32_t pending_status;
uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ
uint32_t pending_req; // pending _BINARY_REQ