The light theme read as the dark one inverted. Now something selected (a
tab, a segment, a tile, Fav) is a tint of the accent with the accent's text
(SEL_*), the full accent fill stays for the primary action; setting values
read in grey (VALUE); popups, the banner and the toast have a quiet grey edge
(EDGE), the toast is a dark pill; neutral greys the RGB565 panel keeps
neutral; the big clock graphite.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings > Display > Theme: Dark / Light (NVS mc_ui/light). The colour
tokens are set once before anything is built, so a change restarts the
device. Text on an accent fill is the new ON_ACCENT (it was BG, white
in the light theme); each accent has a deeper hand-picked light variant
that reads on white and takes white text. The map's empty-tile fill and
grid and the areas' outlines follow the theme too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
L2: a Flashlight app on Home (a lightbulb icon added to the fonts): a
white layer over everything, the backlight at 100 %, no auto-off; a tap,
the side or the top button puts it away and the brightness back.
L1: Tools > System > Flashlight, the whole OLED lit at full contrast
until a key. Not on e-ink.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Density from less chrome instead of smaller rows (ROW_H stays 44):
- titled screens drop the status bar; the title bar (APPBAR_H) holds back,
the title, the screen's actions and the time/battery on a pill; the status
bar returns for Home, the map, typing, the quick panel and the lock
- one radius (RADIUS) for everything tapped: buttons, tabs, choices, chips
- tabs are all segmented at TAB_H in the body (GPS, Clock converted)
- Nodes: chips row + sort + status line become one toolbar row with
Show / Order choices; Messages' All/Favourites is the same choice
- nav map: the target bar only while there is a target; the pin opens one
"Places" popup; back from a map options page restores the map and Map
tools as left, without a jump
- node detail actions at the top of the scroll; Home tiles fill the page
- rowsFit() leaves growing labels to the flex (a screen title cut to one
letter after Messages' filter changed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ACCENT_DIM (the accent mixed toward black) came out brown on selected
tabs, chips, segments and own bubbles. They take the accent with dark
text now, as primary actions and the quick panel tiles do:
styleSelected() sets the fill, the pressed shade and every label under
it. Own bubbles: dark text, age and delivery mark (green or red can't be
read on amber); the melody editor's selected note is outlined, the
sounding one filled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The quick panel, as a phone's: pulled down from the status bar (or a tap
on it). Bluetooth, WiFi, GPS, sound, trail and live share switch at a
tap; Advert opens the advert popup (moved here from the Nodes header);
Lock locks the screen; a brightness slider. Holding a tile opens its
settings. Lock and sun glyphs added to the fonts.
Fixes from rc1 testing on the L2:
- GPS status icon: none when GPS is off (the module kept its last fix
valid, so it stayed green); grey on, green with a fix. ensureGps()
turns GPS on before trusting that stale fix.
- Screen wake: the panel wakes dark, a frame is drawn, then the
backlight fades in -- no white flash. Off fades out first.
- Power off / flat battery: the chip wakes every 30 s to look for USB
power and starts when plugged in (it slept with no wake source before,
until the reset button). Plugged in when switched off: stays off until
re-plugged.
- Message ages in a conversation refresh every 2 s, as on ui-new; the
message popup keeps its age, repeaters heard and delivery up to date.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Battery curve: NodePrefs batt_curve_mv[11] (voltage at 0..100 %, all
zeros = built-in LiPo curve, sentinel 0xC0DE0032). ui-core/Battery.h
uses it for every percentage. L1: Settings > System > Batt curve list
(Left/Right 10 mV, Reset); L2: Settings > Power > Battery curve chart
with draggable points and a line at the cell's voltage.
- L2: the Nodes map is the full navigation map plus the nodes, Back
returns to Nodes; the favourite button is lit while it is one; pinning
to the Home dial uses a thumbtack (fonts regenerated); minimap dots
follow the accent; arranging tiles shows where they land while dragging;
emoji row in Diagnostics > Font.
- Sim hooks: sim_open nodesmap / accent@N / homeedit / battcurve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on the L2 (steady full frames): Settings page 37.7 -> 31.4 ms,
Display 41.5 -> 37.9, Contacts 34.6 -> 32.9, Home 37.3 -> 32.4.
- styleSurface() leaves boxes in the page colour unpainted; styleOpaque()
for the screen and the status bar, which things slide under.
- group() cards clip their corners only while a row is held
(rowPressable(), shared by the tappable rows).
- rowSlider(): the track an opaque tint (theme::mix(), also behind
ACCENT_DIM) instead of 20 % accent blended every frame.
- Map buttons, pills, scale, nav bar and the Home minimap labels opaque.
- Screens drift in without the fading cover: its full-screen blend was in
every entrance frame (page 39 -> 29 ms).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Status bar icons come from ui_icons_14: FontAwesome refitted to one
size by fonts/status_icons.py (falls back to ui_font_12 for the
battery level text), the charging bolt in a tight cell.
- Own channel posts show the repeater count as a small badge, as L1,
instead of a check and a number.
- Message path popup: a stronger connector, roles on the right
(sender / hop N / you), our post's repeaters fanned out under us,
long paths scroll.
- Scrollbars everywhere are thin and hug the edge, clear of the content.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Anim.h: screens emerge from the middle (background cover fades, content
drifts 6 px), Home pages slide, popups and toasts rise and fade in
- Theme.h: accent rules (fill = primary action, dim fill = selected, text =
names/counts/modes), theme layer over the default theme, radius tokens,
accent colour picker (Settings > Display & power > LOOK, NVS mc_ui)
- Splash with the Solo and upstream versions
- Status icons in equal cells, L1-style relay marks, path window with a hop
diagram, tile download popup fits the screen (WiFi only in Settings)
- Perf: uncompressed fonts, two 120-line PSRAM buffers (~48 -> ~33 ms per
transition frame); UI_PERF_TEST harness
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Map tools hold trail, live share and arrival alert, with their options
(schema page "Map options") behind one button; back returns to the map
- Nearby gets an advert button: send now (nearby / everyone) + auto-advert
- Home page 3: Repeater, Admin (list of repeaters and room servers),
Diagnostics
- Settings: display, sound, radio (Bluetooth, WiFi), system, keyboard,
contacts & messages; units moved to Display & power
- Status bar: Bluetooth, GPS, alarm, mute, then auto-advert, trail, live
share, repeater, arrival alert in the accent colour
- Fonts: key and route glyphs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Map screen (Home > Map): Web-Mercator tiles from /maps/{z}/{x}/{y}.png on
the card (Meshtastic MUI layout; per-column TPK1 .pak also read), drag to
pan, +/- zoom, re-centre/follow GPS, Nearby nodes with a position as
markers opening node detail. Tiles decode one per loop pass into a
12-slot RGB565 cache in PSRAM. map/TileProvider.h is the swap point for a
later vector renderer: the screen only calls renderTile(). The tile set's
credit line comes from maps/attribution.txt.
L2 mounts the card over SDMMC 1-bit (CLK 2, CMD 3, D0 1). LVGL's lodepng
is enabled; note its LVGL patch returns an lv_draw_buf_t*, not pixels.
LVGL pool 2 MB for PNG decoding. Fonts gain map / users icons.
tools/maps/fetch_tiles.py prepares a card for an area (presets for
Poland), requires an explicit tile URL (tile.openstreetmap.org blocks
offline use) and stops on placeholder images. The LVGL sim preloads
web/maps into the L2's /sdcard and puts its GPS on Kraków.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ui-core/NearbyModel.h builds the Nearby list (contacts + live [LOC] shares
+ heard adverts, or discover-scan results) with type filter and sort,
moved verbatim out of ui-new's NearbyScreen, which now inherits it.
ui-lvgl: Home is three tiles (Messages, Nearby, Settings). Nearby lists
known nodes with filter chips and a Dist/Recent toggle; tapping a row opens
node detail (distance/bearing, position, last heard, ID) with Message,
Ping, favourite, Add and two-tap Delete. Scan is a popup over the list
with its own model: nodes in range now, not the known set. Fonts gain the
FontAwesome star for favourites. The LVGL sim page adds an optional
repeater so Scan has something to find.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fonts: Noto Sans generated with lv_font_conv (ui-lvgl/fonts/generate.sh,
OFL) replaces ASCII-only Montserrat: European Latin (Latin-1, Extended-A/B),
Greek, Cyrillic + supplement, typographic punctuation, currency, LVGL
symbols + globe; 12/14/16/20 px, clock 40 px digits only (RLE, so
LV_USE_FONT_COMPRESSED is on).
Keyboard (ui-lvgl/Keyboard.h): one layout per script (Latin QWERTY,
Cyrillic, Greek) picked by the same keyboard_main/alt_alphabet prefs as
ui-new, globe key to switch, hold a key for its variants in a popup above
it, one-shot shift, symbols page; compose limit counted in UTF-8 bytes.
First Settings screen (Keyboard: Main / Additional).
Long-press variants and UTF-8 case mapping move to ui-core/KeyboardData.h
and are shared with ui-new, whose Hold-Enter accents gain Romanian,
Turkish, Hungarian, Baltic and Icelandic letters (and ș/ț, Ukrainian /
Serbian letters now capitalise).
Verified on L2 hardware.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New examples/companion_radio/ui-lvgl/ over the shared UI Core (env
Wio_Tracker_L2_companion_solo_lvgl, LVGL 9.2.2, pool in PSRAM):
status bar, home (clock, unread), conversation list (channels + recent
DMs with unread badges), contact picker, conversation view with bubbles,
delivery / relay markers and on-screen keyboard, toasts for Core events,
display auto-off with wake on touch / button. Board glue (LovyanGFX
flush + GT911 touch) isolated in LvglPort.h; design tokens in Theme.h.
UiCore gains the first frontend actions, sendDirectText() and
sendChannelText(), and drives DM auto-resend + unread reconcile from its
own loop (removed from ui-new's loop). MessageHistory exposes newest-first
DM ring iteration and a public contactByPrefix().
Verified on L2 hardware: navigation, send/receive, sleep/wake.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>