A DM sent from the MeshCore companion app went out over the mesh but never
appeared on the T-Deck: the wire protocol deliberately doesn't echo sent
messages back to clients, so the on-device UI (a separate consumer) never saw
app-originated sends. Add an appSentMsgToContact() UI hook (default no-op for
non-touch UIs); the touch UI mirrors the message as a local outgoing bubble in
the recipient's thread. Called from the CMD_SEND_TXT_MSG handler on first
handling only (a client/transport retry was already mirrored).
Still open: the receive direction (T-Deck-received messages reaching the app) —
queueMessage already pushes RESP_CODE_CONTACT_MSG_RECV_V3 to all transports, so
that half needs a frame capture against the real app to pin down.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Any command arriving while s_meshcomod_pending_action is non-NONE and
the timeout hasn't expired previously fell through the confirmation
block and was processed normally, letting a second 'tcp off' / 'ble off'
silently overwrite the pending action and lose the original confirmation.
Add a final else clause that blocks the new command and reminds the user
to 'ok' or 'cancel' the in-flight request.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Post-beta_12 touch-UI fixes (T-Deck / Tanmatsu keyboard nav + composer):
Keyboard navigation
- Chat composer auto-edits on open (cursor shows, type immediately); every
OTHER field stays in navigate mode so the letter-nav keys keep working —
press select/Enter to edit it. Enter (or Esc/X on Tanmatsu) on an empty
composer drops back to navigate mode.
- Menu-bar tab-hotkey letters no longer fire while a text field is the focused
element (fixes a stray tab-jump while typing); directional nav still moves.
- New "Show menu-bar letters" setting (off by default) for the tab hotkeys.
Accent box
- The tap-to-pick accent box no longer steals the keyboard-nav focus group
(NAV_SKIP_FLAG) — it's a passive hint, so typing continues and a keybind no
longer navigates. Ready to wire arrow-key selection later.
Composer
- Dedicated "Special characters" picker (% $ @ # & ... currency/math/accents),
separate from the emoji picker.
- Long-press a sent message -> Resend.
Misc
- 12-hour clock honoured everywhere (top bar, chat bubbles, lock screen), not
just the chat overview.
- GPS UART RX buffer enlarged only when GPS is enabled (restores V4 RAM).
- Derive time-of-day from received mesh message timestamps when Wi-Fi/GPS off.
- Self-record the task-watchdog context on a TWDT reset for the crash report.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Room posts arrive as TXT_TYPE_SIGNED_PLAIN with the author in the 4-byte sender_prefix and a bare body. The display path passed the room contact's name, so every post showed the room name. Resolve the author from the prefix and pass it as the per-message sender via a new newRoomMsgFromPubWithMeta hook; the room stays the thread. Tested on T-Deck Plus.
Signed-off-by: Yazutsu <andrzej@gruziel.pl>
Headline: full keyboard navigation (on by default) — WASDZ spatial focus move, S select,
Q back, per-tab hotkeys (E/R/T/U/I) shown on the icons, plus scroll up/down (F/C). Every
key is remappable in Settings -> Keyboard. Foundation for keyboard-first devices like the
Tanmatsu T-Pager (no touchscreen) and a reliable keyboard workflow on the T-Deck today.
Also: #27 receive/flood reboot fix, on-boot crash-report prompt, map zoom +/- buttons (#26),
route-replay wide overview, 'App drawer as home' option. The in-progress Tanmatsu (ESP32-P4)
port source is now public. Mesh America catalog + release.sh kept from main.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- BLE: user-settable 6-digit pairing code (Settings -> Bluetooth), MyMesh::setBLEPin.
- Lock wallpaper: pick via the file manager (fast, any folder) + 'Set as wallpaper'
in the image viewer; downscaling JPEG decoder accepts images > 1024 px and keeps
the held buffer small; clear message for progressive JPEGs.
- Map tiles: validate JPEG magic before caching + re-fetch bad cached tiles
(fixes black quadrants).
- Channel @reply: quick-reply now appends at the cursor instead of wiping the
mention.
- Audio: heap pre-flight before i2s_driver_install (fixes the esp_timer NO_MEM
abort when toggling sound under BLE+Wi-Fi memory pressure).
- App drawer: squircle tiles. Log hygiene: CORE_DEBUG_LEVEL 1->0 (mute benign
vfs/Preferences spam off the USB-CDC companion stream).
- Core bump to core-v1.16.4 (drops the 4-byte chat-payload trailer, issue #13).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New Monitor app (app drawer): live RF sniffer — recently-heard feed
(type / RSSI / SNR / hops, colour-coded), link-margin grade, packet rate,
and an RSSI + noise-floor scope with an on-screen dBm scale; portrait /
landscape aware. Backed by a recent-RX ring buffer in MyMesh (logRxRaw).
- Chat: DM person icon / channel group icon; block non-contact senders by
name; keep scroll position when opening a thread; contacts sort popup
closes on select; long-press popup close-X no longer overlaps buttons.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Core bump: lib_deps -> meshcomod core-v1.16.3 (BLE advertises the node
name not "NimBLE"; GPS won't push a pre-fix ~1902 date).
Tim's quick-wins: Enter-key-sends toggle, 12-hour clock, lock-when-screen-off,
reverse scrollball.
Launcher / map: fix Wi-Fi tiles never downloading under Launcher (the SD-fallback
cache made tilesFsLowSpace() read the unmounted LittleFS as "full"); plot contact
markers before the tile decode so dots aren't ~2s late.
RTC / time: anchored-time guard re-applies UTC when the clock reads garbage
(GPS clobber); blank pre-2020 timestamps so empty channels don't show 1969/1970;
timezone picker (named zones with correct DST) replacing the CET-only base, with
a v2->v3 config migration mapping prior manual offsets onto a Custom zone.
BLE: persist the random pairing PIN (was re-rolled every boot).
Chat: don't auto-jump to latest on a new message when scrolled up; block-by-name
for non-contact room/channel senders (un-blockable room bots).
Power: drop CPU to 80 MHz when the screen is off; enable Wi-Fi modem-sleep only
once associated (enabling it on the unassociated STA broke the setup-wizard scan).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The graph legend now leads with the live signal ('Sig -3dB TX n RX n (tap)').
Tapping the graph (or the legend) opens a Signal & traffic popup: SNR, RSSI,
bars 0-4, how long ago we last heard the mesh, the flood/direct TX+RX totals
since boot, and the auto-discover interval. logRxRaw now also records RSSI for it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a 4-bar signal indicator to the status row, left of the connection icon.
MyMesh::logRxRaw now records the SNR (+ timestamp) of every received packet;
updateGlobalStatusBar maps that to 0-4 lit bars and dims them when nothing's been
heard for 5 min. To keep it fresh when idle, UITask::loop sends a light zero-hop
'discover' advert every 60 s (neighbours only, not flooded -> minimal airtime) so
nearby repeaters/nodes are prompted and their SNR shows up. Home-name cap shrinks
on the narrow V4 to leave room for the bars.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sent messages have no inbound route, so #30's repeater-names had nothing to show
there. Now when we hear an echo of our own flood, capture the re-flooding
repeater (the echo's last path hop) into the echo ring (deduped, bounded to 3),
and list those repeaters by name under 'Repeats heard' in the message Info.
Zero added risk: fixed-size store (no growth), hard buffer guards in the
renderer, read-only contact lookup. Covers #30 in both directions now.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- MyMesh.cpp logRxRaw: the self-echo parser tested (raw[0] & 0x80) for transport
codes, but 0x80 is the top of the payload VERSION field, not a flag. Transport
codes are present iff route_type (raw[0]&0x03) is TRANSPORT_FLOOD/DIRECT. Since
beta_12's region scope, scoped floods carry transport codes -> the parser hashed
the wrong payload slice -> the echo never matched -> 'repeats heard' showed 0 for
anyone with a region set. Now route-type aware (matches uiStashRxMeta). Also fixed
the diagnostic dst= decoder + the header-layout comment.
- MyMesh.h uiSendTraceRoute: walking c.out_path with an unchecked out_path_len
(uint8_t, can be 65..254 if a contact's path is corrupt) overran sendDirect's
payload memcpy -> reboot when tapping 'Trace route' on a sent DM. Clamp to
<= MAX_PATH_SIZE, else fall back to the single-hop trace.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- MyMesh.cpp: strcpy(p->name, contact.name) could overrun the 32-byte advert_paths
name field when an over-the-air advert carries a 32-char (unterminated) name,
corrupting the recently-heard/Found table. Bounded with strncpy + NUL-terminate.
- main.cpp: log nvs_free_entries at boot so a filling NVS (the boot-loop trigger
under Launcher) is visible in serial before it goes catastrophic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First board lands. wadamesh builds the LVGL touch firmware as its own project,
consuming the MeshCore core via lib_deps @ git tag (ALLFATHER-BV/MeshCore
#v1.16.0-wada.0) — no vendored core in this repo. Output is byte-identical to the
in-tree meshcomod build (delta = embedded build-path strings only).
Contents: companion_radio app (MyMesh/main/DataStore), ui-touch LVGL UI,
variants/heltec_v4 board glue, boards/heltec_v4.json, lv_conf, the bundled
ed25519 lib, AsyncElegantOTA, partition table, and a flattened platformio.ini
for env heltec_v4_tft_companion_radio_usb_tcp_touch.
MeshCore-derived files (app glue) remain MIT; ui-touch is GPL — see NOTICE.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Kaj Schittecat <kaj@schittecat.com>