mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-17 16:46:37 +00:00
feat(ui): make favourites mean one thing across every list
Three names had grown around one idea. "Favourite" was a filter in Settings, an invisible app-only flag on a contact, a device-settable bit on a channel, and — on the Nodes screen — a menu row that actually pinned to the Favourites dial. Nothing marked a favourite on screen, and the dial only took chat contacts. A favourite is now the starred flag (ContactInfo::flags bit 0 for contacts and rooms, ch_fav_bitmask for channels), settable on the device everywhere via a Fav: ON/OFF row, marked with a star on its row, and sorted to the top of the list — in Messages, Tools > Nodes and the Locator target picker. Settings > Contacts > "Favs top" turns the sorting off; it defaults on, and is stored inverted so an upgraded prefs file reads back as on rather than off. MyMesh::setContactFavourite() writes the same bit the app sets and bumps lastmod, so the two stay in sync. The DMs/Rooms = Fav list filters no longer depend on having starred someone in the app first. Pinning is now separate and explicit, and the dial takes contacts, room servers and channels. Slots carry a kind (NodePrefs::favourite_kinds, schema 0xC0DE0029) — a channel slot holds an index, so emptiness is decided by the kind first, since channel 0's payload is all zeroes. Choosing what to pin reuses the Messages screen's own Direct/Channels/Rooms browse instead of a second picker built on the dial, which drops that picker, its key/label tables and the now-unused getRecentDMContacts(). A filled tile gained Unpin/Replace under Hold Enter. Fixes a room server being pinnable and then unremovable: the picker's recent-conversations tier didn't filter by contact type and room posts share the DM history, opening one from the dial skipped the login handshake, and Unpin only existed in the chat contact list that rooms never appear in. Also: PopupMenu::_visible was written and never read (render recomputes the cap from display height), which is why menus with more items than the "visible" argument always worked; Settings' all/fav values and the dm_show_all comment said things that were not true. Built for Heltec V3, Wio Tracker L1, Wio Tracker L1 e-ink and T-Echo Card. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -593,6 +593,22 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
||||
rd(_prefs.repeat_extra_scopes, sizeof(_prefs.repeat_extra_scopes));
|
||||
_prefs.repeat_extra_scopes[sizeof(_prefs.repeat_extra_scopes) - 1] = '\0';
|
||||
|
||||
// → 0xC0DE0028: append favourite_kinds. A pre-0x28 file has that file's own
|
||||
// 4-byte sentinel tail sitting here, so the first slots read back as 0x27/
|
||||
// 0x00/0xDE/0xC0 — clamp anything unknown to CONTACT, which is what every
|
||||
// slot saved before this bump actually was.
|
||||
rd(_prefs.favourite_kinds, sizeof(_prefs.favourite_kinds));
|
||||
for (uint8_t i = 0; i < NodePrefs::FAVOURITES_COUNT; i++) {
|
||||
if (_prefs.favourite_kinds[i] > NodePrefs::FAV_KIND_MAX)
|
||||
_prefs.favourite_kinds[i] = NodePrefs::FAV_KIND_CONTACT;
|
||||
}
|
||||
|
||||
// → 0xC0DE0029: append fav_sort_off. Inverted (see NodePrefs), so both a
|
||||
// pre-0x29 file's stray sentinel byte here and a file that ends before this
|
||||
// field clamp/zero to 0 = favourites on top, which is the default.
|
||||
rd(&_prefs.fav_sort_off, sizeof(_prefs.fav_sort_off));
|
||||
if (_prefs.fav_sort_off > 1) _prefs.fav_sort_off = 0;
|
||||
|
||||
// Schema sentinel: bumped on layout changes. Mismatch means an older file
|
||||
// (or a different schema); rd() already zero-inits any fields not present,
|
||||
// so we just log it — next savePrefs writes the current sentinel.
|
||||
@@ -810,6 +826,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
|
||||
file.write((uint8_t *)&_prefs.cad_enabled, sizeof(_prefs.cad_enabled));
|
||||
file.write((uint8_t *)&_prefs.repeat_scope_only, sizeof(_prefs.repeat_scope_only));
|
||||
file.write((uint8_t *)_prefs.repeat_extra_scopes, sizeof(_prefs.repeat_extra_scopes));
|
||||
file.write((uint8_t *)_prefs.favourite_kinds, sizeof(_prefs.favourite_kinds));
|
||||
file.write((uint8_t *)&_prefs.fav_sort_off, sizeof(_prefs.fav_sort_off));
|
||||
|
||||
// Tail sentinel — must be last. See NodePrefs::SCHEMA_SENTINEL. Its write is
|
||||
// the one we check: once the flash fills, writes return 0, so a good
|
||||
|
||||
Reference in New Issue
Block a user