refactor(eink): Text size and Icon size as schema settings, on opt-in builds only

Review follow-up:

- The rows exist only where the build asks for them: Text size with
  EINK_FONT_SCALE, Icon size with STATUS_ICON_SCALE. The stock 2.13", the
  portrait builds and the L2 don't get them -- their screens are laid out
  for one cell size. The text override also applies in landscape only.
- Stored in NodePrefs (ui_text_scale, ui_icon_scale) instead of a
  /ui_scale file, as rows in the schema's Display section: the usual row,
  save path and factory reset, and console keys display.text.size /
  display.icon.size. The hand-written Settings rows and the load/save code
  are gone; UITask::applyUiScale() applies the prefs at boot and on change
  (applyDisplayPrefs). On opt-in builds ui_text_scale starts at the
  build's EINK_FONT_SCALE (DataStore sanitize), so the row shows the scale
  in use.
- EINK_FONT_SCALE, when set, now scales whichever landscape font the build
  picks (the 6x9, or the EINK_LARGE_FONT one); unset, it is stock as before.
- setUiScale() skips the re-layout and full redraw when nothing changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
pmow
2026-10-10 16:36:39 -10:00
co-authored by Claude Opus 5.5
parent c06b394144
commit 13531dd2ce
11 changed files with 74 additions and 114 deletions
@@ -23,6 +23,7 @@ static const Key KEYS[] = {
K("contacts.expiry", contact_expiry_idx), K("contacts.fav.first", fav_sort), K("dm.resend", dm_resend_count),
K("display.brightness", display_brightness), K("display.off", auto_off_secs), K("display.wake", msg_wake),
K("display.alert", msg_alert), K("lock", auto_lock), K("lock.clock", lock_compact),
K("display.text.size", ui_text_scale), K("display.icon.size", ui_icon_scale),
K("batt.display", batt_display_mode), K("batt.shutdown", low_batt_mv), K("gps.interval", gps_interval),
K("clock.12h", clock_12h), K("clock.seconds", clock_hide_seconds), K("units.imperial", units_imperial),
K("sound.volume", buzzer_volume), K("quiet", quiet_hours), K("quiet.from", quiet_from), K("quiet.until", quiet_to),
@@ -144,6 +144,15 @@ static void optMsgAlert(uint8_t v, char* b, int n, const NodePrefs&) {
static const char* const L[] = { "Normal", "Compact", "Off" };
snprintf(b, n, "%s", L[v < 3 ? v : 0]);
}
#ifdef EINK_FONT_SCALE
static const int32_t TEXT_SCALE[] = { 1, 2, 3, 4, 5 };
static void optTextScale(uint8_t v, char* b, int n, const NodePrefs&) { snprintf(b, n, "%ldx", (long)TEXT_SCALE[v]); }
#endif
#ifdef STATUS_ICON_SCALE
static void optIconScale(uint8_t v, char* b, int n, const NodePrefs&) {
if (v == 0) snprintf(b, n, "Auto"); else snprintf(b, n, "%ux", (unsigned)v);
}
#endif
static void optLockLook(uint8_t v, char* b, int n, const NodePrefs&) { snprintf(b, n, "%s", v ? "Compact" : "Big"); }
static void optExpiry(uint8_t v, char* b, int n, const NodePrefs&) {
snprintf(b, n, "%s", NodePrefs::contactExpiryLabel(v));
@@ -243,6 +252,15 @@ static const Setting ALL[] = {
SW("Lock screen", "Slide to unlock after sleep", SEC_DISPLAY, auto_lock, nullptr),
IDX("Lock clock", "Big, or compact with the clock fields", SEC_DISPLAY, lock_compact, 2, optLockLook, nullptr),
IDX("Battery display", "In the status bar", SEC_DISPLAY, batt_display_mode, 3, optBattDisplay, nullptr),
// Only the builds that ask for them (big e-ink panels): each screen elsewhere
// is laid out for one cell size.
#ifdef EINK_FONT_SCALE
MAP("Text size", "Bigger letters on a big panel", SEC_DISPLAY, ui_text_scale, TEXT_SCALE, optTextScale, applyDisplay),
#endif
#ifdef STATUS_ICON_SCALE
IDX("Icon size", "Home's status icons", SEC_DISPLAY, ui_icon_scale, NodePrefs::UI_ICON_SCALE_MAX + 1,
optIconScale, applyDisplay),
#endif
MAP("Battery shutdown", "Power off below this voltage", SEC_POWER, low_batt_mv, LOW_BATT, optLowBatt, nullptr),
MAP("GPS power saving", "Sleep between fixes", SEC_POWER, gps_interval, GPS_DUTY, optGpsDuty, applyGpsDuty),