Commit Graph
8 Commits
Author SHA1 Message Date
Michael A. Cojocari b5a8c99f55 Complete ThinkNode M9 keyboard parity
Signed-off-by: Michael A. Cojocari <michael.cojocari@gmail.com>
2026-08-25 16:59:15 -04:00
Kaj SchittecatandClaude Opus 4.8 15415fd0f5 i18n: enumerate every user-visible literal instead of grepping for them (49 wrapped, v6)
My earlier sweeps searched for strings I could think of, which is why you
kept finding more. scripts/build/i18n-scan-unwrapped.py now parses every
call that takes user text — LVGL setters (label/checkbox/dropdown/roller/
placeholder/tab/table/msgbox), showAlert, showConfirm, appPageBegin,
createSettingsModal and the settings row helpers — splits the argument list
and reports any human-readable literal not wrapped in TR(). It found 55;
49 got wrapped (--fix does it mechanically), 6 skipped as brand/technical
(WADAMESH, CPU, PSK, OK, and two unit readouts). It now reports zero.

The 33 newly reachable keys are translated in all 13 languages: the Flood/
Zero-hop scope buttons, Share QR, Search contacts, Play / Set as
notification sound / Set as wallpaper, Probe now, On map, Install update,
Save update bin to SD, Choose .wav from files, Power, Clear history, the
Bluetooth/MQTT/Logs/System info sheet titles, both dropdown option lists,
the size preset list, Import, the URL bar, and Snake's New game.

Two format bugs behind the last stragglers: keys whose text begins with
LVGL recolor markup ('#7A7F87 Wardrive: ...#') were dropped as comment
lines by BOTH the device loader and the audit — a line is a comment only
when it has no tab, fixed in both. And several rows had been written with
literal '\xE2\x80\xA6' text where the file needs the real character; the
loader only unescapes \n \t \\, so those keys never matched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 17:46:00 +02:00
Kaj SchittecatandClaude Opus 4.8 471a522d8f touch: put Airtime + Snake on the Spectrum app-page pattern
Both were built from the same template and carried the same three defects, none of
which were really about their own code: they hand-rolled the page chrome that every
other app page gets from the shared machinery.

New src/ui-touch/AppPage.h exports that machinery (appPageCreateRoot / Begin / End /
DeleteRootAsync) so a self-contained module can build the same page the in-file tool
pages do, and both modules now use it.

  1. GEOMETRY. Both positioned their overlay against a local `kTopBar = 22`.
     STATUSBAR_H is a RUNTIME value: SC(22) once the UI scale is above 100%, and
     SB_TOP_PAD + SB_ROW*2 on the T-Display P4's two-row bar. On those boards the
     page sat too high and its own title + close button landed UNDERNEATH the real
     status bar, which is what "the airtime app has issues" looked like. Geometry now
     comes from the live bar height, so a page cannot disagree with the bar.

  2. NAVIGATION. Neither installed s_apppage_title / s_apppage_close, so each needed
     its own case in statusBarTapCb and its own clause in the bar-foreground gate, and
     neither reached statusBarReaderBackCb — the PRESSED fallback that exists because
     the cap-touch swipe detector can drop the lone CLICKED. On a touch-only board
     that left no reliable exit at all. They now install the standard hook, get the
     tall "< Airtime" / "< Snake" bar, and both special cases in UITask are deleted.

  3. TEARDOWN. closeCb ran `lv_obj_del(root_)` and `delete this` synchronously from a
     child button's own event callback, freeing the object LVGL was still dispatching
     to. Teardown is now async throughout: lv_obj_del_async for the root, lv_async_call
     for the instance, one single dismiss() path. Snake's canvas buffer moves to a
     destructor so it is freed after the queued root delete released the canvas.

Also fixes what the rework exposed: applySwipeGesture had swallow-guards for Snake,
sliders, chats, popups, the control centre and settings sheets, but none for app pages
— so a horizontal swipe inside Airtime reached the tab switcher and jumped to the Map
(reported on device). An opaque CLICKABLE root only blocks CLICKS; that detector reads
the touch hardware directly and never consults LVGL hit-testing. One guard now covers
every full-screen page, Spectrum and the rest included, which had the same bug.

Bar titles are copied into module-owned storage rather than holding TR()'s pointer:
TR returns the static table cell for a plain key but a recycled 4-slot ring for an
icon-prefixed one, and s_apppage_title keeps the pointer for the page's lifetime.

Builds clean on V4, T-Deck and the P4 IDF target; flashed + boot-verified on the P4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 15:08:18 +02:00
Kaj SchittecatandClaude Opus 4.8 4e6a9e0108 touch: beta_49 - T-Display P4 fixes (exit traps, screen timeout, UI scale, GPS, control center)
P4-focused beta. Non-P4 boards only pick up minor shared exit-trap code, nothing user-facing.

- Snake + full-screen apps (Monitor/Spectrum/Discover/Web mirror/Advert) exit on status-bar tap
- Screen timeout / standby / burn-in dimming wired for the AMOLED (setBrightness path)
- UI scale pinned to 100% on the P4 (text overflow above 100%)
- No hard-lock on screen-off (P4 has no lock screen yet)
- GPS: L76K detect at 9600 baud, skip boot-detect race, 4096 RX buffer
- Control center dropdown taller on tall screens so the GPS line clears the toggle buttons
- P4 LCD SKU: HI8561 backlight PWM on GPIO51 (fixes the black screen)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 20:34:17 +02:00
Kaj SchittecatandClaude Opus 4.8 49a8f31b8c touch(i18n): full untranslated-text audit + 307 new translation rows
Audited every user-visible string sink across the touch UI and closed the
gaps that had accumulated since the language table was last touched:

- TR() now strips a leading LVGL-symbol glyph (+ spaces) off the lookup key
  and rebuilds the label, so icon-prefixed menu/sheet rows ("<glyph>  Copy")
  translate instead of silently falling back to English.
- Wrapped 95 bare literal sinks (settingsRowLabel / showAlert / showConfirm /
  lv_label_set_text / dropdown / placeholder / checkbox) in TR(); unwrapped 29
  format-only strings that never should have been keys.
- Added 307 missing rows to kI18n[] covering all 11 non-English languages
  (NL DE FR ES IT RU UK BG SR EL PT-BR); keys byte-identical, printf
  placeholders and %-order preserved, Serbian in Cyrillic.

Builds green on T-Deck + Heltec V4; Tanmatsu app 3,169,296 B (107 KB under
the AppFS 50-page load ceiling).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 19:38:07 +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 fe8925f91d apps: Snake review fixes — trackball, New-game gate, full field, tab-bar lock
- trackball now steers Snake (UITask routes motion via SnakeGame::isOpen()/steer()
  and hides the soft cursor on that page).
- a "New game" button gates the start so it doesn't move on open; tap restarts
  after a game over.
- slower tick (220 -> 300 ms).
- playfield fills the unoccupied screen (dynamic cols x rows at kCellPx instead of
  a small fixed square).
- the tab bar is hard-locked while Snake is open so a stray swipe/tap can't slip
  through to the app switcher (e.g. into the map).

Signed-off-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-06-17 09:54:44 +02:00
Dan Vybiral d7151dbbf8 apps: extract Snake into a self-contained SnakeGame class (own files)
Signed-off-by: Dan Vybiral <dan.vybiral@greencode.cz>
2026-06-17 09:54:44 +02:00