Duplicates found between the L1 and L2 frontends, and inside the L2 one:
- geo::fmtLocShare / fmtLatLon / turnDeg / isAhead (GeoUtils.h): the [LOC]
text was built in five places, the turn angle and its "ahead" threshold in
both navigations, coordinates by hand in nine. Tested.
- LiveShareEngine::setEnabled: live share was switched in three places.
- L1 waypoint share uses WaypointModel::shareText; Trail's "Share my pos"
goes through UITask::quickShareMyLocation, so it now sends to a running
live-share session as the home Map page does.
- L2 Widgets.h: switchCreate (one switch size, was four), switchRow with a
state and callback (16 hand-wired copies), switchRowOpens (Bluetooth, WiFi,
GPS), primaryButton (one height for Save / Measure / New area / Update).
GPS: with it off, starting the trail, live share or track back, sharing or
marking a position, or centring the map asks first ("GPS is off") on both
L1 and L2; Cancel leaves it undone. A share or a mark waits for a fresh fix
(a switched-off module may still report its last one), which also fixes the
L1 "Share my pos" sending a stale position. SOS still turns the GPS on itself.
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>
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>
- ui-lvgl: navTextEntry()/TextEntry replace eight copies of popup + field +
keyboard wiring; one byte-capped insert callback instead of two.
- ui-new: drawHeadedBubble()/BubbleMark replace the duplicated DM and channel
bubble drawing in MessagesScreen.
- GpsSky::halt(): stopping the receiver ends an unfinished search but keeps
the first-fix time; keyboard cursor blink restarts after a key.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VeBrxKyHHxWsmttVkUdBrj
A group row's text column (and an info row's key) grows into what the
controls on its right leave, and LVGL lays out children before their
parent, so its labels were first measured 1 px wide; LVGL also works out a
new label's height at its old width (0) before the real one. Each height
that changed then took another pass up the screen: 4-6 passes per screen.
rowsFit(), run before a frame's layout (LV_EVENT_REFR_START) and by
layoutNow() in place of every explicit lv_obj_update_layout(), gives each
new row's growing child the width the flex will give it, worked out from
the other children's styles and text, and labelFit() measures wrapping
labels at their real width up front. The grow stays, so a control that
can't be sized ahead only falls back to the old passes.
Layout on the device: Display page 34 -> 24 ms, Bot 33 -> 18, Quick
37 -> 22, Radio 26 -> 18, Diagnostics 20 -> 12. Sim screenshots of 26
screens unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found by counting flushes on idle screens in the sim:
- The compose field's cursor blinked (a redraw every 400 ms) as soon as
a conversation opened, the keyboard hidden: lv_keyboard_set_textarea()
focuses the field, and LVGL only stops a blink when the cursor moves.
fieldFocus() sets the state and nudges the blink; also used for the
WiFi and channel fields, which left theirs running.
- lv_obj_align_to() restyles on every call, so the status bar's icons
redrew every second; placeLeftOf() moves them only when they move.
- Text colours set every second (nav bar, GPS status, Diag errors) go
through setTextColor(), which skips an unchanged colour.
- A LV_LABEL_LONG_DOT label writes its "..." into its own text, so
setText() never matched and rewrote it every refresh (the nav bar's
hint); labelShows() reads past the dots.
- The map area, the area-outline, trail and vector-label layers were
invalidated on every map refresh (every 3 s, a full-map redraw); now
only when the view or what they draw changed.
Idle map: 17 -> 1 flush in 5 s; list and settings screens: 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dead code gone: anim::fadeHide, radioctl::presetCount, the L2 board's
setSdPower / setGrovePower / expanderOK (awRead, gnssReset now private).
- buttonBar() / barButton() replace 7 copies of the popup button row.
- confirmBody(): one red-button confirm for reboot / power off, reset
counters, admin commands, preset and scope delete.
- tapConfirmed(): the 11 "tap again" buttons share one mechanism, 3 s
everywhere, the label restored when left alone.
- noteLabel() for ~30 wrapped notes.
- localTm() in NodePrefs.h and one MONTHS table: lvgl, MsgExpand, the L1
clock and lock screen.
- The sim keeps UI settings in an in-memory nvs::, so one set of load /
save helpers serves both.
- Asleep, the loop wakes every 50 ms (the button / touch poll), not 20.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Map tools: TRAIL, LIVE SHARE and ARRIVAL ALERT each with their own options
page (that section of Map options; back returns to Map tools), the arrival
alert switch where its state is shown, OFFLINE MAPS (Map areas, Live
tiles; the separate Download an area is gone -- a running or unfinished
download shows at the top of Map areas) and LAYERS.
Map areas: picking one frames it on the map above a small sheet (no Show
button, the map above isn't dimmed); closing the sheet, however it's
closed, puts the map back where it was and drops the outline -- it used
to stay on the map. New popup kind POP_BOTTOM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Download an area: a frame with four corner handles on the map (kept in
world coordinates, the map pans / zooms under it); a bar gives its size,
zoom range, tile count and size, the trails switch and Get; areas on the
card are outlined
- Map tools > Map areas: the downloaded areas (map/AreaStore.h,
/sdcard/maps/areas.txt) -- show (framed, outlined), rename, fill gaps,
refresh (force re-download), trails on / off, delete (in steps, keeping
tiles another area covers)
- TileDownloader: force and per-job trails options
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>