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
@@ -27,10 +27,6 @@ class SettingsScreen : public UIScreen {
#endif
#if FEAT_FULL_REFRESH_SETTING
EINK_FULL_REFRESH,
UI_TEXT_SCALE, // Text size: 1x..5x the 6x9 font
#if STATUS_ICONS_SCALED
UI_ICON_SCALE, // Icon size: Auto, 1x..8x
#endif
#endif
// Sound section
SECTION_SOUND,
@@ -559,18 +555,6 @@ class SettingsScreen : public UIScreen {
uint8_t idx = p ? p->eink_full_refresh_every : 0;
if (idx >= EINK_FULL_REFRESH_COUNT) idx = 0;
val("Full rfsh", EINK_FULL_REFRESH_LABELS[idx]);
} else if (item == UI_TEXT_SCALE) {
char b[4];
snprintf(b, sizeof(b), "%ux", (unsigned)_task->getUiFontScale());
val("Text size", b);
#if STATUS_ICONS_SCALED
} else if (item == UI_ICON_SCALE) {
char b[12];
const uint8_t v = _task->getStatusIconScale();
if (v == 0) snprintf(b, sizeof(b), "Auto");
else snprintf(b, sizeof(b), "%ux", (unsigned)v);
val("Icon size", b);
#endif
#endif
} else if (item == DM_FILTER) {
val("DMs", (p && p->dm_show_all) ? "All" : "Fav");
@@ -1202,21 +1186,6 @@ public:
_dirty = true;
return true;
}
if (_selected == UI_TEXT_SCALE && (left || right || enter)) {
int v = _task->getUiFontScale(); // 1..5, wrapping
v = left ? (v <= 1 ? 5 : v - 1) : (v >= 5 ? 1 : v + 1);
_task->setUiFontScale(v); // saved to /ui_scale immediately
return true;
}
#if STATUS_ICONS_SCALED
if (_selected == UI_ICON_SCALE && (left || right || enter)) {
const int n = STATUS_ICON_SCALE_MAX + 1; // Auto, 1x..8x
int v = _task->getStatusIconScale();
v = (v + (left ? n - 1 : 1)) % n;
_task->setStatusIconScale(v); // saved to /ui_scale immediately
return true;
}
#endif
#endif
if (_selected == DM_FILTER && p && (left || right || enter)) {
p->dm_show_all = p->dm_show_all ? 0 : 1;
+12 -52
View File
@@ -2063,7 +2063,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
applyBrightness();
applyRotation();
applyFullRefreshInterval();
loadUiScale(); // Settings > Display > Text size / Icon size
applyUiScale(); // Settings > Display > Text size / Icon size
applyAllGpioModes(); // restore persisted pin modes to hardware before any UI/bot use
// Locked above (a PIN, or the cover closed) before Home existed to be told.
if (_locked) syncLockToHome();
@@ -4163,57 +4163,17 @@ void UITask::applyFullRefreshInterval() {
}
}
// Text size and Icon size (Settings > Display), in their own /ui_scale file --
// [text pixel scale (0 = build default), icon scale (0 = Auto)] -- so the
// NodePrefs schema is untouched.
static const char* UI_SCALE_FILE = "/ui_scale";
static const uint8_t UI_TEXT_SCALE_MAX = 5;
void UITask::loadUiScale() {
uint8_t b[2] = { 0, statusIconScaleSetting() };
DataStore* ds = the_mesh.getDataStore();
if (ds) {
File f = ds->openRead(UI_SCALE_FILE);
if (f) {
f.read(b, 2);
f.close();
}
}
_ui_font_scale = b[0] <= UI_TEXT_SCALE_MAX ? b[0] : 0;
if (b[1] <= STATUS_ICON_SCALE_MAX) statusIconScaleSetting() = b[1];
if (_display != NULL && _ui_font_scale) _display->setUiScale(_ui_font_scale);
}
void UITask::saveUiScale() {
DataStore* ds = the_mesh.getDataStore();
if (!ds) return;
File f = ds->openWrite(UI_SCALE_FILE);
if (f) {
uint8_t b[2] = { _ui_font_scale, statusIconScaleSetting() };
f.write(b, 2);
f.close();
}
}
uint8_t UITask::getUiFontScale() const {
return _display != NULL ? (uint8_t)_display->pixelScale() : 1;
}
void UITask::setUiFontScale(uint8_t s) {
if (s < 1 || s > UI_TEXT_SCALE_MAX) s = 1;
_ui_font_scale = s;
if (_display != NULL) _display->setUiScale(s);
_next_refresh = 0;
saveUiScale();
}
uint8_t UITask::getStatusIconScale() const { return statusIconScaleSetting(); }
void UITask::setStatusIconScale(uint8_t s) {
if (s > STATUS_ICON_SCALE_MAX) s = 0;
statusIconScaleSetting() = s;
_next_refresh = 0; // the frame differs, so it's redrawn
saveUiScale();
// Text size and Icon size (Settings > Display, NodePrefs ui_text_scale /
// ui_icon_scale), on the builds that offer them. Elsewhere the fields stay 0:
// the build's font scale and Auto icons, as stock.
void UITask::applyUiScale() {
if (!_node_prefs) return;
#ifdef EINK_FONT_SCALE
if (_display != NULL) _display->setUiScale(_node_prefs->ui_text_scale);
#endif
#if STATUS_ICONS_SCALED
statusIconScaleSetting() = _node_prefs->ui_icon_scale;
#endif
}
void UITask::applySoundPrefs() {
+2 -10
View File
@@ -62,7 +62,6 @@ class UITask : public UITaskBase, public UiCoreHost {
unsigned long _next_refresh, _auto_off;
bool _display_was_on = true; // loop(): messagesInView() last time round
NodePrefs* _node_prefs;
uint8_t _ui_font_scale = 0; // Settings > Display > Text size (0 = build default)
bool _locked;
bool _tool_from_home = false;
bool messagesInView() const; // Messages on a lit, unlocked display
@@ -529,7 +528,7 @@ public:
void applyAllGpioModes(); // boot-time restore from NodePrefs, called from begin()
void applyBrightness();
// Settings changed through the schema (ui-core/SettingsSchema.h).
void applyDisplayPrefs() override { applyBrightness(); _next_refresh = 0; }
void applyDisplayPrefs() override { applyBrightness(); applyUiScale(); _next_refresh = 0; }
void applySoundPrefs() override;
bool cliCommand(const char* command, char* reply, int n) override;
void setBuzzerVolumeLevel(uint8_t level);
@@ -544,14 +543,7 @@ public:
bool savePrefsIfDirty(bool& dirty);
void applyRotation();
void applyFullRefreshInterval();
// Settings > Display > Text size / Icon size. Kept in their own /ui_scale
// file rather than NodePrefs, so the prefs schema (and its size assert) is untouched.
uint8_t getUiFontScale() const; // the text's current pixel scale
void setUiFontScale(uint8_t s); // 1..5: applies + saves
uint8_t getStatusIconScale() const; // 0 = Auto (1.5x text), else n
void setStatusIconScale(uint8_t s); // 0..8: applies + saves
void loadUiScale(); // boot-time restore, from begin()
void saveUiScale();
void applyUiScale(); // Settings > Display > Text size / Icon size, from the prefs
uint32_t autoOffMillis() const {
if (!_node_prefs || _node_prefs->auto_off_secs == 0) return 0;
return (uint32_t)_node_prefs->auto_off_secs * 1000UL;
+6 -7
View File
@@ -94,20 +94,19 @@ inline void miniIconDrawCentered(DisplayDriver& d, int cx, int cy, const MiniIco
// Home status bar icon scale. Defining STATUS_ICON_SCALE (build flag) turns on
// scalable status icons: the bar's icons, battery and the page-icon row below it
// are drawn at n x their pixel grid, and the bar grows tall enough to hold them --
// for big panels whose 1-line bar leaves them tiny. Its value is the default for
// Settings > Display > Icon size: 0 = Auto (1.5x the text's pixel scale), else n.
// Unset: icons follow the font, as stock.
// for big panels whose 1-line bar leaves them tiny -- and adds Settings > Display >
// Icon size (NodePrefs::ui_icon_scale): 0 = Auto (1.5x the text's pixel scale),
// else n. Unset: icons follow the font, as stock.
#ifdef STATUS_ICON_SCALE
#define STATUS_ICONS_SCALED 1
#else
#define STATUS_ICONS_SCALED 0
#define STATUS_ICON_SCALE 0
#endif
static constexpr int STATUS_ICON_SCALE_MAX = 8;
static constexpr int STATUS_ICON_ROWS = MINI_ICONS_LARGE == 2 ? 9 : 7; // tallest status icon
// The Icon size setting (0 = Auto). One instance across translation units.
// The Icon size setting (0 = Auto), copied from the prefs by UITask::applyUiScale().
// One instance across translation units.
inline uint8_t& statusIconScaleSetting() {
static uint8_t v = (STATUS_ICON_SCALE >= 0 && STATUS_ICON_SCALE <= STATUS_ICON_SCALE_MAX) ? STATUS_ICON_SCALE : 0;
static uint8_t v = 0;
return v;
}
inline int statusIconScale(DisplayDriver& d) {