mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-01 01:36:12 +00:00
refactor(ui): audit-pass fixes + dead-code/redundancy cleanup
Fixes from a full ui-new audit (OLED + e-ink both build green): - remove dead DisplayDriver::drawScrollArrows (all lists use drawScrollIndicator) - SettingsScreen selection bar -> lineStep()-1, matching the drawList screens - HomeScreen: don't force the 1s blink refresh on the CLOCK page (status icons are hidden there anyway) - FullscreenMsgView: clamp KEY_DOWN scroll to a cached _max_scroll instead of over-incrementing and leaning on the next render to clamp - DataStore: clamp use_lemon_font (>1 -> 0) on load, like the other enum fields - move the ~1.5KB wrap scratch (trans/lines) off the render stack into shared file-scope statics in FullscreenMsgView (single-threaded UI; the fullscreen view and history list never lay out in the same frame) Cleanup: - drop dead members RingtoneEditorScreen::DUR_VALS and HomeScreen::sensors_scroll - delete redundant manual scroll-clamps in handleInput across the drawList screens (drawList already reclamps each render); remove the now-unused _visible from QuickMsgScreen/NearbyScreen/BotScreen and BotScreen::scrollToSel() Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -338,6 +338,9 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
|
|||||||
// can leave stray bytes here, so clamp out-of-range values back to defaults.
|
// can leave stray bytes here, so clamp out-of-range values back to defaults.
|
||||||
// Values for notif_melody_ad: 0=built-in, 1=melody1, 2=melody2, 3=none.
|
// Values for notif_melody_ad: 0=built-in, 1=melody1, 2=melody2, 3=none.
|
||||||
if (_prefs.notif_melody_ad > 3) _prefs.notif_melody_ad = 0;
|
if (_prefs.notif_melody_ad > 3) _prefs.notif_melody_ad = 0;
|
||||||
|
// A stale value >1 from an older multi-font build would read as "Lemon" (all
|
||||||
|
// sites test != 0) until the user toggles Font; clamp it to default here.
|
||||||
|
if (_prefs.use_lemon_font > 1) _prefs.use_lemon_font = 0;
|
||||||
if (_prefs.units_imperial > 1) _prefs.units_imperial = 0;
|
if (_prefs.units_imperial > 1) _prefs.units_imperial = 0;
|
||||||
if (_prefs.trail_show_pace > 1) _prefs.trail_show_pace = 0;
|
if (_prefs.trail_show_pace > 1) _prefs.trail_show_pace = 0;
|
||||||
if (_prefs.advert_sound_scope > 1) _prefs.advert_sound_scope = ADVERT_SOUND_SCOPE_ALL;
|
if (_prefs.advert_sound_scope > 1) _prefs.advert_sound_scope = ADVERT_SOUND_SCOPE_ALL;
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ class BotScreen : public UIScreen {
|
|||||||
static const int ITEM_COUNT = 9;
|
static const int ITEM_COUNT = 9;
|
||||||
|
|
||||||
int _sel;
|
int _sel;
|
||||||
int _scroll; // index of first visible item
|
int _scroll; // index of first visible item (managed by drawList in render)
|
||||||
int _visible; // items fitting on screen; updated each render, used by handleInput
|
|
||||||
bool _dirty;
|
bool _dirty;
|
||||||
|
|
||||||
// keyboard state (reused for trigger and reply fields)
|
// keyboard state (reused for trigger and reply fields)
|
||||||
@@ -32,12 +31,6 @@ class BotScreen : public UIScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the selected row inside the visible window (_visible set by render()).
|
|
||||||
void scrollToSel() {
|
|
||||||
if (_sel < _scroll) _scroll = _sel;
|
|
||||||
else if (_sel >= _scroll + _visible) _scroll = _sel - _visible + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns index into _channel_indices[] for current bot_channel_idx, or -1 if not found/disabled.
|
// Returns index into _channel_indices[] for current bot_channel_idx, or -1 if not found/disabled.
|
||||||
int currentChannelListIdx() const {
|
int currentChannelListIdx() const {
|
||||||
if (!_prefs->bot_channel_enabled) return -1;
|
if (!_prefs->bot_channel_enabled) return -1;
|
||||||
@@ -52,7 +45,6 @@ public:
|
|||||||
void enter() {
|
void enter() {
|
||||||
_sel = 0;
|
_sel = 0;
|
||||||
_scroll = 0;
|
_scroll = 0;
|
||||||
_visible = 1;
|
|
||||||
_kb_field = -1;
|
_kb_field = -1;
|
||||||
_dirty = false;
|
_dirty = false;
|
||||||
refreshChannels();
|
refreshChannels();
|
||||||
@@ -82,7 +74,7 @@ public:
|
|||||||
static const char* labels[] = { "Enable", "Channel", "Trigger DM", "Reply DM",
|
static const char* labels[] = { "Enable", "Channel", "Trigger DM", "Reply DM",
|
||||||
"Trigger Ch", "Reply Ch", "Commands",
|
"Trigger Ch", "Reply Ch", "Commands",
|
||||||
"Quiet from", "Quiet to" };
|
"Quiet from", "Quiet to" };
|
||||||
_visible = drawList(display, ITEM_COUNT, _sel, _scroll, [&](int i, int y, bool sel, int reserve) {
|
drawList(display, ITEM_COUNT, _sel, _scroll, [&](int i, int y, bool sel, int reserve) {
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - reserve, display.lineStep() - 1, sel);
|
display.drawSelectionRow(0, y - 1, display.width() - reserve, display.lineStep() - 1, sel);
|
||||||
display.setCursor(2, y);
|
display.setCursor(2, y);
|
||||||
display.print(labels[i]);
|
display.print(labels[i]);
|
||||||
@@ -153,8 +145,9 @@ public:
|
|||||||
_task->gotoToolsScreen();
|
_task->gotoToolsScreen();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (up && _sel > 0) { _sel--; scrollToSel(); return true; }
|
// drawList() reclamps _scroll from _sel every render.
|
||||||
if (down && _sel < ITEM_COUNT - 1) { _sel++; scrollToSel(); return true; }
|
if (up && _sel > 0) { _sel--; return true; }
|
||||||
|
if (down && _sel < ITEM_COUNT - 1) { _sel++; return true; }
|
||||||
|
|
||||||
if (_sel == 0 && (enter || left || right)) {
|
if (_sel == 0 && (enter || left || right)) {
|
||||||
_prefs->bot_enabled ^= 1;
|
_prefs->bot_enabled ^= 1;
|
||||||
|
|||||||
@@ -6,11 +6,22 @@
|
|||||||
|
|
||||||
static const int FS_CHARS_MAX = 80; // max bytes per wrapped line
|
static const int FS_CHARS_MAX = 80; // max bytes per wrapped line
|
||||||
|
|
||||||
|
// Shared, non-reentrant wrap scratch. The UI renders on a single thread, and the
|
||||||
|
// fullscreen message view and the history list are never laid out in the same
|
||||||
|
// frame (opening the fullscreen view early-returns before the list loop runs),
|
||||||
|
// so one static buffer serves both. This keeps ~1.5 KB of line buffers off the
|
||||||
|
// render-call stack (see CODE_REVIEW.md "Render-path stack peak") at the cost of
|
||||||
|
// a fixed RAM allocation. Only used inside render()/wrap helpers — never across
|
||||||
|
// a yield, so the single instance is safe.
|
||||||
|
static char s_wrap_trans[512];
|
||||||
|
static char s_wrap_lines[12][FS_CHARS_MAX];
|
||||||
|
|
||||||
struct FullscreenMsgView {
|
struct FullscreenMsgView {
|
||||||
int scroll;
|
int scroll;
|
||||||
bool active;
|
bool active;
|
||||||
|
int _max_scroll; // last value computed in render(); bounds KEY_DOWN
|
||||||
|
|
||||||
FullscreenMsgView() : scroll(0), active(false) {}
|
FullscreenMsgView() : scroll(0), active(false), _max_scroll(0) {}
|
||||||
|
|
||||||
enum Result { NONE, PREV, NEXT, CLOSE, REPLY };
|
enum Result { NONE, PREV, NEXT, CLOSE, REPLY };
|
||||||
|
|
||||||
@@ -100,22 +111,21 @@ struct FullscreenMsgView {
|
|||||||
}
|
}
|
||||||
display.setColor(DisplayDriver::LIGHT);
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
|
|
||||||
char trans_text[512];
|
display.translateUTF8ToBlocks(s_wrap_trans, body, sizeof(s_wrap_trans));
|
||||||
display.translateUTF8ToBlocks(trans_text, body, sizeof(trans_text));
|
int lcount = wrapLines(display, s_wrap_trans, max_px, s_wrap_lines, 12);
|
||||||
char lines[12][FS_CHARS_MAX];
|
|
||||||
int lcount = wrapLines(display, trans_text, max_px, lines, 12);
|
|
||||||
// Reserve the right-edge column for the scroll indicator and re-wrap so text
|
// Reserve the right-edge column for the scroll indicator and re-wrap so text
|
||||||
// can't run under it. Reserve appears only once the list overflows, and a
|
// can't run under it. Reserve appears only once the list overflows, and a
|
||||||
// narrower second pass only ever yields more lines — so it stays overflowing.
|
// narrower second pass only ever yields more lines — so it stays overflowing.
|
||||||
int reserve = scrollIndicatorReserve(display, lcount, visible);
|
int reserve = scrollIndicatorReserve(display, lcount, visible);
|
||||||
if (reserve > 0)
|
if (reserve > 0)
|
||||||
lcount = wrapLines(display, trans_text, max_px - reserve, lines, 12);
|
lcount = wrapLines(display, s_wrap_trans, max_px - reserve, s_wrap_lines, 12);
|
||||||
int max_scroll = lcount > visible ? lcount - visible : 0;
|
int max_scroll = lcount > visible ? lcount - visible : 0;
|
||||||
|
_max_scroll = max_scroll;
|
||||||
if (scroll > max_scroll) scroll = max_scroll;
|
if (scroll > max_scroll) scroll = max_scroll;
|
||||||
|
|
||||||
for (int i = 0; i < visible && (scroll + i) < lcount; i++) {
|
for (int i = 0; i < visible && (scroll + i) < lcount; i++) {
|
||||||
display.setCursor(0, startY + i * lineH);
|
display.setCursor(0, startY + i * lineH);
|
||||||
display.print(lines[scroll + i]);
|
display.print(s_wrap_lines[scroll + i]);
|
||||||
}
|
}
|
||||||
drawScrollIndicator(display, startY, visible * lineH, lcount, visible, scroll);
|
drawScrollIndicator(display, startY, visible * lineH, lcount, visible, scroll);
|
||||||
const int nav_y = display.height() - lineH;
|
const int nav_y = display.height() - lineH;
|
||||||
@@ -132,7 +142,7 @@ struct FullscreenMsgView {
|
|||||||
|
|
||||||
Result handleInput(char c) {
|
Result handleInput(char c) {
|
||||||
if (c == KEY_UP) { if (scroll > 0) scroll--; return NONE; }
|
if (c == KEY_UP) { if (scroll > 0) scroll--; return NONE; }
|
||||||
if (c == KEY_DOWN) { scroll++; return NONE; }
|
if (c == KEY_DOWN) { if (scroll < _max_scroll) scroll++; return NONE; }
|
||||||
if (c == KEY_LEFT) return NEXT;
|
if (c == KEY_LEFT) return NEXT;
|
||||||
if (c == KEY_RIGHT) return PREV;
|
if (c == KEY_RIGHT) return PREV;
|
||||||
if (c == KEY_CONTEXT_MENU) return REPLY;
|
if (c == KEY_CONTEXT_MENU) return REPLY;
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
class NearbyScreen : public UIScreen {
|
class NearbyScreen : public UIScreen {
|
||||||
UITask* _task;
|
UITask* _task;
|
||||||
|
|
||||||
int _visible = 4; // updated each render; used by handleInput for scroll clamping
|
|
||||||
|
|
||||||
// ── filter (type axis) ──────────────────────────────────────────────────────
|
// ── filter (type axis) ──────────────────────────────────────────────────────
|
||||||
enum Filter : uint8_t { F_ALL, F_FAV, F_COMP, F_RPT, F_ROOM, F_SNSR, F_COUNT };
|
enum Filter : uint8_t { F_ALL, F_FAV, F_COMP, F_RPT, F_ROOM, F_SNSR, F_COUNT };
|
||||||
static const char* FILTER_LABELS[F_COUNT];
|
static const char* FILTER_LABELS[F_COUNT];
|
||||||
@@ -550,9 +548,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int item_h = display.lineStep();
|
int item_h = display.lineStep();
|
||||||
int start_y = display.listStart();
|
|
||||||
int dist_col = display.width() - display.getCharWidth() * 7;
|
int dist_col = display.width() - display.getCharWidth() * 7;
|
||||||
_visible = display.listVisible(item_h);
|
|
||||||
|
|
||||||
display.setColor(DisplayDriver::LIGHT);
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
char title[28];
|
char title[28];
|
||||||
@@ -587,7 +583,7 @@ public:
|
|||||||
display.drawTextCentered(display.width() / 2, display.height() / 2 + display.lineStep() / 2, hint);
|
display.drawTextCentered(display.width() / 2, display.height() / 2 + display.lineStep() / 2, hint);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_visible = drawList(display, _count, _sel, _scroll, [&](int idx, int y, bool sel, int reserve) {
|
drawList(display, _count, _sel, _scroll, [&](int idx, int y, bool sel, int reserve) {
|
||||||
const Entry& e = _entries[idx];
|
const Entry& e = _entries[idx];
|
||||||
|
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
||||||
@@ -671,16 +667,9 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c == KEY_CONTEXT_MENU) { openActionMenu(); return true; }
|
if (c == KEY_CONTEXT_MENU) { openActionMenu(); return true; }
|
||||||
if (c == KEY_UP && _sel > 0) {
|
// drawList() reclamps _scroll from _sel every render.
|
||||||
_sel--;
|
if (c == KEY_UP && _sel > 0) { _sel--; return true; }
|
||||||
if (_sel < _scroll) _scroll = _sel;
|
if (c == KEY_DOWN && _sel < _count - 1) { _sel++; return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_DOWN && _sel < _count - 1) {
|
|
||||||
_sel++;
|
|
||||||
if (_sel >= _scroll + _visible) _scroll = _sel - _visible + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_ENTER) {
|
if (c == KEY_ENTER) {
|
||||||
if (_count == 0) { if (_source == SRC_STORED) enterScan(); return true; }
|
if (_count == 0) { if (_source == SRC_STORED) enterScan(); return true; }
|
||||||
_detail = true;
|
_detail = true;
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ class QuickMsgScreen : public UIScreen {
|
|||||||
int _dm_hist_sel, _dm_hist_scroll;
|
int _dm_hist_sel, _dm_hist_scroll;
|
||||||
FullscreenMsgView _dm_fs;
|
FullscreenMsgView _dm_fs;
|
||||||
|
|
||||||
int _visible = 4; // updated in render(); used by handleInput() for scroll clamping
|
|
||||||
int _hist_visible = 2; // updated in render(); for history list scroll clamping
|
int _hist_visible = 2; // updated in render(); for history list scroll clamping
|
||||||
|
|
||||||
void expandMsg(const char* tmpl, char* out, int out_len) const {
|
void expandMsg(const char* tmpl, char* out, int out_len) const {
|
||||||
@@ -819,7 +818,6 @@ public:
|
|||||||
int item_h = display.lineStep();
|
int item_h = display.lineStep();
|
||||||
int start_y = display.listStart();
|
int start_y = display.listStart();
|
||||||
int cw = display.getCharWidth();
|
int cw = display.getCharWidth();
|
||||||
_visible = display.listVisible(item_h);
|
|
||||||
|
|
||||||
if (_phase == MODE_SELECT) {
|
if (_phase == MODE_SELECT) {
|
||||||
display.drawCenteredHeader("MESSAGE");
|
display.drawCenteredHeader("MESSAGE");
|
||||||
@@ -854,7 +852,7 @@ public:
|
|||||||
return 5000;
|
return 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
_visible = drawList(display, _num_contacts, _contact_sel, _contact_scroll, [&](int list_idx, int y, bool sel, int reserve) {
|
drawList(display, _num_contacts, _contact_sel, _contact_scroll, [&](int list_idx, int y, bool sel, int reserve) {
|
||||||
int mesh_idx = _sorted[list_idx];
|
int mesh_idx = _sorted[list_idx];
|
||||||
|
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
||||||
@@ -889,7 +887,7 @@ public:
|
|||||||
return 5000;
|
return 5000;
|
||||||
}
|
}
|
||||||
|
|
||||||
_visible = drawList(display, _num_channels, _channel_sel, _channel_scroll, [&](int list_idx, int y, bool sel, int reserve) {
|
drawList(display, _num_channels, _channel_sel, _channel_scroll, [&](int list_idx, int y, bool sel, int reserve) {
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
||||||
ChannelDetails ch;
|
ChannelDetails ch;
|
||||||
if (the_mesh.getChannel(_channel_indices[list_idx], ch)) {
|
if (the_mesh.getChannel(_channel_indices[list_idx], ch)) {
|
||||||
@@ -966,10 +964,8 @@ public:
|
|||||||
if (portrait_expand) {
|
if (portrait_expand) {
|
||||||
int rp = dmHistEntryForContact(_sel_contact.id.pub_key, _dm_hist_scroll + ii);
|
int rp = dmHistEntryForContact(_sel_contact.id.pub_key, _dm_hist_scroll + ii);
|
||||||
if (rp >= 0) {
|
if (rp >= 0) {
|
||||||
char trans[160];
|
display.translateUTF8ToBlocks(s_wrap_trans, skipReplyPrefix(_dm_hist[rp].text), sizeof(s_wrap_trans));
|
||||||
display.translateUTF8ToBlocks(trans, skipReplyPrefix(_dm_hist[rp].text), sizeof(trans));
|
int nl = FullscreenMsgView::wrapLines(display, s_wrap_trans, display.width() - 6 - reserve, s_wrap_lines, 8);
|
||||||
char wl[8][FS_CHARS_MAX];
|
|
||||||
int nl = FullscreenMsgView::wrapLines(display, trans, display.width() - 6 - reserve, wl, 8);
|
|
||||||
bh = (1 + (nl > 0 ? nl : 1)) * lh + 1;
|
bh = (1 + (nl > 0 ? nl : 1)) * lh + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1012,11 +1008,9 @@ public:
|
|||||||
if (age[0]) { display.setCursor(display.width() - age_w - reserve, y + 1); display.print(age); }
|
if (age[0]) { display.setCursor(display.width() - age_w - reserve, y + 1); display.print(age); }
|
||||||
if (!sel) display.setColor(DisplayDriver::LIGHT);
|
if (!sel) display.setColor(DisplayDriver::LIGHT);
|
||||||
if (portrait_expand) {
|
if (portrait_expand) {
|
||||||
char trans[160];
|
display.translateUTF8ToBlocks(s_wrap_trans, skipReplyPrefix(e.text), sizeof(s_wrap_trans));
|
||||||
display.translateUTF8ToBlocks(trans, skipReplyPrefix(e.text), sizeof(trans));
|
int nl = FullscreenMsgView::wrapLines(display, s_wrap_trans, display.width() - 6 - reserve, s_wrap_lines, 8);
|
||||||
char wl[8][FS_CHARS_MAX];
|
for (int li = 0; li < nl; li++) { display.setCursor(3, y + (li + 1) * lh + 1); display.print(s_wrap_lines[li]); }
|
||||||
int nl = FullscreenMsgView::wrapLines(display, trans, display.width() - 6 - reserve, wl, 8);
|
|
||||||
for (int li = 0; li < nl; li++) { display.setCursor(3, y + (li + 1) * lh + 1); display.print(wl[li]); }
|
|
||||||
} else {
|
} else {
|
||||||
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(e.text));
|
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(e.text));
|
||||||
}
|
}
|
||||||
@@ -1109,10 +1103,8 @@ public:
|
|||||||
const char* rtext = _hist[rp].text;
|
const char* rtext = _hist[rp].text;
|
||||||
const char* rsep = strstr(rtext, ": ");
|
const char* rsep = strstr(rtext, ": ");
|
||||||
const char* rbody = rsep ? rsep + 2 : rtext;
|
const char* rbody = rsep ? rsep + 2 : rtext;
|
||||||
char trans[160];
|
display.translateUTF8ToBlocks(s_wrap_trans, skipReplyPrefix(rbody), sizeof(s_wrap_trans));
|
||||||
display.translateUTF8ToBlocks(trans, skipReplyPrefix(rbody), sizeof(trans));
|
int nl = FullscreenMsgView::wrapLines(display, s_wrap_trans, display.width() - 6 - reserve, s_wrap_lines, 8);
|
||||||
char wl[8][FS_CHARS_MAX];
|
|
||||||
int nl = FullscreenMsgView::wrapLines(display, trans, display.width() - 6 - reserve, wl, 8);
|
|
||||||
bh = (1 + (nl > 0 ? nl : 1)) * lh + 1;
|
bh = (1 + (nl > 0 ? nl : 1)) * lh + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1170,11 +1162,9 @@ public:
|
|||||||
if (age[0]) { display.setCursor(display.width() - age_w - reserve, y + 1); display.print(age); }
|
if (age[0]) { display.setCursor(display.width() - age_w - reserve, y + 1); display.print(age); }
|
||||||
if (!sel) display.setColor(DisplayDriver::LIGHT);
|
if (!sel) display.setColor(DisplayDriver::LIGHT);
|
||||||
if (portrait_expand) {
|
if (portrait_expand) {
|
||||||
char trans[160];
|
display.translateUTF8ToBlocks(s_wrap_trans, skipReplyPrefix(msg_part), sizeof(s_wrap_trans));
|
||||||
display.translateUTF8ToBlocks(trans, skipReplyPrefix(msg_part), sizeof(trans));
|
int nl = FullscreenMsgView::wrapLines(display, s_wrap_trans, display.width() - 6 - reserve, s_wrap_lines, 8);
|
||||||
char wl[8][FS_CHARS_MAX];
|
for (int li = 0; li < nl; li++) { display.setCursor(3, y + (li + 1) * lh + 1); display.print(s_wrap_lines[li]); }
|
||||||
int nl = FullscreenMsgView::wrapLines(display, trans, display.width() - 6 - reserve, wl, 8);
|
|
||||||
for (int li = 0; li < nl; li++) { display.setCursor(3, y + (li + 1) * lh + 1); display.print(wl[li]); }
|
|
||||||
} else {
|
} else {
|
||||||
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(msg_part));
|
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(msg_part));
|
||||||
}
|
}
|
||||||
@@ -1233,7 +1223,7 @@ public:
|
|||||||
display.drawCenteredHeader(title);
|
display.drawCenteredHeader(title);
|
||||||
|
|
||||||
int total_msg_items = 1 + _active_msg_count;
|
int total_msg_items = 1 + _active_msg_count;
|
||||||
_visible = drawList(display, total_msg_items, _msg_sel, _msg_scroll, [&](int idx, int y, bool sel, int reserve) {
|
drawList(display, total_msg_items, _msg_sel, _msg_scroll, [&](int idx, int y, bool sel, int reserve) {
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
display.drawSelectionRow(0, y - 1, display.width() - reserve, item_h - 1, sel);
|
||||||
|
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
@@ -1398,16 +1388,9 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c == KEY_CANCEL) { _room_mode = false; _phase = MODE_SELECT; return true; }
|
if (c == KEY_CANCEL) { _room_mode = false; _phase = MODE_SELECT; return true; }
|
||||||
if (c == KEY_UP && _contact_sel > 0) {
|
// drawList() reclamps _contact_scroll from _contact_sel every render.
|
||||||
_contact_sel--;
|
if (c == KEY_UP && _contact_sel > 0) { _contact_sel--; return true; }
|
||||||
if (_contact_sel < _contact_scroll) _contact_scroll = _contact_sel;
|
if (c == KEY_DOWN && _contact_sel < _num_contacts - 1) { _contact_sel++; return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_DOWN && _contact_sel < _num_contacts - 1) {
|
|
||||||
_contact_sel++;
|
|
||||||
if (_contact_sel >= _contact_scroll + _visible) _contact_scroll = _contact_sel - _visible + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_ENTER && _num_contacts > 0) {
|
if (c == KEY_ENTER && _num_contacts > 0) {
|
||||||
if (the_mesh.getContactByIdx(_sorted[_contact_sel], _sel_contact)) {
|
if (the_mesh.getContactByIdx(_sorted[_contact_sel], _sel_contact)) {
|
||||||
_task->clearDMUnread(_sel_contact.id.pub_key);
|
_task->clearDMUnread(_sel_contact.id.pub_key);
|
||||||
@@ -1495,16 +1478,9 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c == KEY_CANCEL) { _phase = MODE_SELECT; return true; }
|
if (c == KEY_CANCEL) { _phase = MODE_SELECT; return true; }
|
||||||
if (c == KEY_UP && _channel_sel > 0) {
|
// drawList() reclamps _channel_scroll from _channel_sel every render.
|
||||||
_channel_sel--;
|
if (c == KEY_UP && _channel_sel > 0) { _channel_sel--; return true; }
|
||||||
if (_channel_sel < _channel_scroll) _channel_scroll = _channel_sel;
|
if (c == KEY_DOWN && _channel_sel < _num_channels - 1) { _channel_sel++; return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_DOWN && _channel_sel < _num_channels - 1) {
|
|
||||||
_channel_sel++;
|
|
||||||
if (_channel_sel >= _channel_scroll + _visible) _channel_scroll = _channel_sel - _visible + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_ENTER && _num_channels > 0) {
|
if (c == KEY_ENTER && _num_channels > 0) {
|
||||||
_sel_channel_idx = _channel_indices[_channel_sel];
|
_sel_channel_idx = _channel_indices[_channel_sel];
|
||||||
int hc = histCountForChannel(_sel_channel_idx);
|
int hc = histCountForChannel(_sel_channel_idx);
|
||||||
@@ -1727,16 +1703,9 @@ public:
|
|||||||
_phase = _sending_to_channel ? CHANNEL_HIST : DM_HIST;
|
_phase = _sending_to_channel ? CHANNEL_HIST : DM_HIST;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (c == KEY_UP && _msg_sel > 0) {
|
// drawList() reclamps _msg_scroll from _msg_sel every render.
|
||||||
_msg_sel--;
|
if (c == KEY_UP && _msg_sel > 0) { _msg_sel--; return true; }
|
||||||
if (_msg_sel < _msg_scroll) _msg_scroll = _msg_sel;
|
if (c == KEY_DOWN && _msg_sel < total_msg_items - 1) { _msg_sel++; return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_DOWN && _msg_sel < total_msg_items - 1) {
|
|
||||||
_msg_sel++;
|
|
||||||
if (_msg_sel >= _msg_scroll + _visible) _msg_scroll = _msg_sel - _visible + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (c == KEY_ENTER) {
|
if (c == KEY_ENTER) {
|
||||||
if (_msg_sel == 0) {
|
if (_msg_sel == 0) {
|
||||||
_kb->begin(_reply_mode ? _reply_prefix : "");
|
_kb->begin(_reply_mode ? _reply_prefix : "");
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class RingtoneEditorScreen : public UIScreen {
|
|||||||
int _visible_notes = 7; // updated in render(); used by clampScroll()
|
int _visible_notes = 7; // updated in render(); used by clampScroll()
|
||||||
|
|
||||||
static const uint16_t BPM_OPTS[5];
|
static const uint16_t BPM_OPTS[5];
|
||||||
static const uint8_t DUR_VALS[4];
|
|
||||||
static const char* DUR_LABELS[4];
|
static const char* DUR_LABELS[4];
|
||||||
static const char PITCH_NAMES[8]; // lowercase rtttl names
|
static const char PITCH_NAMES[8]; // lowercase rtttl names
|
||||||
|
|
||||||
@@ -293,6 +292,5 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
const uint16_t RingtoneEditorScreen::BPM_OPTS[5] = { 60, 90, 120, 150, 180 };
|
const uint16_t RingtoneEditorScreen::BPM_OPTS[5] = { 60, 90, 120, 150, 180 };
|
||||||
const uint8_t RingtoneEditorScreen::DUR_VALS[4] = { 4, 8, 16, 32 };
|
|
||||||
const char* RingtoneEditorScreen::DUR_LABELS[4] = { "1/4", "1/8", "1/16", "1/32" };
|
const char* RingtoneEditorScreen::DUR_LABELS[4] = { "1/4", "1/8", "1/16", "1/32" };
|
||||||
const char RingtoneEditorScreen::PITCH_NAMES[8] = { 'p', 'c', 'd', 'e', 'f', 'g', 'a', 'b' };
|
const char RingtoneEditorScreen::PITCH_NAMES[8] = { 'p', 'c', 'd', 'e', 'f', 'g', 'a', 'b' };
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ class SettingsScreen : public UIScreen {
|
|||||||
bool collapsed = (_collapsed >> si) & 1;
|
bool collapsed = (_collapsed >> si) & 1;
|
||||||
bool sel = (item == _selected);
|
bool sel = (item == _selected);
|
||||||
display.setColor(DisplayDriver::LIGHT);
|
display.setColor(DisplayDriver::LIGHT);
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - _reserve, display.lineStep(), sel);
|
display.drawSelectionRow(0, y - 1, display.width() - _reserve, display.lineStep() - 1, sel);
|
||||||
display.setCursor(2, y);
|
display.setCursor(2, y);
|
||||||
display.print(collapsed ? "+" : "-");
|
display.print(collapsed ? "+" : "-");
|
||||||
display.print(" ");
|
display.print(" ");
|
||||||
@@ -422,7 +422,7 @@ class SettingsScreen : public UIScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool sel = (item == _selected);
|
bool sel = (item == _selected);
|
||||||
display.drawSelectionRow(0, y - 1, display.width() - _reserve, display.lineStep(), sel);
|
display.drawSelectionRow(0, y - 1, display.width() - _reserve, display.lineStep() - 1, sel);
|
||||||
|
|
||||||
display.setCursor(2, y);
|
display.setCursor(2, y);
|
||||||
|
|
||||||
|
|||||||
@@ -482,7 +482,6 @@ class HomeScreen : public UIScreen {
|
|||||||
|
|
||||||
CayenneLPP sensors_lpp;
|
CayenneLPP sensors_lpp;
|
||||||
int sensors_nb = 0;
|
int sensors_nb = 0;
|
||||||
bool sensors_scroll = false;
|
|
||||||
int sensors_scroll_offset = 0;
|
int sensors_scroll_offset = 0;
|
||||||
int next_sensors_refresh = 0;
|
int next_sensors_refresh = 0;
|
||||||
|
|
||||||
@@ -498,7 +497,6 @@ class HomeScreen : public UIScreen {
|
|||||||
reader.skipData(type);
|
reader.skipData(type);
|
||||||
sensors_nb ++;
|
sensors_nb ++;
|
||||||
}
|
}
|
||||||
sensors_scroll = sensors_nb > UI_RECENT_LIST_SIZE;
|
|
||||||
#if AUTO_OFF_MILLIS > 0
|
#if AUTO_OFF_MILLIS > 0
|
||||||
next_sensors_refresh = millis() + 5000; // refresh sensor values every 5 sec
|
next_sensors_refresh = millis() + 5000; // refresh sensor values every 5 sec
|
||||||
#else
|
#else
|
||||||
@@ -992,8 +990,10 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool auto_adv = _node_prefs && _node_prefs->advert_auto_interval_sec > 0;
|
bool auto_adv = _node_prefs && _node_prefs->advert_auto_interval_sec > 0;
|
||||||
// Any blinking status-bar indicator needs a 1 s refresh to animate evenly.
|
// Any blinking status-bar indicator needs a 1 s refresh to animate evenly —
|
||||||
bool need_blink = auto_adv || _task->trail().isActive();
|
// but the status bar (and its icons) is hidden on the CLOCK page, so don't
|
||||||
|
// pay the 1 s cadence there for icons that aren't drawn.
|
||||||
|
bool need_blink = (_page != HomePage::CLOCK) && (auto_adv || _task->trail().isActive());
|
||||||
if (Features::IS_EINK) {
|
if (Features::IS_EINK) {
|
||||||
// slow display: poll every 30 s; inbound msgs force immediate refresh via notify()
|
// slow display: poll every 30 s; inbound msgs force immediate refresh via notify()
|
||||||
return Features::HOME_REFRESH_MS;
|
return Features::HOME_REFRESH_MS;
|
||||||
|
|||||||
@@ -319,7 +319,8 @@ public:
|
|||||||
int n = wpListCount();
|
int n = wpListCount();
|
||||||
int total = n + 1; // + the "Add by coords" row
|
int total = n + 1; // + the "Add by coords" row
|
||||||
if (c == KEY_CANCEL) { _mode = OFF; return true; }
|
if (c == KEY_CANCEL) { _mode = OFF; return true; }
|
||||||
if (c == KEY_UP && _sel > 0) { _sel--; if (_sel < _scroll) _scroll = _sel; return true; }
|
// drawList() reclamps _scroll from _sel every render.
|
||||||
|
if (c == KEY_UP && _sel > 0) { _sel--; return true; }
|
||||||
if (c == KEY_DOWN && _sel < total - 1) { _sel++; return true; }
|
if (c == KEY_DOWN && _sel < total - 1) { _sel++; return true; }
|
||||||
if (c == KEY_ENTER) {
|
if (c == KEY_ENTER) {
|
||||||
if (_sel == n) openAddForm(); // last row → open the add form
|
if (_sel == n) openAddForm(); // last row → open the add form
|
||||||
|
|||||||
@@ -162,16 +162,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up/down scroll indicators in the right-edge column. top_y is the first
|
|
||||||
// row's y, bottom_y the last visible row's y. Replaces the 4-line
|
|
||||||
// setCursor/print("^")/setCursor/print("v") block in every scrollable list.
|
|
||||||
void drawScrollArrows(int top_y, int bottom_y, bool more_up, bool more_down) {
|
|
||||||
int x = width() - getCharWidth();
|
|
||||||
setColor(LIGHT);
|
|
||||||
if (more_up) { setCursor(x, top_y); print("^"); }
|
|
||||||
if (more_down) { setCursor(x, bottom_y); print("v"); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inverted title bar: light background, dark ellipsized label, then the
|
// Inverted title bar: light background, dark ellipsized label, then the
|
||||||
// standard separator line. The label is UTF-8 translated by
|
// standard separator line. The label is UTF-8 translated by
|
||||||
// drawTextEllipsized. Leaves ink colour LIGHT for following content.
|
// drawTextEllipsized. Leaves ink colour LIGHT for following content.
|
||||||
|
|||||||
Reference in New Issue
Block a user