mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
fix(ui): Favourites page polish + upgrade migration
Render issues: - Drop the "FAVOURITES" title — it overlapped the node-name/battery top bar; the page-dots indicator already identifies the page - Use the locally-computed content_y (matches other home pages) so tiles sit below the dots row instead of starting at headerH() + sepH() - Add 2 px top/bottom margin inside the grid so cells don't hug the dots or the panel edge Upgrade migration (visibility + position): - Newly-loaded prefs with an older sentinel OR a non-default mask had HP_FAVOURITES off and could not be enabled — DataStore::loadPrefsInt now ORs HP_FAVOURITES into home_pages_mask whenever the sentinel doesn't match the current schema - Existing page_order_set users were stuck because FAVOURITES wasn't in page_order, so movePageInOrder bailed — ensurePageOrderInit now detects the missing FAVOURITES entry and inserts it right after CLOCK, shifting the tail; if the array is already full the page still appears via the buildVisibleOrder fallback Bug fix in ensurePageOrderInit verification loop: iterated to HPB_COUNT (12) over a PAGE_ORDER_LEN (11) array → one OOB read per call. Now bounded to PAGE_ORDER_LEN. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -314,6 +314,12 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
if (sentinel != NodePrefs::SCHEMA_SENTINEL) {
|
||||
MESH_DEBUG_PRINTLN("prefs schema sentinel mismatch: got 0x%08X, expected 0x%08X — re-saving on next change",
|
||||
(unsigned)sentinel, (unsigned)NodePrefs::SCHEMA_SENTINEL);
|
||||
// 0xC0DE0001 → 0xC0DE0002: FAVOURITES home page added. Older saves have it
|
||||
// implicitly off (their mask doesn't include HP_FAVOURITES); turn it on so
|
||||
// upgraded users see the new page by default and can toggle it later.
|
||||
if (_prefs.home_pages_mask != 0) {
|
||||
_prefs.home_pages_mask |= NodePrefs::HP_FAVOURITES;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
@@ -238,18 +238,34 @@ class SettingsScreen : public UIScreen {
|
||||
}
|
||||
|
||||
// Initialises page_order to the default display sequence if not already set.
|
||||
// Also repairs a partially-initialised order where CLOCK (bit 0, stored as 1) is absent.
|
||||
// Also repairs a partially-initialised order where CLOCK is absent, and migrates
|
||||
// older orders by inserting FAVOURITES after CLOCK so the page is reorderable.
|
||||
void ensurePageOrderInit(NodePrefs* p) const {
|
||||
if (!p) return;
|
||||
if (p->page_order_set == NodePrefs::PAGE_ORDER_MAGIC) {
|
||||
// Order was previously set — verify CLOCK is present to guard against partial/corrupted data.
|
||||
for (int i = 0; i < NodePrefs::HPB_COUNT; i++) {
|
||||
bool has_clock = false;
|
||||
bool has_fav = false;
|
||||
int len = 0;
|
||||
int clock_at = -1;
|
||||
for (int i = 0; i < NodePrefs::PAGE_ORDER_LEN; i++) {
|
||||
uint8_t v = p->page_order[i];
|
||||
if (v < 1 || v > NodePrefs::HPB_COUNT) break;
|
||||
if (v == 0 + 1) return; // CLOCK found, order is intact
|
||||
if ((int)(v - 1) == NodePrefs::HPB_CLOCK) { has_clock = true; clock_at = i; }
|
||||
if ((int)(v - 1) == NodePrefs::HPB_FAVOURITES) { has_fav = true; }
|
||||
len = i + 1;
|
||||
}
|
||||
if (!has_clock) {
|
||||
// Corrupted/partial — full re-init below.
|
||||
memset(p->page_order, 0, sizeof(p->page_order));
|
||||
} else {
|
||||
if (!has_fav && len < NodePrefs::PAGE_ORDER_LEN) {
|
||||
// Insert FAVOURITES right after CLOCK; shift the tail down by one.
|
||||
int insert_at = clock_at + 1;
|
||||
for (int i = len; i > insert_at; i--) p->page_order[i] = p->page_order[i - 1];
|
||||
p->page_order[insert_at] = NodePrefs::HPB_FAVOURITES + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// CLOCK missing — reset and fall through to full re-init.
|
||||
memset(p->page_order, 0, sizeof(p->page_order));
|
||||
}
|
||||
// Default: CLOCK FAVOURITES RECENT RADIO BT ADVERT [GPS] [SENSORS] SETTINGS TOOLS MESSAGES
|
||||
// SHUTDOWN is omitted from the explicit list (PAGE_ORDER_LEN = 11 leaves room for the
|
||||
|
||||
@@ -747,18 +747,19 @@ public:
|
||||
} else if (_page == HomePage::FAVOURITES) {
|
||||
// Grid of pinned contacts. Layout transposes to current orientation:
|
||||
// landscape → 3×2, portrait → 2×3. Selected tile inverts via drawSelectionRow.
|
||||
// No title — node name + battery (top bar) and the page-dots indicator above
|
||||
// serve as the page identity.
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.setTextSize(1);
|
||||
display.drawTextCentered(display.width() / 2, 0, "FAVOURITES");
|
||||
display.fillRect(0, display.headerH() - 1, display.width(), display.sepH());
|
||||
|
||||
const int cols = display.isLandscape() ? 3 : 2;
|
||||
const int rows = NodePrefs::FAVOURITES_COUNT / cols;
|
||||
const int grid_y = display.headerH() + display.sepH();
|
||||
const int grid_h = display.height() - grid_y;
|
||||
const int margin = 2;
|
||||
const int grid_y = content_y + margin;
|
||||
const int grid_h = display.height() - grid_y - margin;
|
||||
const int cell_w = display.width() / cols;
|
||||
const int cell_h = grid_h / rows;
|
||||
const int lh = display.getLineHeight();
|
||||
const int line_h = display.getLineHeight();
|
||||
|
||||
if (_fav_sel >= NodePrefs::FAVOURITES_COUNT) _fav_sel = 0;
|
||||
|
||||
@@ -791,7 +792,7 @@ public:
|
||||
char name[24];
|
||||
if (found) display.translateUTF8ToBlocks(name, ci.name, sizeof(name));
|
||||
else strncpy(name, "(gone)", sizeof(name) - 1), name[sizeof(name) - 1] = '\0';
|
||||
int name_y = cy + (cell_h - lh) / 2;
|
||||
int name_y = cy + (cell_h - line_h) / 2;
|
||||
display.drawTextEllipsized(cx + 2, name_y, cell_w - 4, name);
|
||||
|
||||
if (found) {
|
||||
@@ -805,7 +806,7 @@ public:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int plus_y = cy + (cell_h - lh) / 2;
|
||||
int plus_y = cy + (cell_h - line_h) / 2;
|
||||
display.drawTextCentered(cx + cell_w / 2, plus_y, "+");
|
||||
}
|
||||
if (sel) display.setColor(DisplayDriver::LIGHT);
|
||||
|
||||
Reference in New Issue
Block a user