feat(ui): pill unread badges, unified DM/CH headers, trimmed home carousel

UI-polish trio from CODE_REVIEW (biggest "feels finished" gain per line):

- Pill unread badges: new DisplayDriver::drawUnreadBadge()/unreadBadgeWidth()
  draw a filled capsule with the count knocked out (corners knocked back for a
  rounded look; inverts on a selected row). Replaces the bare right-aligned
  digits in MODE_SELECT, the contact/channel pickers and favourites tiles.
  No <stdio.h> in the header — fmtBadgeCount formats manually, clamps to 99+.
- Unified DM/CH history headers: DM_HIST and CHANNEL_HIST drew their titles by
  hand (drawTextCentered + fillRect at lh+1), a different height/separator than
  every other screen. Both now route through drawCenteredHeader().
- Trimmed default home carousel: new NodePrefs::HP_DEFAULT (Clock, Tools,
  Shutdown, Favourites, Map; Messages + Settings always visible = 7 pages).
  applyDefaults() seeds it instead of HP_ALL. Recent/Radio/BT/Advert/GPS/Sensors
  are opt-in via Settings > Home Pages. Existing users keep their saved mask —
  factory default only; no migration, no schema bump.

Both solo envs build green (OLED RAM 69.9%/Flash 62.8%; e-ink SUCCESS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-07-07 01:12:51 +02:00
parent 58e07900db
commit 8e5b02f0a6
5 changed files with 61 additions and 44 deletions

View File

@@ -1235,21 +1235,14 @@ public:
// Reserve space for the unread badge so the name's ellipsis lands
// before it instead of underneath. Badge and name share one baseline.
char badge[5] = "";
int bw = 0;
uint8_t unread = _task->getDMUnread(ci.id.pub_key);
if (unread > 0) {
snprintf(badge, sizeof(badge), "%d", unread);
bw = display.getTextWidth(badge) + 3; // badge + 3 px gap
}
int bw = unread > 0 ? display.unreadBadgeWidth(unread) + 3 : 0; // badge + 3 px gap
int name_y = cy + (cell_h - line_h) / 2;
int name_max_w = cell_w - 4 - bw;
if (name_max_w < 6) name_max_w = 6;
display.drawTextEllipsized(cx + 2, name_y, name_max_w, name);
if (badge[0]) {
display.setCursor(cx + cell_w - (bw - 3) - 2, name_y);
display.print(badge);
}
if (unread > 0)
display.drawUnreadBadge(cx + cell_w - 2, name_y, unread, sel);
} else {
int plus_y = cy + (cell_h - line_h) / 2;
display.drawTextCentered(cx + cell_w / 2, plus_y, "+");