Past the oldest message in a conversation, Up reads the next 12 from the log.
Pages, not a longer list: the messages screen measures its whole list every
frame. Also from the full-screen view, and for a conversation the ring has lost.
Settings > Messages > Delete after hides older messages at once and frees the
flash a segment at a time, never with the clock unset or behind the log; Delete
history clears the log and the rings. A batch is also written after 12 new
messages, as a room's backlog could leave the ring unsaved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings > Messages > Keep messages (Off, 500, 1000, 2500 in all; off by
default; HIST_FLASH, ui-core/HistoryLog.h). Two append-only logs on the QSPI
flash, channels and DMs, restored into the RAM rings at the start. A batch is
written a minute after the first unsaved change and at shutdown, as the L1's
power switch gives no warning. Each segment has a directory of its own: a
LittleFS 1.x commit erases one of a directory's two fixed blocks every time.
E-ink panels keep their last frame, so a shutdown now leaves "Powered off" on
it and puts the controller into deep sleep.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Home starts on page 0, the Clock. render() chose whether to draw the bar
before moving on from a hidden page, so that frame had none and the next
refresh came 5 s later or on a key press.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Discover: a reply after its try timed out, was stopped or was overtaken
went on to the normal handling and became the contact's route (and sent
a path back); the last tags sent are kept and a late reply is dropped.
Leaving Route on the L2 stops a discovery as it stops a trace.
- Discover: a route whose reply came back another way offers that way too
(L2 There / Back, L1 a Back row), turned round into a route there, so a
trace checks it; the Discover button no longer sits on its group.
- Screenshots: numbered one past the highest (one pass over the folder,
not a stat per number), so one taken after a delete is still the newest.
- Gallery: the newest 300 kept whatever order the folder lists them in;
BMP rows read in the file's order and several at a time; the thumbnail
buffer sized to the page; the folder read once per visit; a failed
open frees or restores the picture.
- NTP: the slot the router's server goes in emptied before joining, so a
cached address isn't taken for it; "Clock set from the network" judged
against the clock a tick before (SNTP has set the system time already).
- Sim: sim_scroll up stops at the top.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Gallery: thumbnails 30 to a page, built only while the screen is still (a decode held the loop and a scroll read as a tap)
- segmented(): CLICK_TRIG, so a swipe starting on a screen's tabs doesn't switch them
- Settings > Device > Home apps removed (hold an app on Home instead)
- platformio.ini: a note that the L2 has no microphone on GPIO15 (verified on hardware)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MyMesh::sendPathDiscovery() shares the request with the app's
CMD_SEND_PATH_DISCOVERY_REQ and hands the reply (the way there and back)
to the UI; PathEditor keeps up to 4 distinct routes with how often each
came. L2: Find the route under Route; L1: Discover row in Path / trace.
Docs: Discover, message routes on the map, Ask status and discovery.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PacketFlow keeps them (each with up to 3 ways it came, contacts by key
prefix) once a frontend asks, in PSRAM; the map frames a replay that's off
screen. Back on the map closes a popup first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first frame (the sprite's default white background, black dots) came out as
a bright bar across the middle of the screen. A plain black frame now, and the
backlight stays off until it's sent: dark through the panel's reset and init
(the LP5814 keeps its state across a restart), lit with the first frame.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A press that silenced the alarm, took a screenshot or woke the screen doesn't
also switch the screen off when it's let go.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The font's line is 18 px (emoji and fallback glyphs), the subtitle label was a
fixed 15: the tails of y, g, j and emoji were cut. Now 18, the title and the
subtitle 1 px further apart; the row stays 44.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
navview::draw (Waypoints, trail back, Nearby, a message's location) shows a
dial beside the lines, or under them on a tall screen (portrait e-ink) where
that makes it larger: with a course a turn dial (the top is where you're
heading, the arrow points at the target, "Turn R 55"), without it the compass
rose. The 4.2" screens keep theirs. On a short screen (the 64 px OLED) the
gap under the distance and the pitch of the lines give way so the ETA is not
cut off at the bottom.
sim_nav_waypoint() opens a waypoint's navigate view from the simulator page.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
An arrow at the target on a round dial whose top is the way you're heading:
turn until it points up. It turns green and the ring doubles when you're
within 12 degrees. The text says how far to turn ("turn right 55") instead of
two bearings to subtract. Standing still there's no course: the arrow greys
out, the top is north and marked red, and the text keeps the bearing.
sim_nav_target() sets a target from the simulator page.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
LVGL's timers stand still while the screen sleeps, so a message that arrived
with wake-on-message off (or in quiet hours, or with a client connected) left
its banner up until the next wake. No banner is shown while asleep now, and
sleep() hides a banner or toast that was up.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Battery display's percent and voltage modes still drew the icon before
the number. Each mode now shows one thing; the title bar no longer has a
battery level to fold away, so only the button words give way to a title.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Same gap as the screens had: the bot reply, a typed message's {temp} and
the placeholder lists read only the sensors, so a board without one (the
L1) answered !temp with n/a while its telemetry carried a temperature.
The fallback moves to LocalSensors.h, shared by the screens, expandMsg()
and sensorPlaceholders(); the latter now takes the chip's temperature.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
USB drive and Format card closed the open map pack and unmounted, while the
tile task could still be reading a tile off the card (a map left open, a
prefetch). Both now wait for it first, as the map's own redraw does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream's flag (meshcore-dev/MeshCore#3290, already set on the L1 OLED
builds) did nothing in the Solo UI. The L1 has a power switch; a pocket
could hibernate it by mistake from the Shutdown page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The telemetry reply adds the MCU temperature, the screens read only the
sensors: on a board without a temperature sensor (the L1) the app showed
a temperature and the clock field '--'. The clock, Status and the L2's
Home now fall back to the chip's, like the reply. The bot's !temp and
{temp} still read only the sensors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The name column always reserved 7-9 characters on the right, though a scan
row shows only 11 px of signal bars: names got about half the OLED.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rows kept a fixed order while their numbers came from page_order,
which still has slots for retired pages (Recent, GPS, Sensors): numbers
skipped, and Left/Right could swap a page with a slot that has no row, so
nothing seemed to happen. Rows now show the pages in Home's order; a move
skips retired slots and the highlight follows the page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The keypad files came back with CRLF endings; MESHCORE_VERSION is the
MeshCore base on the splash (1.18.0), not the Solo version, which comes
from the tag; ENV_INCLUDE_GPS is already set by the ProMicro base. A long
Enter with the screen off acted on the dark screen: it now only wakes it,
like every other key, and restarts the screen-off timer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Simpson: Enter long-press on the keypad, GPS skyview; the last position kept
while GPS duty-cycling sleeps.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Same gap as the ProMicro: an SSD1306 solo build without
OLED_MISC_FIXED_FONT, non-Latin text as filled squares. Flash 75%.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The only SSD1306 solo build without OLED_MISC_FIXED_FONT: non-Latin text
showed as filled squares. ~14 KB flash (70.3% -> 72.3%).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The OLED popup fits 3 rows, a finished ping has 4; UP/DOWN were swallowed
so SNR back stayed hidden. Enter on any row sends. Fixes#50.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On the ProMicro the CardKB sits on Wire with the SSD1306. The poll task,
active while a frame goes out, read the keyboard mid-transfer: frozen
screen and a boot loop since rc3. Fixes#51.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>