Commit Graph
45 Commits
Author SHA1 Message Date
Tesso M Costa 808ee6e1b4 Merge remote-tracking branch 'origin/main' into at-glance 2026-07-30 10:32:23 -06:00
Kaj SchittecatandClaude Opus 4.8 4942fcf5aa touch: configurable per-chat history limit, default 250, warns when turned off
Second half of the "large message history slows the interface down" report. The
first half (4058f8d) removed the repeated ring scan; this bounds how much history
a single chat can accumulate in the first place, which is what was asked for in
the channel: a configurable limit, with a lower default, and a warning.

Until now the message store was one shared ring with no per-chat bound, so a busy
public channel could occupy essentially all of it. That both starved every other
chat of its history and kept the ring permanently full, which is the condition the
slow paths were suffering under. The reporter had 3800 messages in one channel.

  - New pref hist_per_chat (touch-cfg v42), default 250 messages per chat. Chosen
    to be deep enough to scroll back through a conversation while staying far below
    the 5000-record SD ring, so no single chat can dominate it.
  - Enforced on append: enforceHistoryCap() blanks that chat's oldest records until
    it is back within the limit. It walks from the oldest end, so for the chat that
    is actually over the cap (the one filling the ring) the records it wants are
    found immediately rather than after a full scan.
  - Settings -> Chats: "Keep per chat (messages)" — 100 / 250 / 500 / 1000 / 2000 /
    No limit, with a line explaining that older messages are dropped past the limit.
  - "No limit" is a deliberate choice, not a silent one: it raises a confirmation
    saying a busy channel can then fill the whole store and make things slower. The
    dropdown reverts first and only commits from the confirm handler, so dismissing
    the dialog leaves the previous limit in place.

The thread-history cache from 4058f8d becomes a per-thread COUNT rather than a
bool, since the cap needs to know how many records a chat holds; "has history" is
just count > 0, so the O(1) inbox behaviour is unchanged.

Existing installs pick up the 250 default and will trim on the next message in an
over-long chat. Anyone who wants the old unbounded behaviour can select No limit.

Builds clean on V4 + T-Deck; flashed to the T-Deck.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 17:27:32 +02:00
Tesso M Costa 14d5fdb8b3 touch: add "at a glance while locked" opt-in, fix glance multi-line body
New Options > Lock screen toggle lets the at-a-glance overlay fire while
the device is manually locked too, not just unlocked+idle-dimmed -- off
by default since it makes message text readable off a locked device.
Persisted via TouchPrefsStore (touchPrefsGetGlanceWhenLocked). When it
fires from a locked state, mirrors lockscreenReveal()'s peek path (panel
lit, _manual_lock left alone) rather than wakeScreen() (which would
silently clear the lock).

Also fixes the glance body label: LV_LABEL_LONG_DOT only wraps/dot-
ellipsizes across multiple lines when the label has a fixed height, so
left at auto-height it was effectively single-line everywhere, cropping
longer messages instead of continuing to a second line. Now sized to
the actual space available below it for the current board's resolution
and font.

Adds a T-Deck-only experiment shrinking the glance body font from 28px
to 20px (extras_lat_20 gate widened past Tanmatsu-only to cover it);
easy to revert in isolation per the comments at each site.

Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>
2026-07-30 09:12:05 -06:00
Kaj SchittecatandClaude Opus 4.8 b066c379c0 touch: P4 antenna — internal on every boot, confirm before going external
Reworks the P4 antenna setting so the failure mode it protects against is
impossible by default. Transmitting into an external connector with nothing
fitted is what destroys a PA, so the state you get for free after any power
cycle, crash or OTA has to be the on-board antenna.

  - The on-board antenna is forced at EVERY boot, in two places: the park in
    Xl9535::powerOnSequence() (before the radio object even exists) and a
    re-assert in UITask::begin() in case anything touched IO1 in between.
  - The choice is now session-only and is never written to flash. That is the
    whole point: if "external" could survive a reboot, the safety property is
    gone. touchPrefsGet/SetP4Antenna are removed; the p4_antenna byte stays in
    the struct as reserved so TOUCH_CFG_VER does not have to rewind.
  - Selecting External raises a confirmation naming the MMCX socket and the
    risk. showConfirm has no cancel hook, so the dropdown reverts immediately
    and is only re-selected from the confirm handler — a dismissed dialog
    therefore leaves both the UI and the hardware on internal.
  - The dropdown reads the live xl9535.antennaMode() rather than a stored pref,
    so it can never claim an antenna the hardware is not actually on.

Also renames the modes from the opaque Auto/Pinned A/Pinned B to Internal /
External / Auto (legacy). The reasoning for treating IO1 as an antenna select
rather than a TX/RX path switch is written up on Xl9535.h: a per-transmit
switch must settle within microseconds of the PA ramping, and an I2C expander
write on a bus shared with touch, the RTC and the fuel gauge cannot do that,
while the SX1262 has DIO2 for exactly that job. Which LEVEL is which antenna is
still unconfirmed against LilyGo's schematic, but the SAFE level is known from
the field: the legacy mode sits LOW to receive and every P4 receives fine at
+12 dB, so LOW demonstrably radiates into something connected, while HIGH was
only ever used for transmit and is the suspect. One named constant
(INTERNAL_LEVEL) flips the mapping if the schematic ever says otherwise.

Builds clean on the P4 IDF target plus the V4 and T-Deck S3 envs (the shared
TouchPrefsStore change); compile-verified only, the P4 is off the USB bus.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 13:51:15 +02:00
Kaj SchittecatandClaude Opus 4.8 d6c0321472 touch: P4 LoRa antenna control, to settle the outbound-signal deficit
Field reports say a T-Display P4 transmits far weaker than it receives: one user's
repeater hears his P4 at -10 dB while the P4 hears the repeater at +12, and his
T-Deck is +12/+12. Decisively, the SAME P4 under other P4 firmware gives symmetric
numbers, so it is not his hardware, and that firmware also offers an
internal/external antenna choice which we do not.

Reading the variant, our whole RF path rests on one never-validated assumption.
XL9535 IO1 is labelled "SKY13453 VCTL (LoRa TX/RX path)" with the comment "polarity
TBD on-device", and we flip it around every transmit. But this expander has NO other
antenna-select line -- all 16 IOs are power rails, screen, touch, ethernet, C6, SD
and the SX1262 reset/DIO1. If IO1 is actually the internal/external ANTENNA select,
then toggling it per transmit means we send on one antenna and listen on the other,
which is exactly a large outbound-only deficit on a unit with an external antenna
fitted. A second user reporting symmetric +11.8/+12.0 does not refute it: that was a
two-floor link where SNR saturates in both directions and would mask the loss.

I will not gamble on that assumption: if IO1 really is a TX/RX switch, pinning it
would break transmit or receive outright. So this adds a Radio setting (P4 only):
  Auto (switch per transmit)  - the existing behaviour, and the DEFAULT, so an
                                untouched device is bit-for-bit unchanged
  Pinned A / Pinned B         - hold the line in one state for both TX and RX
Whichever pinned option gives symmetric Trace SNR both ways is the correct antenna,
and that result also tells us what IO1 actually is. The labels are deliberately A/B
rather than Internal/External because we do not yet know which is which.

Applied live on change and re-applied at boot, next to the V4 FEM-LNA precedent.
Stored as touch-cfg v41, a trailing field defaulting to 0, so existing installs
migrate with no behaviour change.

Builds clean on all 8 S3 envs plus the T-Display P4. Cannot be verified here: no P4
is on USB, and the answer needs an on-air SNR comparison anyway.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 13:19:13 +02:00
Kaj SchittecatandClaude Opus 4.8 17651bcd90 touch: fix blocked senders, muted notification sound, and a latched Wi-Fi scan gate
Three community-reported bugs, two of which turned out to share one cause.

#177 blocking a channel sender did nothing. Group packets carry no per-sender
pubkey (MyMesh's channel branch passes from_pub = nullptr), so the prefix ignore
list is never consulted for channel traffic and the only live filter is the name
one. But the block path stored a PUBKEY whenever the sender happened to be a saved
contact, so the block was recorded, shown in the blocked list, and filtered
nothing. Channel blocks now always write the name entry; a saved contact also
keeps its pubkey entry so DMs stay blocked as before. Unblock is now paired, so
clearing one entry clears its twin instead of leaving the sender half-blocked.

#184 lost notification sound until a restart. s_tile_fetch_pending gates all four
chime paths and is only ever ++/--, never reset, so one leaked increment mutes the
device for the rest of the boot. queueTileForFetch ignored
ensureTileFetchTaskRunning()'s result, and that function creates the QUEUE before
it can still fail on the worker's 8 KB contiguous-DRAM stack: queue alive, worker
dead, every send incremented a counter nothing could drain. Honor the result.
Not a beta_50 regression, the sound path was untouched in that release.

#171 Wi-Fi never reconnecting after a reboot. Same worker. Opening the Wi-Fi page
drops the link and raises the scan gate, which is lowered only when the tile
worker reports s_wifiscan_done. If that worker never starts, the gate latches:
autoreconnect stays off and main.cpp suppresses its reconnect retry, so Wi-Fi is
dead until a reboot. Added a 30 s recovery deadline, far longer than any real
sweep, so it can only fire when the normal completion path is genuinely lost.

Also corrected the stale comment that described the signal probe as a flood. It
is a zero-hop NODE_DISCOVER_REQ that repeaters answer directly and never
re-broadcast, and it is skipped entirely when a direct neighbour was heard in the
poll window. That wording is where issue #80's "spams the mesh" concern came from.

Verified: all 8 S3 envs plus Tanmatsu build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 10:54:20 +02:00
Dan Vybiral fdaf48402c touch: sync-fallback for failing chat saves, with a configurable threshold
EIO persisted on the core-1 flush task, which narrows the failure to
shared-SPI interleave rather than core-0 starvation alone: the one
always-working configuration is the LOOP TASK writing (reboot persist)
-- when it writes, nothing else interleaves radio traffic between the
SD transactions on the shared bus. (The pager port notes flagged
exactly this: 'keep an eye on SD-write + RX overlap during history
flush'.)

The flush now self-heals: after N consecutive failed background writes
it retries synchronously on the loop task (one UI hitch per flush while
degraded), and a single success flips it back to the async task. N is a
new setting (Settings -> General -> 'Chat save fallback', dropdown
Off/1/2/3/5/8, default 2; Off = background retries only). Stored as
TouchCfg v40 trailing field hist_sync_after with getter/setter.

Builds verified: all five SD-relevant touch envs.

Signed-off-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-07-26 18:37:46 +02:00
041dd60b8d touch: beta_46 — control-center redesign, Do Not Disturb, contact safety + board fixes
- Contact-loss fix (microSD devices): atomic temp+swap saveContacts, unified robust
  boot SD-mount ladder, and a storage-truth line in the Store-on-SD setting.
- Heltec V4-R8: route MISO for the shared FSPI bus so the microSD mounts; wake-from-sleep
  freeze fixed (panel sleep goes through LovyanGFX's own bus, not the HSPI shim).
- Do Not Disturb (originally PR #156 by Tesso Codemonkey / @codemonkeybr): scheduled
  sound-silencing window in Settings > Sound + a status-bar bell.
- Control-center redesign: round icon-only chips that spread to fill each row (T-Deck 2x4,
  V4 portrait 2 rows), frosted-glass panel, real lock glyph + dynamic bell/bell-slash DND
  chip + keyboard icon+word chip (new cc_icons_16 FontAwesome font), per-chip confirmation
  toasts, press-grow clip fix, and a V4-portrait status-bar BLE/clock overlap fix.
- LilyGo T-Pager: map tile cache falls back to the microSD under the launcher (fixes the
  "storage error / reflash the tiles partition" dead-end).

Co-Authored-By: Tesso Codemonkey <798026+codemonkeybr@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:30:05 +02:00
Tesso M Costa 5c97d02fbe Merge remote-tracking branch 'origin/main' into tlora-pager-port-lr1121
Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>

# Conflicts:
#	NOTICE
#	platformio.ini
#	src/ui-touch/UITask.cpp
#	src/ui-touch/device_caps.h
2026-07-14 10:45:53 -06:00
Kaj SchittecatandClaude Opus 4.8 831959ea5c touch: beta_43 - web control panel becomes a full remote app + V4 map-tile fix
The browser control panel gains full Chats / Contacts / Discovered / Settings
tabs (search, sort, filter, per-contact actions, notifications + live refresh,
ACK/repeats, add-from-discovered, live radio settings, quick-command picker).

Heltec V4 map tiles: fixed the "only the top renders" bug on the 2 MB-PSRAM
board with a persistent tile-buffer pool + viewport culling (no more per-render
128 KB churn/fragmentation). Adds an opt-in "Tile debug overlay" (Map options).

Also: V4 physical-keyboard input in remote/VNC, clearer remote-access screen,
complete Terminal help on device + web, WADAMESH header + status icons.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 16:29:08 +02:00
Kaj SchittecatandClaude Opus 4.8 3f375f2fe4 touch: beta_41 - VNC + REMOTE web mirror (experimental)
Stream the live LVGL UI to a phone/desktop browser over the WS companion
server (VNC app) plus a headless REMOTE mode that renders the UI at a
browser-friendly resolution. Non-blocking per-client TX buffering, a
core-0 stream task guarded by a recursive mutex, an on-page Rotate
orientation toggle, and a small 480x288 render upscaled in the browser.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 22:32:25 +02:00
Tesso M Costa 49a6f80419 pager: let D/F nudge a focused slider, quieten default volume
No touch or trackball on this board means a focused lv_slider (Control
Center brightness, a Settings slider, the Map zoom bar, ...) couldn't
be adjusted at all via keypad nav. D/F now drive it through
navMoveDir()'s existing slider-capture branch -- the same proportional
step, live-update, and persist-on-release the T-Deck trackball's
LEFT/RIGHT already does -- instead of a fixed one-unit-per-press step
that's wrong for every slider's range.

Also lower the pager's default notification volume to 50%: its ES8311
codec + NS4150B amp run louder at a given percentage than the T-Deck's
I2S amp/Tanmatsu's ES8156, so the shared 70% default clipped into
uncomfortable territory on this board specifically.

Signed-off-by: Tesso M Costa <tesso.martins@gmail.com>
2026-07-08 13:59:19 -06:00
Kaj SchittecatandClaude Fable 5 b3004b85eb fix(esp32): use_sd toggle follow-up — both directions on Launcher installs (PR #123 review)
Two edges from the #123 review:
- The raw-NVS mirror is best-effort now: on installs with unusable NVS
  (Launcher) the file write is the authoritative copy, so a failed mirror
  no longer fails the setter.
- When prefs actively live on the SD card, the toggle also rewrites the
  SPIFFS copy of touch.kv (record-preserving; new SdNvsPrefs::fileFs()
  accessor tells the setter which fs is active). Without this, boot's
  SPIFFS fallback kept reading the stale use_sd=true and SD storage could
  be turned on but never off again where NVS is broken.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 11:06:02 +02:00
Steve GlennerandCursor a7d435b03b fix(esp32): honor use_sd from touch prefs at boot
UI stores the SD toggle in /prefs/touch.kv via SdNvsPrefs; boot only read
raw NVS. Dual-write on change and read NVS with touch.kv fallback so SD
storage selection survives reboot.

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Steve Glenner <steveglenner@hotmail.com>
2026-07-07 10:58:58 +02:00
Kaj SchittecatandClaude Fable 5 01900296f3 touch: beta_35 — worker-thread history flush, radio memory guards, 30.5 KB DRAM freed, crash-safe prefs
- History flush runs on the core-0 worker (snapshot + storage-busy gate +
  bounded shutdown wait): kills the V4's multi-second ui:hist stalls and
  the refuses-to-wake-after-message symptom (SPIFFS GC off the UI thread).
- BLE + Wi-Fi runtime enables share the boot co-init heap guard (50 KB
  free + 20 KB block): refuse with a toast + revert the switch instead of
  panicking (BLE) or silently not starting while claiming on (Wi-Fi).
- Internal DRAM: static footprint 95,365 -> 64,908 B (30.5 KB freed):
  serial_interface -> PSRAM; 23 keyboard layout maps const'd -> flash;
  nine rings/tables -> psAlloc PSRAM (UITask/TouchPrefsStore/MyMesh);
  unused TinyUSB MSC + DFU-mode class drivers stubbed out of the link
  (usb_unused_class_stubs.c) — CDC + runtime-DFU untouched, double-flash
  verified over the stubbed stack.
- DataStore prefs writes are crash-safe (write .tmp, swap) with a
  self-healing loader (.tmp recovery) and a truthful save result up to
  the profile-name toast — fixes the boots-with-default-name-once report.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:34:24 +02:00
Kaj SchittecatandClaude Fable 5 4e1ac2ca6b touch: beta_34 — buffered LoRa receive ON by default (test channel) + core pin core-v1.16.5
Consumes the new core (buffered receive drain task + RX counters, #13
stock payload layout, GPS-date guard). Fork side:
- TouchPrefs v33 rx_queue, DEFAULT ON for the test channel (fresh
  installs + a one-time migrate for upgraders); opt-out toggle
  'Buffered receive (experimental)' in Radio & Mesh, applies live.
- About live tier shows LoRa RX heard/read/err/late-lost/qdrop, the
  field evidence for the missed-messages fix.
- Spectrum parks/resumes the drain task around raw radio use; MyMesh
  setParams sequences hold the radio mutex.
- TanmatsuLoraRadio: no-op API stubs (P4 keeps its own RX path).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:15:52 +02:00
Kaj SchittecatandClaude Fable 5 11939a744e touch: beta_31 — WhatsApp-style chats tab (avatars + previews) with per-channel custom icons
- Default chat list: 56px rows with a round initials avatar in the thread's
  FNV-hue signature colour, last-message preview (getThreadLastMessage ring
  accessor), time top-right, unread pill + @ below; compact chat mode keeps
  the dense 34px contact-style rows (layout mode mixed into the rebuild sig)
- Per-channel avatar emoji: 'Chat icon' in the thread-settings sheet (tap =
  emoji sheet in new pick mode, long-press = reset to letters); persisted in
  a chmute-style keyed blob (touchPrefsGet/SetChannelEmoji, 24 x 48B)
- Fix: name/preview overlap (LONG_DOT labels need fixed one-line heights)
- Thread-sheet grid gap 6->4 so the 7th channel cell keeps one screen on T-Deck

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 21:07:42 +02:00
Kaj SchittecatandClaude Fable 5 8eb63a7edd touch: beta_29 — clock floor for room-server replay guards, BLE repeats-heard, deep SD history, one-screen popups
- ClockFloorRTC on all boards: persisted monotonic send-timestamp floor (touchPrefs v32),
  garbage-set rejection, trusted-backstep cap; Join no-reply watchdog + server clock
  skew warning from the LOGIN_OK timestamp prefix (issue #89 follow-up)
- BLE repeats-heard: own-echo RX-log frames pass to BLE one-shot; the #46/#54
  congestion skip stays for everything else (issue #94)
- Mirror app-sent channel messages on-device (was Tanmatsu-only from birth)
- Chat delete: persist the ring purge; mesh-channel drop prefers the pinned slot
- Deep SD history (5000-msg ring) + date separators; chat-list rows restyled compact
- Popup unification: popupClose() + k_popup_registry drive dismiss/count/swipe-block
- Thread/channel sheet as one-screen 2-col grid (contact-sheet layout)
- Keypad nav: strip LVGL SCROLL_ON_FOCUS from collected widgets (About-page jump);
  update dot no longer focusable; verchk waits for an IP + retries with backoff
- Tanmatsu: FIRMWARE_RELEASE_TAG from git describe (drop the hand-bumped hardcode)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 10:07:16 +02:00
Kaj SchittecatandClaude Fable 5 b90b8bac14 touch: beta_28 — room-server session fix (#89), ST7789 panel sleep, wyvern feedback batch
- Rooms: re-enable the keep-alive pinger (checkConnections), arm a 128s
  keep-alive on LOGIN_OK (servers send 0), blank-relogin self-heal while a
  room chat is open, 'Log in again' in the room sheet, read-only warning.
  Root-caused against simple_room_server: 3 unACKed pushes freeze a client
  until the server hears from it — and we never pinged (issue #89).
- Burn-in: ST7789 SLPIN/SLPOUT on screen-off (backlight-off alone kept the
  panel driving the static image), lit-lock dim guard on all boards, 10s
  notify-wake re-dim, lock clock pixel drift.
- wyvern.red batch: scroll-keys map zoom, backspace exits empty composer,
  Reset path in the chat sheet, compact chat toggle (TouchPrefs v31),
  clearer delivery glyphs + tap-to-resend on failed sends.
- OTA: hide Install-update when the running image's physical address falls
  outside the esp_ota running slot (mixed/legacy tables; beta_21 coredump).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 13:40:02 +02:00
Kaj SchittecatandClaude Opus 4.8 492d0886ec touch: beta_25 (test) — contacts-list refresh, advertise-on-boot, Tanmatsu SD tiles + persistence
- Contacts list rebuilds on advert (force past the count-cache) + a count-delta safety
  net, so a node discovered off-tab or added by the phone app shows immediately (#73)
- New "Advertise on boot" toggle in the Advertise app, off by default (#76)
- Tanmatsu: cache Wi-Fi map tiles on microSD (the P4's internal FFat metadata layer is
  broken — f_getfree/f_stat lie); read tiles via open() not the misreporting exists()/size()
- Tanmatsu: persist contacts/channels/chat on microSD (DataStore secondary FS + chat
  history) so they survive reboot; identity/prefs stay on the (working) internal FFat
- Tanmatsu: boot fix (drop Serial.begin re-init of USB-Serial-JTAG), MQTT disabled, popups
  fit + scroll, keyboard-nav scoped to the open popup, 2000 contacts, Large UI default
- Emoji/quick-reply Esc/red-X closes the popup not the chat; lock-screen unlock after msg-wake

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 23:28:13 +02:00
Kaj SchittecatandClaude Opus 4.8 03e50b0609 touch: beta_21 — first stable build + test channel, MQTT bridge, contacts & signal-probe fixes
New: stable/test update channels with an opt-in "Get test builds (beta)" toggle on
OTA devices (switches both the update check and what you install); experimental
opt-in MQTT bridge (consent-gated, payload encryption, direct messages off by
default); Portugal (Narrow) region preset (#74); saved-contacts counter in the
Contacts overflow menu (#72).

Fixed: the signal probe is now strictly zero-hop so a repeater can't re-flood it;
the contact list sorts before capping so the most relevant contacts show, with a
"+N more — search to narrow" footer (#73); the blocked-users list opened from
Contacts shows the two-line title bar with a back button; the Contacts overflow
popup fits the screen again.

Also lands the two-channel release tooling (scripts/release.sh stable/beta modes +
gen-flasher-meta channel arg), the docs site, and the MQTT reference decryptor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:34:11 +02:00
Kaj SchittecatandClaude Opus 4.8 b4c941f954 touch: beta_20 - spectrum analyzer, custom sounds, saved Wi-Fi, V4 high-gain RX, flood-scope + channel-send fixes
New: Spectrum analyzer app; custom notification sounds (SD WAV per event);
saved Wi-Fi networks with auto-join; unified chat settings screen; per-channel
mute; Heltec V4.3 high-gain receiver (FEM LNA) toggle; Apps button on the V4
home screen; Blocked list reachable from Contacts + chat settings; Portuguese
(BR) UI language.

Fixed: touch-screen flood adverts now region-scoped so region repeaters relay
them (#68); channel sends matched by name so a message can't go out on the
wrong channel's key; opt-in "scope direct messages to region" so room-server
logins work through a region-only path (#64); Wi-Fi scan no longer cancelled
by the reconnect retry (empty SSID list).

Under the hood: flood-scope rework (channel vs direct floods); Spectrum owns
the SX1262 while open and restores mesh RX on exit; wifiScanIsActive() gate;
FEM KCT8103L LNA wired; TouchPrefsStore migrations for the new prefs. Adds the
previously-untracked device_caps.h.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 23:33:44 +02:00
f6192aa6e5 touch+deploy: opt-in OpenTopoMap style + persist map link-lines (open PRs)
Implements the three open PRs, with OpenStreetMap kept as the shipping default and
OpenTopoMap added as a user toggle (the deploy PRs flipped the default to topo —
this keeps OSM default and makes topo opt-in).

PR #61 (@Yazutsu) — persist the map 'Show link lines' toggle across reboots:
TouchCfg gains map_show_links (cfg v20, default 1); saved in mapOptLinesCb, loaded
in begin().

PR #52/#53 (@samuelcoustet) — OpenTopoMap tile proxy, adapted:
- deploy: tiles.wadamesh.com.conf keeps the default /{z}/{x}/{y}.jpg on OSM and
  adds /opentopo/ (OpenTopoMap) + an explicit /osm/ alias; tile-transcode.py grows
  _fetch_tile_png/_tile_response_from_png helpers feeding /osm + /opentopo while the
  root route stays OSM.
- firmware: new map_style pref (cfg v21, 0=OSM default, 1=OpenTopoMap) + a
  'Topographic map' switch in Map → Options. Topo tiles are namespaced on disk
  (/tiles/topo) and fetched via the proxy's /opentopo route, so the OSM and topo
  caches never collide and toggling is instant for already-cached tiles. Topo
  bypasses the OSM-only microSD packs and always fetches online; the shared
  (z,x,y) fetch-dedup ring is cleared on toggle so the new style re-queues.

Legal: OpenTopoMap map tiles are © OpenTopoMap (CC-BY-SA) over © OpenStreetMap
contributors (ODbL) + SRTM. The on-map © attribution and the Options → Info credits
sheet switch to that text when topo is active; the proxy keeps a contactable
User-Agent + 14-day cache per OpenTopoMap's tile-usage policy.

Topo needs the VPS deploy (restart wadamesh-tile-transcode + reload nginx) before
the /opentopo route serves; until then topo tiles 404 (handled as a permanent miss,
no retry hammer). OSM default is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Yazutsu <andrzej@gruziel.pl>
2026-06-26 18:49:41 +02:00
Kaj SchittecatandClaude Opus 4.8 59b1b2ab09 touch(tanmatsu): beta_17 — Vol± gestures, message LED, microSD, backups on FFat, status-bar fixes
- Vol+ short = top-bar dropdown toggle; long hold = sound master toggle
- Message-notification LED: flash on new message, soft green glow on unread; toggle in Display settings
- Backups use the internal FFat partition (export/scan/import) + Import button on the Backups page
- microSD browsable in the file manager (P4 SDMMC slot 0; the C6 radio's slot 1 untouched)
- Status-bar icon overlaps fixed (charging-slide + language indicator now SC-scaled with the cluster)
- Vol- screen sleep/wake/lock (screen-lock work)
- Companion link: TCP server start + BLE bond NVS persistence + app-sent channel-message mirror

All Tanmatsu changes gated #if defined(HAS_TANMATSU); T-Deck/V4 bins stay byte-identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 17:30:55 +02:00
Kaj SchittecatandClaude Opus 4.8 79b4f10c25 touch: V4 Sensors tab + Home env widget only when sensors present
Refines the Expansion-Kit UI (#29) so it doesn't intrude on a bare V4: the
Sensors tab and the Home environment widget now appear only when an actual
environment sensor (BME280 / GXHTV3) is detected at boot — battery and GPS no
longer count, so a V4 without the Expansion Kit board shows the normal 5-tab
layout and a clean Home (no empty "Batt ----" / "Temp ...." lines). Adds a
"Show Sensors tab" toggle in Display settings to hide it even when sensors are
present (applies on restart). Tab indices resolve at boot so Settings shifts
back to slot 4 when the Sensors tab is absent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 14:34:29 +02:00
Kaj SchittecatandClaude Opus 4.8 278b31cc92 touch: keyboard navigation OFF by default (Tanmatsu stays on)
Reverses the v15 force-on. New installs and existing T-Deck/V4 devices now
default to keyboard-nav OFF (a v18 one-time migration flips existing installs
to off); the user's later explicit on/off then persists. The Tanmatsu is exempt
— it has no touchscreen, so keyboard nav is its only input and stays on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 09:39:28 +02:00
Kaj Schittecat cd2dc8b3f8 Merge PR #38: touch — optional trackball edge-scroll (tun0) 2026-06-23 23:22:34 +02:00
Kaj Schittecat f4fb7171e5 Merge PR #22: touch — beer emoji, status-bar unread tap, new-contact toast toggle, Czech accents (Vybo)
# Conflicts:
#	src/helpers/esp32/TouchPrefsStore.cpp
2026-06-23 23:22:23 +02:00
Kaj SchittecatandClaude Opus 4.8 069aeb8908 touch: keyboard-nav typing fixes, dedicated symbol picker, 12h everywhere
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>
2026-06-23 23:18:34 +02:00
Ruben Laban bb86a32b04 touch: add optional edge-scroll for trackball cursor mode
When enabled in Settings → Keyboard, pushing the cursor past any screen
edge routes the overflow into the nearest scrollable widget rather than
absorbing it.  Works on regular tab content (lv_scr_act children) and on
lv_layer_top() overlays such as the app drawer.

Implementation:
- tbFindScrollableAt() hit-tests at the vertical centre of the content
  area (avoids status/tab-bar chrome and per-tab headers), searches
  lv_layer_top() before lv_scr_act(), then walks ancestors to the first
  scrollable with room in the overflow direction.
- scroll_by direction is negated relative to raw overflow (scroll_by(+dy)
  moves children down = reveals earlier content = scroll up).
- Scroll amount is capped to lv_obj_get_scroll_top/bottom/left/right so
  we never push past the widget's content bounds.
- Preference persisted as NVS key "tb_edgesc" (default off).
- Map, Snake, and emoji-picker modes are unaffected (they return before
  cursor mode runs).
2026-06-23 14:07:57 +02:00
Dan Vybiral 4a0d7f5247 touch: beer emoji, status-bar unread tap, new-contact toast toggle, Czech accents
- emoji: bake the beer mug U+1F37A and clinking beers U+1F37B as colour glyphs
  into emoji_data.c (now 252) and add the beer mug to the composer picker; the
  clinking pair was already listed but only rendered monochrome, now colour.
- status bar: tapping the unread badge (envelope + count) on the left now jumps
  to the Chats inbox. The CLICKABLE flag is toggled per-tick so only the badge
  state intercepts the tap — every other left-zone state (Back chevron, profile
  name, OSM credit, blank) keeps the bar's control-center / Back tap.
- contacts: add a "Notify on new contact" toggle to the Auto-add page
  (TouchCfg v8, default ON). When off it suppresses the auto-discovery toast
  chip in UITask::notify(); the diag-log line and tab badge are unaffected.
- keyboard: add the Czech accents c-caron, e-caron, t-caron, z-caron, r-caron
  and u-ring (plus uppercase) to the long-press / tap accent popup. Glyphs are
  already baked in the extras fallback fonts, so no font regeneration needed.

Builds verified on both LilyGo_TDeck_companion_radio_touch and
heltec_v4_tft_companion_radio_usb_tcp_touch.

Signed-off-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-06-22 20:37:24 +02:00
Kaj SchittecatandClaude Opus 4.8 1f755ec3b8 touch: beta_11 — bindable keyboard navigation, crash-report prompt, map zoom buttons, app-drawer-as-home; publish Tanmatsu port source
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>
2026-06-22 19:10:40 +02:00
Kaj SchittecatandClaude Opus 4.8 c931df6054 touch: beta_10 — trackball D-pad mode, microSD tile-cache fill, Battery group
- T-Deck: trackball mouse/D-pad navigation toggle (Settings -> Keyboard).
- Map (#20): microSD-tile mode now caches Wi-Fi-fetched tiles onto the SD card so
  the offline library fills in + grows instead of going blank past its edge.
- Power: PR #19 idle power-save (Dan Vybiral / @Vybo) relocated into a new
  'Battery' group under Settings -> System, alongside a button that opens the
  battery / power-history screen.
- TouchCfg v10 (ui_scale, tb_keypad, sleep_idle). Mesh America catalog -> beta_10.

Curated touch overlay onto main (the WIP Tanmatsu ESP32-P4 build system stays on
the tanmatsu-port branch). Co-Authored-By: Dan Vybiral <dan.vybiral@greencode.cz>

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 00:08:13 +02:00
Dan Vybiral 11b31e1cdd touch: idle power-save — loop-throttle + downclock when parked (#19)
Opt-in Idle power-save for the T-Deck: when parked (screen off, on battery, no
companion client, Wi-Fi+BLE off, mesh idle) the main loop is throttled with
vTaskDelay so the FreeRTOS idle task can halt the CPU between ticks, on top of the
existing 80 MHz screen-off downclock — without ever stopping mesh RX. Default OFF
(Settings -> Lock, persisted TouchCfg v8 sleep_idle); status-bar moon indicator +
idle stats. Heltec V4 compiles (gate never passes there). A plain scheduler throttle
rather than esp_light_sleep_start(), which trips INT_WDT in this build.

Co-authored-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-06-21 22:39:59 +02:00
Kaj SchittecatandClaude Opus 4.8 7a63ffe86c touch: beta_9 — crash/Wi-Fi reliability, crash-report export, room fixes, app-drawer icon size
- Stability: Wi-Fi auto-reconnect; corrupt chat-history quarantine (fixes reboot-on-
  receive / inaccessible messages); draw-buffer + flush NULL-guards (boot-panic).
- Crash-report export to SD/SPIFFS (Settings -> About).
- Map: reload purges on-disk tiles offline + visible zoom band; corrupt-tile self-heal
  on load; z15 dedup-key overflow fixed.
- Contacts: favourites always listed (#17).
- Chat: room message send-time (#26) + sender labels; QR share uses the official
  meshcore://contact/add format (#16); unread badge capped at 99+.
- App drawer: icon-size setting (Compact/Large) + smoother scrolling.
- ~5 KB internal DRAM reclaimed (backup arrays + msg_idx -> PSRAM).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:16:04 +02:00
Kaj SchittecatandClaude Opus 4.8 2aa8f59410 touch: beta_8 — Ack reply, map visibility toggles + auto-refresh, RAM trim
- Chat: quick replies insert at the cursor (no longer replace typed text);
  long-press 'Ack' drops a signal-strength + route reply into the composer
  (@mentions the sender on channels); fixed the action-menu overflowing the screen.
- Map: +/- zoom glyph; per-line on-map visibility toggles (coords / tile xyz /
  contacts); microSD-tiles regrouped under a heading; auto-refresh follow button
  with on/off toast; close-X overlap fix when scrolled.
- Perf: ~18.9 KB internal DRAM reclaimed (6 scratch buffers -> on-demand PSRAM).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 14:36:46 +02:00
Dan Vybiral 30fe6fbd6f map/telemetry/battery/snake: visibility, zoom slider, night mode, screenshot
Battery chart: stats line spans the full width so the CPU MHz figure no longer
wraps; the CPU series + chip now use the RF-monitor noise-floor grey (0x4A5256).

Telemetry: the window no longer auto-requests on open — it shows history and a
Request button (async refresh glyph, left of the gear) sends a poll. Legend text
recoloured to the axis-note grey instead of near-black.

Map: the + / - overlay buttons are replaced by a single zoom button that toggles
a full-width zoom slider along the bottom of the map (tap again to hide); the
chosen level is persisted across reboots and wins over the first-open auto-snap.
New 'Night mode (invert)' toggle in Map options inverts tile colours at render
time only (cache untouched), persisted.

Snake: pause/resume button next to the close X.

Status bar: hold for 3 s to capture a full-screen screenshot to
/screenshots/<time>.bmp on the SD card (16-bit BMP — fastest viewable format;
the hold suppresses the control-center tap).

Prefs: cfg v5 adds map_night + map_zoom.
Signed-off-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-06-17 13:47:38 +02:00
Dan Vybiral 373be3e546 settings: option to hide the device name and park the clock left
Signed-off-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-06-17 09:54:03 +02:00
Kaj SchittecatandClaude Opus 4.8 e9ece7bf6b touch: tester feedback batch + Launcher/RTC/BLE fixes + timezone picker
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>
2026-06-16 22:40:55 +02:00
Kaj SchittecatandClaude Opus 4.8 11bd8365d6 beta_5: official-app region scope + contacts/discovered/sound/map overhaul
Companion / core (ported from meshcomod):
- Region/default scope from the official MeshCore app now works: handle
  CMD_SET/GET_DEFAULT_FLOOD_SCOPE 63/64 (companion-v1.16.0.3, issue #31) —
  previously fell through with no reply ("no_event_received").
- US/Canada radio preset corrected to 910.525 MHz / 62.5 kHz / SF7.
- T-Deck +22 dBm TX fix (SX1262 DIO2-as-RF-switch, issue #6) retained.

Touch UI (since beta_4):
- Contacts: person/antenna + red-blocked icons, block/unblock in the popup,
  table with sort/filter + multi-select delete (favourites protected),
  compact time/distance columns, long-name marquee, instant fav-star toggle.
- Discovered: persists across reboots, holds 48, cogwheel settings
  (auto-delete oldest + auto-delete above N hops), "48!" full badge.
- Sound: +/- volume, master toggle, separate Messages/@mention switches.
- Chats: per-row last-message time, per-channel mute, @mention jump-to-message.
- Map: remembers zoom + pan; compact contact popup (no Block button).
- Auto-add on its own page; full-screen settings; refined tab bar; drawer polish.
- T-Deck keyboard backspace at the caret; quick-replies scroll.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 22:34:04 +02:00
Kaj SchittecatandClaude Opus 4.8 a10abe1487 fix theme persistence; control-center back-to-dropdown + themed slider/chips
- Theme reverting on reboot: the boot wordmark reads a pref (UI rotation) BEFORE
  SdNvsPrefs::useFile() switches the backend to files, so the settings blob got
  cached from legacy NVS and file-saved values (accent, brightness, language…)
  were ignored every boot. Add touchPrefsReload(), called right after useFile(),
  to re-read from the file backend. (main.cpp now quote-includes TouchPrefsStore.h
  so it sees the new decl, not the monorepo lib's stale copy.)
- Control center: a settings page opened via a chip long-press now returns to the
  dropdown (not Home) when you tap the bar to go Back — tracked with
  s_settings_from_cc.
- Control center now follows the theme accent: brightness slider indicator/knob
  and the toggle chips use COLOR_ACCENT (chips: solid on / faint off) instead of
  a fixed green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:16:05 +02:00
Kaj SchittecatandClaude Opus 4.8 86c07560e5 perf(nvs): pack 17 scalar touch settings into one blob (shrink NVS footprint)
NVS is a tiny ~20KB partition shared with the Launcher/other apps/Wi-Fi; it was
filling up (Launcher 'Failed to store settings in NVS: 4357', boot loops). The
touch namespace spread 17 scalar settings (brightness, kb backlight, accent,
language, rotation, lock colour, ...) across 17 separate keys. Pack them into one
versioned 'cfg' blob -> ~16 NVS entries reclaimed per device.

One-time migration is crash-safe (write blob, then remove legacy keys only after a
durable write; idempotent via magic+ver), preserves every user's existing settings,
and falls back cleanly if the write fails on an already-full NVS. use_sd/setup_ok
stay standalone (main.cpp reads them at boot); strings, byte-blobs and Wi-Fi slots
are untouched. Public API unchanged; both touch envs build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 22:40:29 +02:00
Kaj SchittecatandClaude Opus 4.8 48cfb55803 firmware: sync touch fixes from the working build
- Wi-Fi scan: watchdog-safe async scan (fixes the no-SSID task-watchdog panic)
- Boot: WADAMESH logo (anti-aliased mark + teal dots) replaces MESHCOMOD wordmark,
  drawn full-res via writePixelsRGB565, centred; LVGL splash mark matches
- Theme: brand teal (#15B6A6) added to the picker + made the first-boot default
- Wi-Fi settings: Save / Scan apply live (Wi-Fi+BLE coexist via NimBLE) — no reboot
- Factory reset: fix SD-storage crash (SPIFFSFS cast on SDFS) + robust recursive
  wipe (rewind / collect-then-delete so FatFS doesn't skip entries)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 15:08:28 +02:00
Kaj SchittecatandClaude Opus 4.8 bc8344b219 firmware: re-point endpoints to wadamesh.com subdomains
- tile server default: tiles.meshcomod.com -> tiles.wadamesh.com
- update-check feed: app.meshcomod.com/api-github/... -> firmware.wadamesh.com/releases/TOUCH
  (same beta_<N> listing shape, so the on-device parser is unchanged)
- 'update manually at flasher.meshcomod.com' -> flasher.wadamesh.com (incl. all 11 i18n langs)
- HTTP User-Agents -> wadamesh-touch

SD data path /meshcomod/ left as-is (changing it would orphan existing users'
on-card data — a brand-rename-with-migration is a separate decision). Tiles stay
plain HTTP (Cloudflare-cached); the lightweight version check stays HTTP too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Kaj Schittecat <kaj@schittecat.com>
2026-06-13 09:01:27 +02:00
Kaj SchittecatandClaude Opus 4.8 ad2f52c6ee refactor: own the touch/app files relocated out of the MeshCore fork
Take ownership of the 26 files moved out of the core during the fork-minimize:
touch HW drivers (helpers/input/*), touch prefs/SD helpers + companion transport
servers + HTTP-OTA helpers (helpers/esp32/*, helpers/*Ota*.h), LVGL PSRAM
allocator, and touch diag. Three transport headers switched to lib-style
<helpers/...> includes for the new layout. platformio.ini builds them
(helpers/** filters + -I src) and pins MeshCore @ v1.16.0-wada.1 (the slimmed
fork). Both boards build green + size-identical from the published tag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Kaj Schittecat <kaj@schittecat.com>
2026-06-13 00:30:21 +02:00