Add multi-tap channel navigation for messages

This commit is contained in:
mikecarper committed 2026-09-08 22:47:15 -07:00
1 parent c690f65376
commit f778d14c76
12 files changed
+431 -68

No files matched your search

+3 -2
View File
@@ -210,8 +210,9 @@ int MomentaryButton::check(bool repeat_click) {
event = BUTTON_EVENT_TRIPLE_CLICK;
break;
default:
// For 4+ clicks, treat as triple click?
event = BUTTON_EVENT_TRIPLE_CLICK;
// Screens with group navigation opt into a distinct four-tap event.
event = _quadruple_click ? BUTTON_EVENT_QUADRUPLE_CLICK
: BUTTON_EVENT_TRIPLE_CLICK;
break;
}
_click_count = 0;
+3
View File
@@ -7,6 +7,7 @@
#define BUTTON_EVENT_LONG_PRESS 2
#define BUTTON_EVENT_DOUBLE_CLICK 3
#define BUTTON_EVENT_TRIPLE_CLICK 4
#define BUTTON_EVENT_QUADRUPLE_CLICK 5
#ifndef MOMENTARY_BUTTON_WAKE_HOLD_MS
#define MOMENTARY_BUTTON_WAKE_HOLD_MS 0
@@ -24,6 +25,7 @@ class MomentaryButton {
uint32_t _last_click_time;
int _multi_click_window;
bool _pending_click;
bool _quadruple_click = false;
int8_t _candidate_level;
uint32_t _candidate_since;
bool _debouncing;
@@ -39,6 +41,7 @@ public:
MomentaryButton(int8_t pin, int long_press_mills, int analog_threshold);
virtual void begin();
virtual int check(bool repeat_click=false); // returns one of BUTTON_EVENT_*
void enableQuadrupleClick() { _quadruple_click = true; }
void cancelClick(); // suppress next BUTTON_EVENT_CLICK (if already in DOWN state)
uint8_t getPin() { return _pin; }
bool isPressed() const;
+14 -7
View File
@@ -12,28 +12,35 @@ struct ButtonReaderHintLayout {
const char* lines[3];
};
// Match the single-button UI: double click is Previous, click is Next, and
// hold is Enter/exit. Measure with the reader's font, including tiny panels.
// Alternate page and group navigation within the same footer. Measure both
// views so changing the hint never repaginates text or hides a message row.
inline ButtonReaderHintLayout makeButtonReaderHintLayout(
DisplayDriver& text, int line_height, int bottom) {
DisplayDriver& text, int line_height, int bottom, bool show_groups = false) {
ButtonReaderHintLayout layout = {
0, line_height, 1, {"<- 2 tap 1 tap -> long press: exit", nullptr, nullptr}};
const char* group_line = "<<- 4 tap 3 tap ->>";
if (text.getTextWidth(layout.lines[0]) > text.width()
&& text.getTextWidth("<-2 tap 1 tap-> hold: exit") <= text.width()) {
layout.lines[0] = "<-2 tap 1 tap-> hold: exit";
&& text.getTextWidth("<-2 tap 1 tap-> hold: X") <= text.width()) {
layout.lines[0] = "<-2 tap 1 tap-> hold: X";
}
if (text.getTextWidth(layout.lines[0]) > text.width()) {
if (text.getTextWidth(layout.lines[0]) > text.width()
|| text.getTextWidth(group_line) > text.width()) {
layout.line_count = 2;
layout.lines[0] = "<- 2 tap 1 tap ->";
layout.lines[1] = "long press: exit";
if (text.getTextWidth(layout.lines[0]) > text.width()
|| text.getTextWidth(group_line) > text.width()
|| text.getTextWidth(layout.lines[1]) > text.width()) {
layout.line_count = 3;
layout.lines[0] = "<- 2 tap";
layout.lines[1] = "1 tap ->";
layout.lines[2] = "hold: exit";
layout.lines[2] = "hold: X";
}
}
if (show_groups) {
layout.lines[0] = layout.line_count < 3 ? group_line : "<<- 4 tap";
if (layout.line_count == 3) layout.lines[1] = "3 tap ->>";
}
layout.top = bottom - layout.line_count * line_height;
if (layout.top < 0) layout.top = 0;
return layout;