Commit Graph
20 Commits
Author SHA1 Message Date
Kaj SchittecatandClaude Opus 5.5 e5a0ebedd7 Merge #754: web T-LoRa Pager simulator, -DWADA_SIM_PAGER=ON (MrYoshii)
Conflict in web/CMakeLists.txt: main's WADA_HOST_BOARD=m9 flavour and the
WADA_SIM_PAGER option both kept, one after the other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:26:27 +01:00
Kaj SchittecatandClaude Opus 5.5 82238d3f7c web: ThinkNode M9 flavour of the host build for scripted d-pad tests
cmake -DWADA_HOST_BOARD=m9 compiles the M9's key path (HAS_M9_KEYBOARD: the
d-pad, the function keys, the Back ladder, the chat message walk) into the
host app on the web board, so M9 navigation runs headless with
--size 320x240 instead of only on a device. The rest stays the web board
(its caps, no SD). platform/WebM9Keyboard.cpp feeds the host keys in as the
controller's bytes.

Scripts: `key NAME [COUNT]` takes a raw byte (`key 0x81` = MSG) and a count
(several keys queued before one render, as on a busy device). The demo
backend takes WADA_DEMO_CHATTER_MS / WADA_DEMO_CHATTER_BURST so messages
arrive at known times.

UITask gates that named the board where they meant its keyboard now name
HAS_M9_KEYBOARD (keyboard backlight level, map pan, nav always on), the nav
globals and CAP_KEYPAD_NAV also take the host flavour, the M9 loop's
lock-screen service sits behind CAP_LOCK_SCREEN and the CardKB drain steps
aside for the M9 keys. Unchanged on every device build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 10:14:01 +01:00
JoshandClaude Opus 5.5 517bb7b80d web: T-LoRa Pager simulator (-DWADA_SIM_PAGER=ON)
The host build laid out as the Pager: 480x222, no touch, keyboard and rotary
encoder as the only input, with the UI's own TLORA_PAGER branches compiled in,
so the Pager's screens can be reviewed and scripted without flashing.

- web/sim_pager/: keyboard/encoder bridge, stubs for the codec, I2S, haptics,
  IMU, charger and gauge, README and a tour script. Environment switches fake
  the hardware states: WADA_SIM_CHARGING, WADA_SIM_CHARGE_HOT,
  WADA_SIM_CARE_HOLD, WADA_SIM_SOC (+ _DROP), WADA_SIM_USE_MA,
  WADA_SIM_FACEDOWN, WADA_SIM_PICKUP, WADA_SIM_BAG.
- Script commands for the Pager: holdkey (accent picker; holdkey space to
  lock; holdkey shift / fn for the modifier shortcuts).
- device_caps.h: a WADA_SIM_PAGER caps block. Off by default; the normal web
  and host builds are unchanged.
- Host fixes it needed: INT_MAX include for glibc, SD.begin(ss, SPIClass&) in
  the SD shim, panelSleep() on WebDisplay.
- Host SPIFFS lists a directory the way SPIFFS does: every file, with its
  folder in the name ("/lock/a.jpg"). The host keeps such files in real
  folders, and readdir() handed the folder back as an entry, which the file
  manager showed as a 0 B file (/lock, /msgs). Affects the host builds only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Josh <8422439+MrYoshii@users.noreply.github.com>
2026-10-26 16:35:53 +01:00
Kaj SchittecatandClaude Opus 5.5 f2c8fc1e6f test: #731 auto-delete old contacts, end to end in the host build
web/platform/board.cpp: WADA_CLOCK_UNSET=1 skips the boot clock set, so
the UI runs as a device before its first sync (timeIsCurrent() false).

web/scripts/contact-purge.sh, three runs on one data dir of the demo
(Femke heard 3 days ago, Old Node 9): Contact Management opens with the
switch off and 30 days; with the clock unset, Old Node favourited, the
switch on and Days = 2, nothing is deleted; with the clock set and
Femke's chat open through the first pass (3 min after boot) Femke and
Old Node both stay; with the Contacts tab open through it Femke is gone
and the favourite Old Node stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:57:03 +01:00
Kaj SchittecatandClaude Opus 5.5 fcda025b08 test: #744 slot recreate in the host build (WADA_PREFS_FILE=1)
web/platform/board.cpp: WADA_PREFS_FILE=1 routes the settings to the
devices' file-backed store (SdNvsPrefs::useFile on SPIFFS "/prefs", as
src/main.cpp does on a board without SD) instead of the host NVS stand-in.
Off by default, so the demo and the tours are unchanged.

web/scripts/prefs-slot.sh: first boot writes prefs/touch.kv; touch.alt is
then made a damaged read-only file; finishing setup saves into that slot;
a reboot must land on Home. With the current SdNvsPrefs.cpp the log shows
"slot b ... recreating it" and the reboot is on Home; built with the
file as it was before #744 the slot never takes the write and the reboot
shows the welcome screen again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 14:11:46 +01:00
Kaj SchittecatandClaude Opus 5.5 27af6f1cfb web: merge web-mobile (phones and tablets) into web-build
The phone branch (portrait/landscape canvas from the window, the phone's
own keyboard, manifest and icons, a one-row bar, mobiletest) next to the
no-threads bundle selection and the Wi-Fi/https chooser messaging. Both
bundles share the one page, so the http copy gets the phone layout too.

Checked after the merge: host build, smoke, webtest (tiles, location,
Store, backups), nodetest (15/15 incl. the location privacy rule),
mobiletest (iPhone 14, Pixel 7, iPad); on the no-threads bundle over
http://<LAN IP>: the browser tour, the mock-node tour, and the mobile tour
(layout + keyboard pass; Bluetooth is not offered there, by design).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:53:02 +02:00
Kaj SchittecatandClaude Opus 5.5 817004c861 web: merge main (repeater admin); the stand-in serves the admin app
Merges main 8954fe06. The drift alarm caught the repeater admin app's new
members: sendStatusPingForUI, sendTelemetryRequestForUI,
uiSendBinaryRequest (-> onBinaryReply), UiReqKind::Binary and
uiLastLoginInfo/UiLoginInfo. Over a node: CMD_SEND_BINARY_REQ and its tagged
PUSH_BINARY_RESPONSE, the ACL and firmware level of a modern LOGIN_OK. The
demo's repeater and room log in (any password = admin, empty = guest) and
answer status, neighbours, the access list, owner info and CLI lines; the
mock node answers neighbours and owner info.

Also from main: nvs_open/nvs_close in the compat (SdNvsPrefs asks first),
and the tiles partition now has to exist before the UI mounts it: the compat
partition table reports "tiles" (the web board's LittleFS volume). Font
guards keep WADA_WEB next to main's new SenseCAP Indicator.

No-threads bundle: a UI-thread wait called from the page (not the main
loop) no longer sleeps (it hung the flush after a Store install).

A wheel turn counts as user activity (no screensaver mid-scroll).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:42:56 +02:00
Kaj SchittecatandClaude Opus 5.5 2fc2288879 web: phones and tablets get a UI that fills the screen
- the canvas is sized from the space below the bar at about one CSS pixel per
  canvas pixel, whole device pixels where possible (crisp): iPhone 14 390x616,
  Pixel 7 360x692, iPad 540x686; landscape by height and the window's aspect
  (664x358, 734x330, 720x506). A computer keeps the framed 800x480. Same
  large-screen layouts, which size themselves from the display.
- a turn restarts the UI in the other layout only when the aspect flips and
  the width changes (a keyboard is no turn), never while typing
- the phone keyboard: no focus ring or tab hotkey letters for it
  (CAP_NATIVE_KEYBOARD in the nav-keys block), keeps up while tapping the UI
  mid-edit; IME composition followed live
- the page: slim one-row bar (slimmer on its side), safe areas, link help as
  an overlay, home-screen icons (icons/app-icon.svg + render.mjs, maskable)
- tests: web/build.sh mobiletest (iPhone 14, Pixel 7, iPad): fill > 90 %,
  UTF-8 + emoji through the hidden field, IME composition, send, turn and
  back with the message kept, chooser, manifest. Labels found by text
  (wadamesh.findText) so taps work at any size; the UTF-8 storage check
  searches bytes. webtest's phone step checks the portrait canvas.
- WEB_BUILD.md "Phones and tablets"; the stray docs/tmp shots removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:12:46 +02:00
Kaj SchittecatandClaude Opus 5.5 c56b5bd885 web: a no-threads bundle for the http copy, and the Wi-Fi/https messaging
The http copy of the page (it can reach a node's plain ws://) is never
cross-origin isolated, so it has no SharedArrayBuffer and no pthreads.
web/build.sh web-nothreads (also built by web) makes a second bundle with
WADA_NO_THREADS: the FreeRTOS tasks are Emscripten fibers (Asyncify) run
after each UI step, every wait a yield point (freertos_coop.cpp); delay,
yield and esp_timer follow; HTTP from a task is an async fetch it waits
for. The page loads nt/wadamesh.js when it is not isolated (serve.py
serves nt/), and never shows developer hints off localhost.

Chooser: on http, Wi-Fi with a link to the https copy for USB, Bluetooth
and the location; on https, "Open the Wi-Fi version" opens the http copy
with the address (#wifi=...), and a ws:// connect that fails there as mixed
content (or times out) explains it with the same button.

Checked against http://<LAN IP>: the browser tour (persistence, tiles,
Store, backups) and the mock-node tour pass on the no-threads bundle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:49:41 +02:00
Kaj SchittecatandClaude Opus 5.5 1524bb5241 web: WIP phones: portrait canvas, phone keyboard, mobile page polish
Work in progress, handed to the web-mobile branch:
- the canvas size is the board's resolution, picked at boot from the window
  (WebDisplay runtime size, host --size WxH); a phone held upright gets a
  480-wide portrait canvas on the large-screen portrait layouts; turning
  the phone restarts the UI in the other layout (data kept)
- the phone's own keyboard: a hidden textarea opened inside the tap's
  gesture, its edits forwarded as UTF-8 text + Backspace/Enter through the
  CardKB path (cardKbUiKey passes BLE_KEY_TEXT through); CAP_NATIVE_KEYBOARD
  keeps the UI's own keys down; the screen slides above the keyboard
- viewport/safe-area/overscroll, web app manifest, More menu (Reset too),
  bar stays on one row, chooser notes for iOS and the http/https copies,
  a mixed-content ws:// failure explains the http copy
- web/scripts/mobile-tour.mjs (iPhone 14, Pixel 7)

Known open: the mobile tour's UTF-8 storage check fails (the bubble shows
the text; the stored history does not match the needle; on desktop,
Playwright's insertText of a non-ASCII char sends no keydown and is lost).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:30:13 +02:00
Kaj SchittecatandClaude Opus 5.5 48a8303db3 web: the Store, Lua apps and backups in the browser
Store: the firmware's own catalog, install and language code over
wadaHttpRequest; http://firmware.wadamesh.com/apps/... becomes the
same-origin fw/apps/... (serve.py and the nginx snippet proxy exactly those
paths). The update check, OTA images and reports stay unreachable
(CAP_FW_UPDATE_CHECK 0); the Store badge fetches the catalog on its own.
CAP_STORE_DOWNLOADS keeps the baked apps and languages as the offline first
load and turns the Apps tab and language downloads on. Other servers
(wada.net) are fetched directly: CORS decides, no open proxy. Installs and
app data live in the backend's IndexedDB data dir.

Backups: the stand-in exports and imports the device's backup file (no
private key); CAP_FILE_HANDOFF downloads an export and imports a file picked
on the computer through the UI's own confirm + import. A restart waits for
the node commands an import queued. The bar's More menu backs up and
restores the whole data dir of this browser as one .tar.

webtest: a Store app installed via the proxy survives a reload and runs; a
backup goes out (download) and into a fresh profile (file picker); a
browser backup restores the app and the settings into another one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:03:11 +02:00
Kaj SchittecatandClaude Opus 5.5 71f1829a2e web: the browser's location is the GPS, map tiles, polish
Location: the web board has CAP_GPS 1. web/platform/WebLocation.* is its
SensorManager + LocationProvider, fed by navigator.geolocation (page shell,
only while the UI's GPS is on, the prompt deferred to a tap) or WADA_GPS on
the host, so the GPS switch, status, map centring, distances and
wada.sys.gps (with speed/course) work unchanged. The position reaches a
connected node (CMD_SET_ADVERT_LATLON, displaced by the Location privacy
radius) only while the node's advert-location setting is "share"; the demo
moves its cast to the visitor's location.

Map tiles: wadaHttpRequest serves the firmware's default tile server only:
a synchronous emscripten_fetch from the tile_fetch pthread to the
same-origin tiles/ path (serve.py proxies it; nginx location for the site),
plain HTTP natively. WiFi reports connected while the browser is online.
Fixes the static-init order of the host VFS (the UI's own tiles LittleFS
copied an empty impl).

Polish: Lua apps that need the board's own radio carry "radio": "own" in the
catalog (baked under CAP_RADIO_TOOLS, greyed in the Store); mouse wheel and
trackpad scrolling; Settings > Wi-Fi / Bluetooth explain the page bar
(CAP_WIFI_SETUP / CAP_BT_SETUP); no Download mode (CAP_USB_FLASH); no
receiver settings on Settings > GPS (CAP_GPS_RECEIVER).

Tests: webtest checks the map centres on Playwright's Ghent location and
shows tiles; nodetest checks the location privacy rule against the mock node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:25:13 +02:00
Kaj SchittecatandClaude Opus 5.5 4534e36250 web: the page connects to a node (USB, Bluetooth, Wi-Fi)
Connect opens a chooser with the transports the browser has (Web Serial and
Web Bluetooth on Chrome / Edge, WebSocket to the node's port 8765 everywhere,
with a note where some are missing). The choice is kept and the UI reboots
into it; each backend has its own data dir (/data/demo, /data/node-<key>) so
demo and node data never mix; a reload reconnects; Disconnect returns to the
demo. The bar shows Demo / Connecting / Connected: <node> over <link> /
Reconnecting, and Reconnect / Pair again when the browser needs a click.
Transports retry a lost link and reopen a granted USB port on plug-in. A node
skips the demo's setup wizard. A link lost mid-handshake no longer reports
ready. web/build.sh nodetest: the flow end to end against the mock WS node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:18:23 +02:00
Kaj SchittecatandClaude Opus 5.5 a986c79cfc web: merge web-companion: the companion backend in both front ends
Backend selection moves into the shared boot: a WadaBackendChoice
(web/mesh/BackendSelect.h) that host_main.cpp fills from --serial / --tcp /
--read-only and web_main.cpp from the page (Module.wadaBackend, with its own
data dir), and board.cpp creates the backend from it. The demo position is
only set for the demo. The companion link reports its state through
g_wada_link_hook (web_main.cpp passes it to Module.wadaLink). The browser
transports' JS joins the Emscripten link as --pre-js. WEB_BUILD.md keeps both
phases' sections. build.sh: "$0" relative to the caller's directory no longer
breaks smoke / serve / webtest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:06:51 +02:00
Kaj SchittecatandClaude Opus 5.5 ee5a85b14e web: every tap reaches the UI (hold a press across LVGL input reads)
The page hands one press/release edge to the UI per animation frame, but LVGL
reads the pointer every 30 ms. A press that lasted a single 16 ms frame (a
trackpad tap-to-click, or a synthetic click) was often never seen, so taps
landed at random. A press is now held for at least 70 ms before its release is
delivered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:01:28 +02:00
Kaj SchittecatandClaude Opus 5.5 b372b91a54 web: Emscripten build of the real UI in a page (web/build.sh web, serve)
pthreads for the UI's background tasks, LVGL + the UI loop on the browser main
thread (emscripten_set_main_loop), IDBFS at /data loaded before main() and
persisted after writes settle and on hide/pagehide; Reboot persists and
reloads. Page shell in the site's Night palette: Demo badge, Connect
placeholder, Reset demo data, Fullscreen; canvas scaled with aspect kept,
crisp at whole device pixels; pointer = finger, keyboard = CardKB codes.
serve.py and nginx-snippet.conf send COOP/COEP; without isolation the page
says so. Release -O2 (wasm brotli 1.14 MB), web-debug variant with -g.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:56:00 +02:00
Kaj SchittecatandClaude Opus 5.5 91fc03fdc0 web: one board boot (board.cpp) for two front ends; panel dirty rectangle
board.cpp owns the board globals and src/main.cpp's setup()/loop() order;
host_main.cpp keeps only the SDL window, event pump and scripted tour, so the
browser front end reuses the boot unchanged. WebDisplay tracks the changed
rectangle for the canvas upload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:55:59 +02:00
Kaj SchittecatandClaude Opus 5.5 b3caafe511 web: companion backend: the real UI drives a MeshCore companion node
CompanionBackend speaks the companion frame protocol (stock MeshCore 1.17/1.18,
wadamesh extras handled) over a CompanionTransport: USB serial and TCP natively
(--serial / --tcp), Web Serial, Web Bluetooth and WebSocket in the browser (JS
glue in web/mesh/js, framing in C++). The stand-in gains the node-only events
(self info, raw RX, login, CLI, regions, contact removal) and computes the RX
log, advert routes, repeats heard and message route info from the node's raw
RX pushes, as the device does. Demo stays the default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:44:58 +02:00
Kaj SchittecatandClaude Opus 5.5 75487cd99b web: acceptance tour + screenshots; radio-tools and screen-mirror caps
web/build.sh shots runs the phase-1 tour headless on a fresh data dir
(onboarding, Home, Chats, a conversation, send, Contacts, Settings,
Device, Apps, the Snake Lua app) and writes web/docs/*.png; smoke runs
the same tour for an exit status only.

device_caps.h gains CAP_RADIO_TOOLS and CAP_SCREEN_MIRROR (default 1,
so every board keeps its tiles) and lets a board block preset
CAP_WEB_BROWSER; the web board turns all three off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:10:23 +02:00
Kaj SchittecatandClaude Opus 5.5 963c75df5d web: host build of the real touch UI (SDL2, demo backend)
The touch UI (src/ui-touch, unmodified apart from WADA_WEB board guards)
builds for macOS with CMake and runs in an SDL2 window: a compat layer
for the Arduino/ESP-IDF/FreeRTOS surface, a MyMesh stand-in with a
MeshBackend interface (DemoBackend now), and the web board's SDL
display/touch/keyboard drivers. WEB_BUILD.md follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:06:04 +02:00