Merge remote-tracking branch 'refs/remotes/pr/497' into integration/all-open-prs-20260913
This commit is contained in:
commit
fdde0dd0cc
6 files changed
+105
-12
No files matched your search
@@ -36,6 +36,9 @@ because that is the root.
|
||||
|
||||
**HOME** is the shortcut past all of that: it goes straight to the root and
|
||||
clears the trail, so Back from there won't jump you back out again.
|
||||
When **App drawer as home** is enabled, the drawer cog's **Lock home to drawer**
|
||||
option makes HOME stay in or return to the drawer. The **Cmdr** tile still
|
||||
opens the Commander screen when you need it.
|
||||
|
||||
The only exception is deliberate: progress overlays (SD format, bulk delete)
|
||||
block all keys until the operation finishes — Back will not navigate out from
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace TouchPrefsSchema {
|
||||
|
||||
static constexpr uint16_t MAGIC = 0x5743; // 'WC' (WadaCfg)
|
||||
static constexpr uint8_t CURRENT_VERSION = 59; // v49: fem_lna default flip on the V4-R8; v50: map tile z/x/y line off by default (no new fields); v51: console_mode (boot into the text console; new trailing field, default OFF); v52: console_monitor (show incoming messages in the console, default ON); v54: boot_wifi_time + boot_wifi_open (cold-boot saved-Wi-Fi time sync, #383; both OFF); v55: loud_alerts (resonant-pitch chime, #388; OFF); v56: theme_mode (Day/Night firmware theme, #296; default Night); v57: gps_fuzz_m (displace the advertised position, #399; 0 = off); v58: Attaky notification blink enable + room/DM color indexes (#423); v59: telem_loc_exact (answer position requests from chosen contacts with the REAL fix instead of the advert displacement; 0 = keep it displaced)
|
||||
static constexpr uint8_t CURRENT_VERSION = 60; // v49: fem_lna default flip on the V4-R8; v50: map tile z/x/y line off by default (no new fields); v51: console_mode (boot into the text console; new trailing field, default OFF); v52: console_monitor (show incoming messages in the console, default ON); v54: boot_wifi_time + boot_wifi_open (cold-boot saved-Wi-Fi time sync, #383; both OFF); v55: loud_alerts (resonant-pitch chime, #388; OFF); v56: theme_mode (Day/Night firmware theme, #296; default Night); v57: gps_fuzz_m (displace the advertised position, #399; 0 = off); v58: Attaky notification blink enable + room/DM color indexes (#423); v59: telem_loc_exact (answer position requests from chosen contacts with the REAL fix instead of the advert displacement; 0 = keep it displaced); v60: home_key_keeps_drawer (#491; default OFF)
|
||||
static constexpr uint8_t BROKEN_MID_INSERT_VERSION = 44;
|
||||
|
||||
// Persisted byte layout. New fields must be appended at the end: older blobs
|
||||
@@ -116,6 +116,7 @@ struct __attribute__((packed)) Config {
|
||||
// you already picked, not a broadcast, so applying the advert displacement to it is
|
||||
// arguably too blunt (honza_87628). OFF keeps the displacement, matching the advert.
|
||||
uint8_t telem_loc_exact;
|
||||
uint8_t home_key_keeps_drawer; // v60: M9 Home key stays in/returns to the app drawer
|
||||
};
|
||||
|
||||
static constexpr size_t HEADER_SIZE = offsetof(Config, bright);
|
||||
@@ -128,10 +129,10 @@ static_assert(offsetof(Config, web_mirror) == offsetof(Config, rx_queue) + sizeo
|
||||
// rejection is silent: cfgFlush just returns false and every preference stops
|
||||
// persisting, with nothing in the log to say why. The struct grows most releases,
|
||||
// so guard the ceiling here rather than discover it as "settings do not save" on
|
||||
// whichever board is using the file backend. 117 bytes today.
|
||||
// whichever board is using the file backend. 121 bytes today.
|
||||
static_assert(sizeof(Config) <= 2048,
|
||||
"Config exceeds the SdNvsPrefs value cap; prefs would silently stop saving");
|
||||
static_assert(offsetof(Config, telem_loc_exact) + sizeof(Config::telem_loc_exact) == sizeof(Config),
|
||||
static_assert(offsetof(Config, home_key_keeps_drawer) + sizeof(Config::home_key_keeps_drawer) == sizeof(Config),
|
||||
"new preference fields must remain trailing");
|
||||
// lang_file must stay immediately before the tail, or a v48-era blob overlays
|
||||
// onto the wrong bytes. Checking both ends means the next person to append is
|
||||
@@ -169,6 +170,9 @@ static_assert(offsetof(Config, attaky_notify_dm_color) ==
|
||||
static_assert(offsetof(Config, telem_loc_exact) ==
|
||||
offsetof(Config, attaky_notify_dm_color) + sizeof(Config::attaky_notify_dm_color),
|
||||
"telem_loc_exact must follow attaky_notify_dm_color");
|
||||
static_assert(offsetof(Config, home_key_keeps_drawer) ==
|
||||
offsetof(Config, telem_loc_exact) + sizeof(Config::telem_loc_exact),
|
||||
"home_key_keeps_drawer must follow telem_loc_exact");
|
||||
|
||||
// Overlay a persisted blob on caller-provided defaults. Beta 57 wrote v44 with
|
||||
// retry_echo inserted before web_mirror, shifting every later value. That blob
|
||||
|
||||
@@ -149,6 +149,7 @@ static void cfgSetDefaults(TouchCfg& c) {
|
||||
c.attaky_notify_room_color = 0; // red
|
||||
c.attaky_notify_dm_color = 1; // green
|
||||
c.compact_chat = 0; // OFF: bubble chat layout (opt-in IRC-style dense rows)
|
||||
c.home_key_keeps_drawer = 0; // OFF: preserve Home-key Commander/drawer toggle
|
||||
c.clock_floor = 0; // no persisted send-timestamp floor yet
|
||||
c.rx_queue = 1; // ON: buffered receive (test-channel default; opt-out toggle in Radio & Mesh)
|
||||
c.retry_echo = 0; // OFF: auto-retry is opt-in (toggle in Radio & Mesh)
|
||||
@@ -264,6 +265,7 @@ static void cfgLoadOrMigrate() {
|
||||
if (stored_version < 56) { s_cfg.theme_mode = 0; } // Night: unchanged appearance
|
||||
if (stored_version < 57) { s_cfg.gps_fuzz_m = 0; } // OFF: real position
|
||||
if (stored_version < 59) { s_cfg.telem_loc_exact = 0; } // OFF: answers stay displaced
|
||||
if (stored_version < 60) { s_cfg.home_key_keeps_drawer = 0; } // preserve Home-key toggle
|
||||
if (stored_version < 58) {
|
||||
s_cfg.attaky_notify_enabled = 0;
|
||||
s_cfg.attaky_notify_room_color = 0;
|
||||
@@ -1398,6 +1400,16 @@ bool touchPrefsSetHomeIsDrawer(bool on) {
|
||||
return cfgFlush();
|
||||
}
|
||||
|
||||
bool touchPrefsGetHomeKeyKeepsDrawer() {
|
||||
if (!s_begun) touchPrefsBegin();
|
||||
return s_cfg.home_key_keeps_drawer != 0;
|
||||
}
|
||||
bool touchPrefsSetHomeKeyKeepsDrawer(bool on) {
|
||||
if (!s_begun) touchPrefsBegin();
|
||||
s_cfg.home_key_keeps_drawer = on ? 1 : 0;
|
||||
return cfgFlush();
|
||||
}
|
||||
|
||||
// Store ALL device data (identity, prefs, contacts, channels) on the SD card
|
||||
// under /meshcomod instead of internal SPIFFS. Read at boot (main.cpp) BEFORE
|
||||
// the data loads, so changing it needs a reboot. Key "use_sd" in the "touch"
|
||||
|
||||
@@ -289,6 +289,11 @@ bool touchPrefsSetNavDirKey(int idx, uint8_t ch);
|
||||
bool touchPrefsGetHomeIsDrawer();
|
||||
bool touchPrefsSetHomeIsDrawer(bool on);
|
||||
|
||||
/* M9 Home-key behavior: when true and the app drawer is configured as Home,
|
||||
* pressing Home stays in or returns to the drawer instead of toggling Commander. */
|
||||
bool touchPrefsGetHomeKeyKeepsDrawer();
|
||||
bool touchPrefsSetHomeKeyKeepsDrawer(bool on);
|
||||
|
||||
/** Hide the device/profile name in the status bar and move the clock to the
|
||||
* left where the name used to be. Default false (name shown). */
|
||||
bool touchPrefsGetHideNodeName();
|
||||
|
||||
+54
-6
@@ -41797,12 +41797,15 @@ static bool m9HandleNavKey(int key) {
|
||||
}
|
||||
if (getActiveTab() == HOME_TAB_INDEX) {
|
||||
const bool was_open = s_home_drawer_mode; // read BEFORE dismissing anything
|
||||
// Stop on a key-blocker row (SD format / bulk delete progress) instead of
|
||||
// spinning eight times closing nothing and then toggling the drawer out
|
||||
// from under a running operation.
|
||||
for (int i = 0; i < 8 && anyPopupOpen(); i++) { if (!hwKeyDismissTopPopup()) break; }
|
||||
if (anyPopupOpen()) { s_nav_show = true; if (g_lv.task) g_lv.task->noteUserInput(); return true; }
|
||||
setHomeDrawer(!was_open); // decide from the snapshot, not the now-mutated flag
|
||||
const bool keep_drawer = s_home_is_drawer && touchPrefsGetHomeKeyKeepsDrawer();
|
||||
if (!(keep_drawer && was_open && s_appdrawer_root && !appDrawerCovered())) {
|
||||
// Stop on a key-blocker row (SD format / bulk delete progress) instead of
|
||||
// spinning eight times closing nothing and then toggling the drawer out
|
||||
// from under a running operation.
|
||||
for (int i = 0; i < 8 && anyPopupOpen(); i++) { if (!hwKeyDismissTopPopup()) break; }
|
||||
if (anyPopupOpen()) { s_nav_show = true; if (g_lv.task) g_lv.task->noteUserInput(); return true; }
|
||||
setHomeDrawer(keep_drawer ? true : !was_open); // optional sticky drawer; otherwise preserve toggle
|
||||
}
|
||||
} else {
|
||||
s_m9_map_pan = false; // leaving the Map: pan must not outlive the tab (a stale flag ate the next Back press)
|
||||
if (!navGoToMainTab(HOME_TAB_INDEX)) { // a blocker popup refused: nothing moved, so keep the trail
|
||||
@@ -46026,7 +46029,21 @@ static void appHomeIsDrawerCb(lv_event_t* e) {
|
||||
#endif
|
||||
s_home_is_drawer = on;
|
||||
if (on) s_home_drawer_mode = true; // make the drawer the live Home view too (persists on return + reboot)
|
||||
#if defined(HAS_THINKNODE_M9)
|
||||
lv_obj_t* dependent_row = static_cast<lv_obj_t*>(lv_event_get_user_data(e));
|
||||
if (dependent_row && lv_obj_is_valid(dependent_row)) {
|
||||
if (on) lv_obj_clear_flag(dependent_row, LV_OBJ_FLAG_HIDDEN);
|
||||
else lv_obj_add_flag(dependent_row, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(HAS_THINKNODE_M9)
|
||||
static void appHomeKeyKeepsDrawerCb(lv_event_t* e) {
|
||||
if (lv_event_get_code(e) != LV_EVENT_VALUE_CHANGED) return;
|
||||
touchPrefsSetHomeKeyKeepsDrawer(
|
||||
lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
}
|
||||
#endif
|
||||
static void openAppGridSheet() {
|
||||
closeAppGridSheet();
|
||||
lv_coord_t sw = lv_disp_get_hor_res(nullptr), sh = lv_disp_get_ver_res(nullptr);
|
||||
@@ -46056,6 +46073,9 @@ static void openAppGridSheet() {
|
||||
lv_obj_remove_style_all(card);
|
||||
{
|
||||
int card_h = hdr + 2 * btn_h + gap + home_row + gap + 2 * pad;
|
||||
#if defined(HAS_THINKNODE_M9)
|
||||
card_h += home_row + gap;
|
||||
#endif
|
||||
if (card_h > card_h_max) card_h = card_h_max;
|
||||
lv_obj_set_size(card, card_w, card_h);
|
||||
}
|
||||
@@ -46064,7 +46084,13 @@ static void openAppGridSheet() {
|
||||
lv_obj_set_style_bg_opa(card, LV_OPA_COVER, LV_PART_MAIN);
|
||||
lv_obj_set_style_radius(card, 8, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_all(card, pad, LV_PART_MAIN);
|
||||
#if defined(HAS_THINKNODE_M9)
|
||||
lv_obj_set_scroll_dir(card, LV_DIR_VER);
|
||||
lv_obj_set_scrollbar_mode(card, LV_SCROLLBAR_MODE_AUTO);
|
||||
lv_obj_add_event_cb(card, scrollClampOnEndCb, LV_EVENT_SCROLL_END, nullptr);
|
||||
#else
|
||||
lv_obj_clear_flag(card, LV_OBJ_FLAG_SCROLLABLE);
|
||||
#endif
|
||||
|
||||
lv_obj_t* ttl = lv_label_create(card);
|
||||
lv_label_set_text(ttl, TR("App icon size"));
|
||||
@@ -46109,7 +46135,29 @@ static void openAppGridSheet() {
|
||||
#if defined(ESP32)
|
||||
if (touchPrefsGetHomeIsDrawer()) lv_obj_add_state(sw, LV_STATE_CHECKED);
|
||||
#endif
|
||||
#if defined(HAS_THINKNODE_M9)
|
||||
const int ky = ty + home_row + gap;
|
||||
lv_obj_t* key_row = lv_obj_create(card);
|
||||
lv_obj_remove_style_all(key_row);
|
||||
lv_obj_set_size(key_row, card_w - 2 * pad, home_row);
|
||||
lv_obj_set_pos(key_row, 0, ky);
|
||||
lv_obj_clear_flag(key_row, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_t* kl = lv_label_create(key_row);
|
||||
lv_label_set_long_mode(kl, LV_LABEL_LONG_DOT);
|
||||
lv_obj_set_width(kl, lv_pct(68));
|
||||
lv_label_set_text(kl, TR("Lock home to drawer"));
|
||||
lv_obj_set_style_text_font(kl, &g_font_12, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_color(kl, lv_color_hex(COLOR_TEXT), LV_PART_MAIN);
|
||||
lv_obj_align(kl, LV_ALIGN_LEFT_MID, 0, 0);
|
||||
lv_obj_t* key_sw = lv_switch_create(key_row);
|
||||
lv_obj_align(key_sw, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||
if (touchPrefsGetHomeKeyKeepsDrawer()) lv_obj_add_state(key_sw, LV_STATE_CHECKED);
|
||||
if (!touchPrefsGetHomeIsDrawer()) lv_obj_add_flag(key_row, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_event_cb(key_sw, appHomeKeyKeepsDrawerCb, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
lv_obj_add_event_cb(sw, appHomeIsDrawerCb, LV_EVENT_VALUE_CHANGED, key_row);
|
||||
#else
|
||||
lv_obj_add_event_cb(sw, appHomeIsDrawerCb, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
static void appDrawerSettingsCb(lv_event_t* e) {
|
||||
|
||||
@@ -30,6 +30,7 @@ static Config safeDefaults() {
|
||||
c.attaky_notify_enabled = 0;
|
||||
c.attaky_notify_room_color = 0;
|
||||
c.attaky_notify_dm_color = 1;
|
||||
c.home_key_keeps_drawer = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -125,7 +126,8 @@ int main() {
|
||||
+ sizeof(Config::gps_fuzz_m) + sizeof(Config::attaky_notify_enabled)
|
||||
+ sizeof(Config::attaky_notify_room_color)
|
||||
+ sizeof(Config::attaky_notify_dm_color)
|
||||
+ sizeof(Config::telem_loc_exact) == sizeof(Config),
|
||||
+ sizeof(Config::telem_loc_exact)
|
||||
+ sizeof(Config::home_key_keeps_drawer) == sizeof(Config),
|
||||
"v53 is the current layout minus every byte appended since");
|
||||
|
||||
Config v53 = safeDefaults();
|
||||
@@ -167,6 +169,7 @@ int main() {
|
||||
current.attaky_notify_enabled = 1;
|
||||
current.attaky_notify_room_color = 6;
|
||||
current.attaky_notify_dm_color = 4;
|
||||
current.home_key_keeps_drawer = 1;
|
||||
migrated = safeDefaults();
|
||||
assert(TouchPrefsSchema::overlayStored(migrated, ¤t, sizeof(current), &stored_version));
|
||||
assert(stored_version == TouchPrefsSchema::CURRENT_VERSION);
|
||||
@@ -198,7 +201,8 @@ int main() {
|
||||
+ sizeof(Config::attaky_notify_enabled)
|
||||
+ sizeof(Config::attaky_notify_room_color)
|
||||
+ sizeof(Config::attaky_notify_dm_color)
|
||||
+ sizeof(Config::telem_loc_exact) == sizeof(Config),
|
||||
+ sizeof(Config::telem_loc_exact)
|
||||
+ sizeof(Config::home_key_keeps_drawer) == sizeof(Config),
|
||||
"v55 is the current layout minus every byte appended since");
|
||||
Config v55 = safeDefaults();
|
||||
v55.ver = 55;
|
||||
@@ -220,7 +224,8 @@ int main() {
|
||||
static_assert(v57_size + sizeof(Config::attaky_notify_enabled)
|
||||
+ sizeof(Config::attaky_notify_room_color)
|
||||
+ sizeof(Config::attaky_notify_dm_color)
|
||||
+ sizeof(Config::telem_loc_exact) == sizeof(Config),
|
||||
+ sizeof(Config::telem_loc_exact)
|
||||
+ sizeof(Config::home_key_keeps_drawer) == sizeof(Config),
|
||||
"v57 is the current layout minus the Attaky notification fields");
|
||||
Config v57 = safeDefaults();
|
||||
v57.ver = 57;
|
||||
@@ -236,6 +241,22 @@ int main() {
|
||||
assert(migrated.attaky_notify_room_color == 0);
|
||||
assert(migrated.attaky_notify_dm_color == 1);
|
||||
|
||||
// #491 appends the M9 Home-key drawer behavior at v60. A v59 blob keeps
|
||||
// every prior setting, while the new option defaults OFF to preserve the
|
||||
// established Commander/drawer toggle until the user opts in.
|
||||
constexpr size_t v59_size = offsetof(Config, home_key_keeps_drawer);
|
||||
static_assert(v59_size + sizeof(Config::home_key_keeps_drawer) == sizeof(Config),
|
||||
"v59 is the current layout minus the Home-key drawer option");
|
||||
Config v59 = safeDefaults();
|
||||
v59.ver = 59;
|
||||
v59.telem_loc_exact = 1;
|
||||
v59.home_key_keeps_drawer = 1; // outside the stored v59 extent
|
||||
migrated = safeDefaults();
|
||||
assert(TouchPrefsSchema::overlayStored(migrated, &v59, v59_size, &stored_version));
|
||||
assert(stored_version == 59);
|
||||
assert(migrated.telem_loc_exact == 1);
|
||||
assert(migrated.home_key_keeps_drawer == 0);
|
||||
|
||||
Config invalid = safeDefaults();
|
||||
uint8_t garbage[sizeof(Config)] = {};
|
||||
assert(!TouchPrefsSchema::overlayStored(invalid, garbage, sizeof(garbage)));
|
||||
|
||||
Reference in new issue
Block a user