mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-10-09 03:06:39 +00:00
feat(ui-lvgl): tap-to-wake switch, the side button no longer wakes
Settings > Display & power > WAKE > Tap to wake (NVS, on by default): off, only the top WAKE button turns the screen on. The side USER button doesn't wake the screen any more (a press in a pocket); held, it still mutes / unmutes with the screen off. Roadmap: buttons corrected (WAKE is the top one), USER to open the main menu page later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,8 +5,10 @@ for what comes next, in order. Tick items off as they land.
|
||||
|
||||
Decisions already made:
|
||||
|
||||
- **Buttons:** WAKE (side, expander P00) turns the screen off / on. USER/BOOT
|
||||
goes back; holding it mutes / unmutes the device.
|
||||
- **Buttons:** WAKE (top, expander P00) turns the screen off / on. USER/BOOT
|
||||
(side) goes back; holding it mutes / unmutes the device, also with the
|
||||
screen off; it doesn't wake the screen (a press in a pocket). Later: a
|
||||
click takes you to the main menu page, once the menu is rebuilt.
|
||||
- **Placeholders:** the "+" popup next to a text field is the placeholder UI;
|
||||
it must offer every placeholder and appear at every field that sends text.
|
||||
- **Message history:** kept on the SD card, about 100 per conversation to
|
||||
@@ -251,7 +253,8 @@ User list, second batch (2026-09-26):
|
||||
the MeshCore title font (the wordmark's letters plus l, v, d, digits,
|
||||
'.', '-' drawn to match; Noto for a line with anything else).
|
||||
- [ ] Emoji, ideally the full range (glyphs could live on the SD card).
|
||||
- [ ] Tap-to-wake toggle.
|
||||
- [x] Tap-to-wake toggle (Settings > Display & power > WAKE, NVS, on by
|
||||
default; off: only the top button wakes it).
|
||||
- [ ] Favourites as their own screen in the menu rather than a tile.
|
||||
- [ ] WiFi indicator icon in the status bar.
|
||||
|
||||
|
||||
@@ -226,6 +226,21 @@ static void saveLiveCap(int idx) {
|
||||
p.putChar("ltcap", (int8_t)idx);
|
||||
p.end();
|
||||
}
|
||||
// Settings > Display & power > Tap to wake: a touch turns the dark screen on
|
||||
// (off: only the side button does).
|
||||
static bool loadTapWake() {
|
||||
Preferences p;
|
||||
if (!p.begin("mc_ui", true)) return true;
|
||||
bool on = p.getBool("tapwake", true);
|
||||
p.end();
|
||||
return on;
|
||||
}
|
||||
static void saveTapWake(bool on) {
|
||||
Preferences p;
|
||||
if (!p.begin("mc_ui", false)) return;
|
||||
p.putBool("tapwake", on);
|
||||
p.end();
|
||||
}
|
||||
// Filesystem size and space in use (Settings > Storage), plus the card's own
|
||||
// size -- a card whose FAT partition is small (e.g. written by a Raspberry Pi
|
||||
// imager) shows both. The first free-space count on a big card takes a moment.
|
||||
@@ -514,6 +529,9 @@ static void saveHistKeep(int idx) { s_hist_keep = idx; }
|
||||
static int s_live_cap = -1;
|
||||
static int loadLiveCap() { return s_live_cap; }
|
||||
static void saveLiveCap(int idx) { s_live_cap = idx; }
|
||||
static bool s_tap_wake = true;
|
||||
static bool loadTapWake() { return s_tap_wake; }
|
||||
static void saveTapWake(bool on) { s_tap_wake = on; }
|
||||
// The browser has no card: a nominal 32 GB, used = what the files add up to
|
||||
// (the storage screen counts them anyway; it passes that in).
|
||||
static bool sdInfo(uint64_t& total, uint64_t& used, uint64_t& card) { total = card = 32ULL << 30; used = 0; return true; }
|
||||
|
||||
@@ -222,6 +222,7 @@ void UITask::begin(DisplayDriver* display_drv, SensorManager* sensors, NodePrefs
|
||||
s_archive.restore(_core->history);
|
||||
_core->history.setArchive(&s_archive);
|
||||
}
|
||||
_tap_wake = lvport::loadTapWake();
|
||||
msgtext::seedQuick(node_prefs); // "OK" in quick message 1 on first boot
|
||||
_nearby = new NearbyModel();
|
||||
_nearby->bindModel(_core, node_prefs);
|
||||
@@ -274,8 +275,9 @@ void UITask::loop() {
|
||||
pollConnection();
|
||||
drainCoreEvents();
|
||||
|
||||
// USER (BOOT) button: back; held, mutes / unmutes. WAKE button: screen off /
|
||||
// on. Either one silences a ringing alarm first.
|
||||
// USER (BOOT, side) button: back; held, mutes / unmutes, also with the
|
||||
// screen off, which it doesn't wake. WAKE (top) button: screen off / on.
|
||||
// Either one silences a ringing alarm first.
|
||||
bool btn_click = false, btn_hold = false, wake_press = false;
|
||||
#ifdef PIN_USER_BTN
|
||||
int ev = user_btn.check();
|
||||
@@ -298,10 +300,10 @@ void UITask::loop() {
|
||||
if ((btn_click || btn_hold || wake_press) && _core->clock.isRinging()) dismissRing();
|
||||
else if (wake_press) { if (_asleep) wake(); else sleep(); }
|
||||
else if (btn_hold) toggleMute();
|
||||
else if (btn_click) { if (_asleep) wake(); else if (!locked()) back(); }
|
||||
else if (btn_click) { if (!_asleep && !locked()) back(); } // the side button doesn't wake: pockets
|
||||
|
||||
if (_asleep) {
|
||||
if (lvport::touched()) { lvport::swallowTouch(); wake(); }
|
||||
if (lvport::touched()) { lvport::swallowTouch(); if (_tap_wake) wake(); } // off: the top (WAKE) button only
|
||||
} else {
|
||||
uint32_t aoff = autoOffMillis();
|
||||
if (aoff > 0 && lv_display_get_inactive_time(NULL) > aoff && !_core->clock.isRinging() && !otaBusy()) sleep();
|
||||
@@ -2374,6 +2376,15 @@ void UITask::setBrightnessPct(uint8_t pct, bool save) {
|
||||
if (save) the_mesh.savePrefs();
|
||||
}
|
||||
|
||||
static void onTapWake(lv_event_t* e) {
|
||||
s_ui->setTapWake(lv_obj_has_state((lv_obj_t*)lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
}
|
||||
|
||||
void UITask::setTapWake(bool on) {
|
||||
_tap_wake = on;
|
||||
lvport::saveTapWake(on);
|
||||
}
|
||||
|
||||
void UITask::buildSchemaSettings() {
|
||||
lv_obj_t* body = newScreen(settings::pageTitle(_settings_page), true);
|
||||
_prune_lbl = nullptr;
|
||||
@@ -2390,6 +2401,10 @@ void UITask::buildSchemaSettings() {
|
||||
lv_obj_center(_prune_lbl);
|
||||
}
|
||||
if (_settings_page == settings::PG_DEVICE) { // after Lock screen's section, in NVS not the schema
|
||||
sectionTitle(body, "WAKE");
|
||||
lv_obj_t* tw = switchRow(body, "Tap to wake", "Off: only the top button turns it on", nullptr);
|
||||
if (_tap_wake) lv_obj_add_state(tw, LV_STATE_CHECKED);
|
||||
lv_obj_add_event_cb(tw, onTapWake, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
sectionTitle(body, "SECURITY");
|
||||
listRow(body, LV_SYMBOL_EYE_CLOSE " Screen PIN", _pin[0] ? "On - asked when the screen wakes" : "Off",
|
||||
onPinSetup, NULL);
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
void mapPan(int dx, int dy);
|
||||
void mapOpenMarker(int idx);
|
||||
void mapDownloadPopup();
|
||||
void setTapWake(bool on);
|
||||
void mapDownloadClose();
|
||||
void mapDownloadStart();
|
||||
void mapDownloadStop();
|
||||
@@ -404,6 +405,7 @@ private:
|
||||
lv_obj_t* _prune_lbl = nullptr;
|
||||
// Screen PIN (DeviceScreen.h); stored in NVS (lvport::loadPin)
|
||||
char _pin[9] = ""; // "" = no PIN
|
||||
bool _tap_wake = true; // a touch wakes the dark screen (NVS)
|
||||
char _pin_entry[9] = ""; // digits typed so far
|
||||
char _pin_new[9] = ""; // setup: the first entry, waiting for its confirmation
|
||||
uint8_t _pin_fails = 0;
|
||||
|
||||
Reference in New Issue
Block a user