fix: replace long-press lock trigger with back_btn.isPressed() check

Long press detection on back_btn was unreliable — the release generated
a spurious CLICK that cancelled the sequence. Now the Enter click handler
checks back_btn.isPressed() directly: holding Back and clicking Enter 3×
within 3 seconds locks/unlocks the screen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-17 23:08:45 +02:00
co-authored by Claude Sonnet 4.6
parent 2d4f7d3d23
commit e4063c0c8c
2 changed files with 31 additions and 47 deletions
+28 -43
View File
@@ -1186,7 +1186,26 @@ void UITask::loop() {
#if UI_HAS_JOYSTICK #if UI_HAS_JOYSTICK
int ev = user_btn.check(); int ev = user_btn.check();
if (ev == BUTTON_EVENT_CLICK) { if (ev == BUTTON_EVENT_CLICK) {
c = checkDisplayOn(KEY_ENTER); if (back_btn.isPressed()) {
// Enter clicked while Back is held — lock/unlock sequence
if (millis() - _lock_seq_ms > 3000) _lock_seq_count = 0; // timeout reset
_lock_seq_count++;
_lock_seq_ms = millis();
if (_lock_seq_count >= 3) {
_lock_seq_count = 0;
_locked = !_locked;
if (_locked) {
_lock_wake_until = millis() + 2000;
} else {
uint32_t aoff = autoOffMillis();
if (aoff > 0) _auto_off = millis() + aoff;
}
_next_refresh = 0;
}
// eat the Enter — don't pass to curr
} else {
c = checkDisplayOn(KEY_ENTER);
}
} else if (ev == BUTTON_EVENT_LONG_PRESS) { } else if (ev == BUTTON_EVENT_LONG_PRESS) {
c = handleLongPress(KEY_ENTER); // REVISIT: could be mapped to different key code c = handleLongPress(KEY_ENTER); // REVISIT: could be mapped to different key code
} }
@@ -1214,13 +1233,11 @@ void UITask::loop() {
} }
ev = back_btn.check(); ev = back_btn.check();
if (ev == BUTTON_EVENT_CLICK) { if (ev == BUTTON_EVENT_CLICK) {
c = checkDisplayOn(KEY_CANCEL); if (_lock_seq_count > 0) {
} else if (ev == BUTTON_EVENT_LONG_PRESS) { // Back released mid-sequence — cancel sequence, eat the click
if (_display != NULL && _display->isOn()) {
_lock_seq = 1;
_lock_seq_count = 0; _lock_seq_count = 0;
_lock_seq_ms = millis(); } else {
_next_refresh = 0; c = checkDisplayOn(KEY_CANCEL);
} }
} else if (ev == BUTTON_EVENT_TRIPLE_CLICK) { } else if (ev == BUTTON_EVENT_TRIPLE_CLICK) {
c = handleTripleClick(KEY_SELECT); c = handleTripleClick(KEY_SELECT);
@@ -1264,43 +1281,13 @@ void UITask::loop() {
} }
#endif #endif
// Lock sequence timeout check
if (_lock_seq == 1 && millis() - _lock_seq_ms > 3000) {
_lock_seq = 0;
_lock_seq_count = 0;
}
if (c != 0) { if (c != 0) {
// Intercept Enter presses when a lock/unlock sequence is active if (!_locked && curr) {
if (_lock_seq == 1 && c == KEY_ENTER) {
_lock_seq_count++;
if (_lock_seq_count >= 3) {
_lock_seq = 0;
_lock_seq_count = 0;
_locked = !_locked;
if (_locked) {
_lock_wake_until = millis() + 2000; // brief "locked" display, then blank
} else {
uint32_t aoff = autoOffMillis();
if (aoff > 0) _auto_off = millis() + aoff;
}
}
_next_refresh = 0;
} else if (_lock_seq == 1) {
// Non-Enter key cancels the sequence; process key normally below
_lock_seq = 0;
_lock_seq_count = 0;
if (!_locked && curr) {
curr->handleInput(c);
{ uint32_t aoff = autoOffMillis(); if (aoff > 0) _auto_off = millis() + aoff; }
_next_refresh = 100;
}
} else if (!_locked && curr) {
curr->handleInput(c); curr->handleInput(c);
{ uint32_t aoff = autoOffMillis(); if (aoff > 0) _auto_off = millis() + aoff; } // extend auto-off timer { uint32_t aoff = autoOffMillis(); if (aoff > 0) _auto_off = millis() + aoff; } // extend auto-off timer
_next_refresh = 100; // trigger refresh _next_refresh = 100; // trigger refresh
} else if (_locked) { } else if (_locked) {
// Locked: eat all keys except unlock sequence (handled above) // Locked: eat all keys (unlock sequence handled at button-event level above)
// Any key extends the wake window if display is already on // Any key extends the wake window if display is already on
if (_display != NULL && _display->isOn()) if (_display != NULL && _display->isOn())
_lock_wake_until = millis() + 5000; _lock_wake_until = millis() + 5000;
@@ -1372,10 +1359,8 @@ void UITask::loop() {
} }
// Hint popup at bottom (like alert style) // Hint popup at bottom (like alert style)
_display->setTextSize(1); _display->setTextSize(1);
const char* hint = _lock_seq == 1 const char* hint = _lock_seq_count == 0 ? "Hold Back + 3xEnter" :
? (_lock_seq_count == 0 ? "Enter x3 to unlock" : _lock_seq_count == 1 ? "Enter x2 more..." : "Enter x1 more...";
_lock_seq_count == 1 ? "Enter x2 more..." : "Enter x1 more...")
: "Hold Back + 3xEnter";
int p = 3; int p = 3;
int hy = _display->height() - 13; int hy = _display->height() - 13;
int hw = _display->getTextWidth(hint); int hw = _display->getTextWidth(hint);
+3 -4
View File
@@ -35,9 +35,8 @@ class UITask : public AbstractUITask {
NodePrefs* _node_prefs; NodePrefs* _node_prefs;
bool _locked; bool _locked;
unsigned long _lock_wake_until; // when to blank screen again after locked wake (5s) unsigned long _lock_wake_until; // when to blank screen again after locked wake (5s)
int _lock_seq; // 0=idle, 1=active (long-Back pressed, awaiting Enters) int _lock_seq_count; // Enter presses while Back held (lock/unlock sequence)
int _lock_seq_count; // Enter presses so far in current sequence unsigned long _lock_seq_ms; // millis() of last lock-sequence press (for timeout)
unsigned long _lock_seq_ms; // millis() when sequence started
char _alert[80]; char _alert[80];
char _notif_mel_buf[220]; // persistent RTTTL buffer for custom notification melodies char _notif_mel_buf[220]; // persistent RTTTL buffer for custom notification melodies
unsigned long _alert_expiry; unsigned long _alert_expiry;
@@ -93,7 +92,7 @@ public:
_msgcount = _room_unread = 0; _msgcount = _room_unread = 0;
_locked = false; _locked = false;
_lock_wake_until = 0; _lock_wake_until = 0;
_lock_seq = 0; _lock_seq_count = 0; _lock_seq_ms = 0; _lock_seq_count = 0; _lock_seq_ms = 0;
_last_notif_ch_idx = -1; _last_notif_ch_idx = -1;
_last_notif_dm_valid = false; _last_notif_dm_valid = false;
memset(_last_notif_dm_prefix, 0, sizeof(_last_notif_dm_prefix)); memset(_last_notif_dm_prefix, 0, sizeof(_last_notif_dm_prefix));