feat(ui): marquee-scroll selected long names/labels instead of static ellipsis

Selecting a row whose ellipsized text overflows now animates a "swing"
marquee: holds at the start, scrolls to reveal the full tail, holds
there, then scrolls back and repeats. Unselected/non-overflowing text
is unchanged (still a static "..."). E-ink gets slower, coarser steps
(fewer, cheaper partial refreshes) than OLED; unchanged frames are
already skipped by the display's CRC diff, so idle holds are free.

Wired into every screen with a selectable row: home favourites, DM/
channel lists and message bodies, Settings, popup menus, Bot, Admin,
Nearby, Waypoints, Locator, Live Share, and the alarm screen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-08-30 17:17:55 +02:00
co-authored by Claude Sonnet 5
parent 12cf81b13f
commit 1bb28296c2
13 changed files with 250 additions and 79 deletions
@@ -166,19 +166,22 @@ class ClockToolsScreen : public UIScreen {
const char* rows[3] = { "Time", "Repeat", "Armed" };
if (_sel > 2) _sel = 2;
const int valx = d.width() / 2 + 6;
int mq_delay = 0;
drawList(d, 3, _sel, _scroll, [&](int i, int y, bool sel, int reserve) {
drawRowSelection(d, y, sel, reserve);
d.setCursor(4, y); d.print(rows[i]);
if (i == 0) {
drawAlarmTime(d, y, valx, sel && _alarm_editing);
} else if (i == 1) {
d.drawTextEllipsized(valx, y, d.width() - valx - reserve,
NodePrefs::alarmRepeatLabel(NodePrefs::alarmRepeatIdxForMask(_prefs->alarm_repeat_mask)));
int mqr = d.drawTextEllipsized(valx, y, d.width() - valx - reserve,
NodePrefs::alarmRepeatLabel(NodePrefs::alarmRepeatIdxForMask(_prefs->alarm_repeat_mask)), sel);
if (sel && mqr > 0) mq_delay = mqr;
} else {
d.drawTextEllipsized(valx, y, d.width() - valx - reserve, _prefs->alarm_on ? "ON" : "OFF");
}
});
return _alarm_editing ? 50 : 60000;
if (_alarm_editing) return 50;
return (mq_delay > 0 && mq_delay < 60000) ? mq_delay : 60000;
}
int renderTimer(DisplayDriver& d) {