Commit Graph
566 Commits
Author SHA1 Message Date
Kaj SchittecatandClaude Opus 4.8 ba508396fd lua: hiding MQTT actually hides it — apply live, and reach existing installs (v47)
Two reasons it still showed. The settings landing is built ONCE at boot, so
the build-time skip never re-ran after a toggle; each category card is now
remembered and shown/hidden live (flex closes the gap), applied from the
Store switch, the long-press hide and the build itself. And the 'hidden by
default' only fired for blobs older than v46 — anyone already on v46 (every
current tester) kept app_hide=0, so a v47 one-time flip sets the MQTT bit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 14:50:22 +02:00
Kaj SchittecatandClaude Opus 4.8 c717217563 lua: long-press hides built-in tiles, readable store cards, MQTT hideable and hidden by default
Long-pressing a hideable built-in tile (Spectrum, Discover, VNC, Remote,
Web, Terminal, Files, Signal, Mentions) now offers Hide with the same
confirm sheet installed Lua apps use for Remove; hiding sets the same bit
the Lua Store's built-in switches toggle, so the two views agree. Core
tiles (Chats/Contacts/Map/Settings/...) stay unhideable.

Store cards: name and version share the title line and the description
gets its own full-width wrapped line — it was previously squeezed beside
the version badge into an unreadable sliver.

The MQTT bridge joins the hideable list (it is a Settings section, so the
bit gates that section) and ships hidden by default on new installs and on
the v46 migration: it is experimental and forwards message content to a
broker, so it should be opt-in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 14:37:53 +02:00
Kaj SchittecatandClaude Opus 4.8 68f66556d0 lua: Lua Store looks like a store — cards with icon chips, header counts, refresh, real empty states
Catalog rows are cards now (icon chip with the app initial, name, version
badge that turns accent when installed, wrapped description, rounded action
button tinted by action: teal Get, blue Update, red Remove). Section
headers are small-caps accent. A header strip shows 'N apps / M installed'
with a refresh control that re-fetches the catalog on demand — before this
the list was only ever fetched once per session. Loading and unavailable
states are proper cards explaining what to do instead of one dim line, and
sideloaded apps get their own 'Your own apps' section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 14:28:29 +02:00
Kaj SchittecatandClaude Opus 4.8 2791a1aa12 lua: drop the two invented apps — the catalog is conversions of existing apps only
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 14:01:01 +02:00
Kaj SchittecatandClaude Opus 4.8 c2161b4650 lua: delete the native RF Monitor + Airtime — the Lua Store versions replace them
Kaj confirmed the 1.3 ports stand on their own, so the built-in versions
are gone, not gated: ~320 lines of monitor page + helpers removed from
UITask.cpp, ChannelUtil.cpp/.h deleted, and every reference with them —
drawer tiles, APPACT_MONITOR/APPACT_AIRTIME actions, dispatch cases, the
popup-registry row, anyPopupOpen and tab-lock checks, the Store's built-in
hide toggles, and their doc-capture shot (Lua apps stay out of the tour;
the tour itself gets revisited separately).

Also new in the catalog: Nodes (contacts by last-heard with freshness
colours) and Breakout (canvas + per-frame tick + drag-to-move paddle).
Five apps now. V4 reclaims ~4 KB, T-Deck ~6 KB.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:57:28 +02:00
Kaj SchittecatandClaude Opus 4.8 e7343871bb lua: 'Lua Store' everywhere + catalog rows stack title above description
The row anchored the name to the top and the description to the bottom of
a fixed 52px box, so on the T-Deck's line heights they overlapped. Both are
now positioned from measured line heights with the row sized to fit, and
the title is width-capped clear of the action button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:48:18 +02:00
Kaj SchittecatandClaude Opus 4.8 ea58ff3d9a lua: scrollable app pages + real line heights; Monitor scrolls, Airtime gets a Reset button
Two API gaps the ports exposed: wada.ui.scroll(true) makes the app body
scroll vertically (games leave it off so swipes still steer), and
wada.ui.text_h(size) returns the actual font line height — the overlapping
labels came from stacking rows on guessed heights.

Monitor 1.3 lays every row out from measured heights, scrolls, and shows
the full 16-entry heard ring. Airtime 1.3 replaces tap-to-reset with a
Reset button top-right (a tap was too easy to trigger by accident).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:45:53 +02:00
Kaj SchittecatandClaude Opus 4.8 8f174c63b7 lua: chart matches the built-in styling + Y-axis labels; app layouts stop overflowing
wada.ui.chart now uses the same recipe as the built-in Monitor/Airtime
charts (panel fill, 1px dark border, radius 6, dim grid, no point dots,
2px series) and gains chart:axis(ticks, gutter) for LVGL's Y value labels
— which draw to the LEFT of the chart, so the apps inset it by the gutter.
Labels gain label:width(px) to wrap instead of running off the screen.

Monitor 1.2: dBm axis, 72-point history, wrapped metrics/feed rows.
Airtime 1.2: % axis, and the chart height is now whatever is left after
the detail block is reserved — the text that fell off the bottom was the
chart claiming a fixed height on short screens.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:41:19 +02:00
Kaj SchittecatandClaude Opus 4.8 fd4659f4ce lua: wada.ui.chart + full radio stats, and RF Monitor/Airtime rebuilt to parity (1.1)
Adds the primitive the ports were missing: wada.ui.chart (two shifting
series, line or bar, settable range) plus rx_events/rx_dropped/tx_pkts/
freq/bw/sf/duty_pct on wada.mesh.stats.

RF Monitor 1.1: live RSSI + noise-floor chart, peak with tap-to-reset,
link-margin grade, RX/min, radio params, colour-coded heard feed, narrow
and wide layouts. Airtime 1.1: live + average utilization bars, peak,
rx/tx air split, duty ceiling, tx budget, packet counters, tap to restart
the window. Native versions stay compiled in until these are field-proven.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:34:06 +02:00
Kaj SchittecatandClaude Opus 4.8 47ec8a2293 lua: install button flips to Remove without reopening + the two ports are labelled SDK examples
The Store trusted a directory re-listing taken immediately after writing the
files; on FAT that can lag, leaving the row reading 'Get' until reopen. The
install result now updates the installed list directly (rescan still runs).

The RF Monitor / Airtime ports lacked the native tools' depth on device, so
they ship as 'RX Log (example)' / 'Air Bars (example)' — wada.mesh demos for
app authors. The native versions remain the real tools; full-parity ports are
future work, not a day-one swap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:29:10 +02:00
Kaj SchittecatandClaude Opus 4.8 14d5b06560 lua: Phase 3 — wada.mesh + wada.net, RF Monitor + Airtime as catalog apps, IDF wiring
wada.mesh: read-only contacts/rx_log/stats/self via thin UITask bridges
(no mesh types cross into the host TU). wada.net.http_get: async on the
existing net worker, http-only, 32 KB cap, one in flight per app, callback
delivered on the UI thread under the guarded pcall. RF Monitor and Airtime
rewritten as Lua catalog apps (live on the VPS with snake); their native
versions deliberately stay compiled in for beta_59 until the ports are
field-proven. lib/lua joined both IDF component builds (P4 verified on
RISC-V). Catalog source tracked at deploy/apps/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:18:12 +02:00
Kaj SchittecatandClaude Opus 4.8 f7a550685c lua: SD adoption migrates /apps too (mkdir the FAT parent so the copies succeed)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:07:24 +02:00
Kaj SchittecatandClaude Opus 4.8 1a1fc0f260 lua: bare .lua files on the card are apps — no manifest needed
Drop myapp.lua into /meshcomod/apps/ on the SD (any reader, the Files
app, USB) and it appears in the drawer named after the file (ver 'dev').
Manifests stay the store's install format; the second scan pass only
picks up ids no manifest claimed. macOS ._* AppleDouble junk skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:03:14 +02:00
Kaj SchittecatandClaude Opus 4.8 7e6ff56a3f lua: rebuild the app drawer when the Store closes over it (fresh installs appear immediately)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:59:30 +02:00
Kaj SchittecatandClaude Opus 4.8 2a60138e16 lua: Snake is store-only on Lua boards + long-press-to-remove on installed tiles
The built-in Snake tile and embedded copy are gone where the host exists,
install it from the catalog like any app (non-Lua boards keep the native
game). Installed app tiles gain a long-press remove with a confirm sheet;
the post-long-press release click is swallowed so the app does not launch
under it. Store 'Remove' and the tile path share one removal helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:57:30 +02:00
Kaj SchittecatandClaude Opus 4.8 ed22bd071c lua: store page fixes — layer_top stacking (drawer covered it) + pre-layout width read
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:50:38 +02:00
Kaj SchittecatandClaude Opus 4.8 6b29714f60 lua: Phase 2 — App Store page, catalog installs, drawer integration, hide toggles
The Store (new drawer tile) lists the VPS catalog (apps.json on
firmware.wadamesh.com, fetched on the net worker like the version check),
installs/updates/removes Lua apps (two files under <root>/apps/, .sav kept
across reinstalls), shows sideloaded apps, and hosts show/hide switches
for the built-in drawer tiles (app_hide bitmask, prefs v46 appended under
the schema's trailing assert). Installed apps appear as drawer tiles and
launch through the host. Catalog + snake 1.0 staged under out/firmware/apps
and live on the VPS (nginx /apps locations added).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:39:35 +02:00
Kaj SchittecatandClaude Opus 4.8 322e4dd6f2 lua: Phase 1 — app host + wada.* v1 + Snake in Lua (hardware-verified)
LuaAppHost: one sandboxed app at a time as an AppPage overlay, every
callback under a 100k-instruction budget + traceback pcall (an app error
is a toast and a clean close, never a reset — proven live when the first
Snake build errored: 4 contained retries, zero leak). Bindings: wada.ui
canvas/label/button + theme colors, hardware-swipe/trackball/touch input,
timer, sys (millis/toast/board/random), per-app KV store under the data
root. Snake rewritten in Lua as the embedded reference app; the drawer
launches it via the host and prefers a user-editable /apps/snake.lua.
CAP_LUA_APPS defaults on for all touch boards. T-Deck: 85.1% flash
(host layer = 13 KB over the VM), app opens at 19 KB PSRAM.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:23:11 +02:00
Kaj SchittecatandClaude Opus 4.8 f2067848a7 lua: Phase 0 — vendor Lua 5.4.7 + PSRAM-capped sandbox spike (GO: +96KB flash, 7.5KB state)
Vendored 5.4.7 core+stdlib under lib/lua (mains excluded), LUA_32BITS
baked into luaconf.h so the VM and embedders share one ABI. LuaHost spike
behind WADA_LUA_SPIKE: PSRAM-only allocator with a hard 256KB cap,
io/os-free sandbox, instruction-budget hook. Measured on the T-Deck:
flash +96KB, state+libs 7.5KB/2ms, hostile while-true contained in 30ms,
zero leak. Inert (byte-identical build) when the flag is off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:00:49 +02:00
Kaj SchittecatandClaude Opus 4.8 46b81c2f71 docs: Lua apps ships as one beta (beta_59), phases become build order
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:52:56 +02:00
Kaj SchittecatandClaude Opus 4.8 379ddfeff6 docs: Lua apps plan + tracker (runtime, wada.* API, store, conversion tiers, phases)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 11:35:25 +02:00
Kaj SchittecatandClaude Opus 4.8 3708eb1811 touch: beta_58 — beta_57 upgrade-bug repair (#229/#230), retry opt-in, Hungarian (#227), lock wallpaper (#228), P4 backups (#231)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
beta_58
2026-08-04 11:00:45 +02:00
Kaj SchittecatandClaude Opus 4.8 2fd578515d touch: P4 backups write to the LittleFS store, not unmounted FFat (#231)
backupInternalFs() still returned FFat on the T-Display P4, but the hot
store moved to LittleFS('storage') at beta_54 and FFat is never mounted
since - every profile export and backup failed at open with 'can't open
file'. The list and restore paths share the helper, so all three heal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:41:02 +02:00
Kaj SchittecatandClaude Opus 4.8 a44d2a2193 touch: repair the #227 Hungarian merge - restore LANG_RO, remap stored ui_lang, dedupe one row
The PR inserted LANG_HU at slot 1 (shifting every stored language choice)
and dropped LANG_RO from the enum while the table still carries all 14
columns, so it did not compile as-is. Romanian is restored to the enum in
the table's column order, a one-time v45 remap keeps every existing user's
language selection, one row had its Hungarian cell pasted twice, and the
enum gained an append-only warning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:30:48 +02:00
Kaj Schittecat 66a7714e90 Merge pull request #227 from pisti87/main 2026-08-04 10:26:22 +02:00
Kaj SchittecatandClaude Opus 4.8 c49fac407c touch: auto-retry is opt-in (default OFF) on top of the #230 schema repair
Per user feedback on beta_57: the retry default is the user's choice to
make. Applies to the v45 migration line, the fresh-install default, and
the pre-UI mesh state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:24:25 +02:00
Kaj Schittecat 10ed6a6e80 Merge pull request #230 from PixPMusic/pixpmusic/prefs-schema-repair 2026-08-04 10:23:59 +02:00
Kaj Schittecat cb17ee80a9 Revert "touch: repair the beta_57 prefs layout shift + auto-retry now opt-in (v45)"
This reverts commit b0c31c9105.
2026-08-04 10:21:41 +02:00
Kaj SchittecatandClaude Opus 4.8 ed2b2cb135 touch: WADAMESH lock-screen wallpaper (#228)
The default lock wallpaper had MESHCOMOD baked into the image pixels
(both the rendered RGB565 embed and the SPIFFS-seeded JPEG) - the beta_56
branding fix only changed the animation text drawn over it. Regenerated
both assets with the WADAMESH wordmark and brand-teal padlock; the JPEG's
size change makes the SPIFFS seeder replace the old copy on next boot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:11:27 +02:00
Kaj SchittecatandClaude Opus 4.8 b0c31c9105 touch: repair the beta_57 prefs layout shift + auto-retry now opt-in (v45)
beta_57 inserted retry_echo MID-struct (between rx_queue and web_mirror)
instead of at the blob tail. The stored cfg is a raw memcpy, so on upgrade
every later u8 shifted one byte: remote_mode inherited remote_landscape's
force-flipped 1 (v37) - every upgraded device booted into remote mode -
map_tile_debug inherited hist_sync_after's 2 (debug overlay on), and
hist_sync_after fell to 0 (blocking chat-flush fallback disabled).

v45: retry_echo moved to the true tail, a one-time repair resets the
shifted run on v44 blobs (originals unrecoverable - beta_57 re-flushed
over them), and auto-retry is opt-in now (default OFF) per user feedback.
Struct gains a loud append-only warning. Layout verified with a host-side
byte-level test of all three upgrade paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 08:33:51 +02:00
István def866d07b Merge branch 'main' into pisti87-hungarian-lang 2026-08-04 07:43:02 +02:00
Pixel Perfect 65f25334c4 fix(prefs): repair beta 57 config migration
Beta 57 inserted retry_echo into the middle of the packed TouchCfg blob, shifting the remote-mode and later fields during migration. Define a v45 layout with retry_echo appended at the true tail and recover ambiguous v44 suffix bytes to safe defaults while preserving the stable prefix. Add a host regression test for v43, broken v44, and v45 blobs.

Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-03 19:01:35 -07:00
Kaj SchittecatandClaude Opus 4.8 84378c06b9 touch: beta_57 notes rewritten to the house style (fuller why-focused prose)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 18:02:31 +02:00
Kaj SchittecatandClaude Opus 4.8 3c0f454d32 touch: beta_57 — community drop: auto-retry (#207), Pager TCXO (#209), SD-store fixes (#211/#212/#213), Discover emoji + SD format fixes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
beta_57
2026-08-03 17:10:10 +02:00
István b64ef39ebd Upgrade actions/checkout from v6 to v4 2026-08-03 17:03:08 +02:00
Kaj SchittecatandClaude Opus 4.8 169971205d touch: run the SD format + paste workers on every board that offers them (#172)
The Format button (and its busy overlay) is compiled for T-Deck, M9 and
V4-R8, and Copy/Paste for every Files-app board, but both deferred workers
in UITask::loop were gated T-Deck-only. Elsewhere the tap set a pending
counter nothing consumed: the notice stayed up forever and the format
latch blocked SD remounting until reboot. Widen the format worker to the
button's gate (via the per-board sdSharedSPI accessor), ungate paste.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 17:02:14 +02:00
Kaj SchittecatandClaude Opus 4.8 f4a6c1b3ad touch: recolor-safe node names in Discover feed + msg-info trace (#223)
A repeater name with an emoji (multi-byte UTF-8 cut at a byte cap) or a
literal '#' desynced the LVGL recolor runs in the Discover feed, visually
killing every row after it; same class in the message-info repeat list.
Names are now UTF-8-boundary-cleaned and '#'-escaped at both sites, and
copyUtf8ReplacingMissingGlyphs no longer emits a split glyph at its cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 16:52:34 +02:00
István ca885dfb85 feat(lang): add Hungarian language 2026-08-03 16:41:45 +02:00
István 4b752919a4 Update i18n.cpp 2026-08-03 16:32:50 +02:00
István 402585d0b5 Update i18n.cpp 2026-08-03 16:25:52 +02:00
Kaj Schittecat e1aceec8a8 Merge pull request #212 from PixPMusic/pixpmusic/sd-prefs-concurrency 2026-08-03 15:52:04 +02:00
Kaj Schittecat 829278c9a2 Merge pull request #213 from PixPMusic/pixpmusic/storage-wdt-state 2026-08-03 15:51:55 +02:00
Kaj Schittecat c64a6eae49 Merge pull request #211 from PixPMusic/pixpmusic/datastore-pref-rename 2026-08-03 15:45:48 +02:00
Kaj Schittecat d9a0040d16 Merge pull request #209 from PixPMusic/pixpmusic/tpager-sx1262-tcxo 2026-08-03 15:45:42 +02:00
Kaj SchittecatandClaude Opus 4.8 78fed3a09d touch: Radio & Mesh toggle for the #207 auto-retry (default ON, opt-out)
'Retry sends until heard' switch under Radio & Mesh gates mikecarper's retry
train (#207): OFF stops new retry trains (an in-flight one finishes its
schedule), applied live and persisted (cfg v44 retry_echo, default ON).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 15:23:19 +02:00
Kaj 8d02fa78e8 Merge pull request #207 from mikecarper/feat/retry-until-echo
Retry until echo is heard
2026-08-03 15:18:29 +02:00
István 568001e1db feat(lang): add Hungarian language v0.3 2026-08-03 11:19:04 +02:00
István f55b9441c9 Update release.yml 2026-08-02 22:15:57 +02:00
Pixel Perfect afd41c393f fix(storage): make the heavy-WDT depth counter atomic
_wdtHeavyDepth() is a plain int, but WdtHeavyGuard is taken from both the
UI/loop task and the core-1 history worker (histFlushTaskFn ->
uiSegRunArmedJob -> uiSegAppendRecords/uiSegCompactWrite, each of which holds
one). Both run at priority 1 on core 1, so ordinary tick round-robin can
preempt between the load and the store of d++ / --d.

That race predates this PR, but this PR makes it likely rather than
theoretical: the new guard in rebootDevice() is constructed immediately
before uiHistWaitWorkerIdle(), a deliberate wait of up to 9 s on the very
worker that also takes the guard. Interleave the two and either

  - the depth strands above zero, so enableCore0WDT() is never called again
    and IDLE0 stays unsubscribed from the task watchdog for the session, or
  - the depth drops to zero while a guard is still held, re-arming the
    watchdog during the flash burst it exists to cover -- which panics
    mid-save and loses exactly the chat history rebootDevice() runs to
    persist.

Use std::atomic with an acq_rel fetch_add and a compare-exchange decrement.
The CAS preserves the original `d > 0` underflow guard, which still matters:
doFactoryReset() calls wdtHeavyBegin() with no matching end because it
reboots, so the counter can legitimately stay elevated and an unbalanced end
must not drive it negative.

Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-02 13:15:06 -07:00
István a35ae6fb0e Update release.yml 2026-08-02 22:11:55 +02:00