mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
feat(ui): show repeater echo count instead of a checkmark on channel sends
The plain ✓ on your own channel post only said "at least one repeater heard it" -- now it shows how many distinct repeaters echoed it back, drawn as tiny 3x5 digit icons (icons.h) rather than the normal font, since the slot next to the sender name is icon-sized, not text-row- sized. DM delivery ticks are untouched (no repeater-count concept there, so they keep the plain checkmark). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -420,10 +420,17 @@ class MessagesScreen : public UIScreen {
|
||||
// Delivery marker, drawn with the current ink colour and auto-scaled to the
|
||||
// font (see icons.h). Pending = a row of dots, one per send (so it grows with
|
||||
// each auto-resend); delivered = ✓; failed = ✗; ACK_NONE = nothing.
|
||||
static void drawAckGlyph(DisplayDriver& d, int x, int top_y, AckState s, int sends = 1) {
|
||||
// relay_count (channel sends only): when > 0, replaces the ✓ with the
|
||||
// distinct-repeater echo count as tiny digit icons -- the count alone
|
||||
// already says "confirmed", so showing the checkmark too is redundant; a
|
||||
// DM's ✓ (no such count) leaves it 0 and keeps the plain checkmark.
|
||||
static void drawAckGlyph(DisplayDriver& d, int x, int top_y, AckState s, int sends = 1, int relay_count = 0) {
|
||||
switch (s) {
|
||||
case ACK_PENDING: miniIconDotRow(d, x, top_y, sends); break;
|
||||
case ACK_OK: miniIconDraw(d, x, top_y, ICON_CHECK); break;
|
||||
case ACK_OK:
|
||||
if (relay_count > 0) miniIconDrawNumber(d, x, top_y, relay_count);
|
||||
else miniIconDraw(d, x, top_y, ICON_CHECK);
|
||||
break;
|
||||
case ACK_FAIL: miniIconDraw(d, x, top_y, ICON_CROSS); break;
|
||||
default: break; // ACK_NONE → nothing
|
||||
}
|
||||
@@ -447,11 +454,11 @@ class MessagesScreen : public UIScreen {
|
||||
|
||||
// Width of an ack/delivery glyph (see drawAckGlyph) — needed up front to size
|
||||
// an outgoing bubble before it's drawn.
|
||||
static int ackGlyphWidth(DisplayDriver& d, AckState s, int sends) {
|
||||
static int ackGlyphWidth(DisplayDriver& d, AckState s, int sends, int relay_count = 0) {
|
||||
const int sc = miniIconScale(d);
|
||||
switch (s) {
|
||||
case ACK_PENDING: return sends * 3 * sc; // dot+gap pitch (icons.h), slightly generous
|
||||
case ACK_OK: return ICON_CHECK.w * sc;
|
||||
case ACK_OK: return relay_count > 0 ? miniIconNumberWidth(d, relay_count) : ICON_CHECK.w * sc;
|
||||
case ACK_FAIL: return ICON_CROSS.w * sc;
|
||||
default: return 0;
|
||||
}
|
||||
@@ -1334,10 +1341,13 @@ public:
|
||||
int ret = _fs.render(display, fsender, fmsg,
|
||||
_hist_sel < fs_hist_count - 1,
|
||||
_hist_sel > 0);
|
||||
// Channels: ✓ only once a repeater echo confirms relay (see list view).
|
||||
// Channels: ✓ only once a repeater echo confirms relay (see list view),
|
||||
// plus the distinct-echoing-repeater count as tiny digits (path_len's
|
||||
// hop_count -- see markChannelRelayed/showPathDetail's "Relayed by").
|
||||
if (strcmp(fsender, "Me") == 0 && _history.chAtPos(ring_pos).relay_status == ACK_OK) {
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
drawAckGlyph(display, 2 + display.getTextWidth(fsender) + 3, 1, ACK_OK);
|
||||
int relay_count = _history.chAtPos(ring_pos).path_len & 63;
|
||||
drawAckGlyph(display, 2 + display.getTextWidth(fsender) + 3, 1, ACK_OK, 1, relay_count);
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
}
|
||||
if (_ctx_menu.active) _ctx_menu.render(display);
|
||||
@@ -1437,8 +1447,9 @@ public:
|
||||
// was relayed into the mesh; otherwise no marker (absence is normal).
|
||||
bool outgoing = strcmp(sender, "Me") == 0;
|
||||
bool show_ack = outgoing && _history.chAtPos(ring_pos).relay_status == ACK_OK;
|
||||
int relay_count = show_ack ? (_history.chAtPos(ring_pos).path_len & 63) : 0;
|
||||
int full_avail = display.width() - reserve;
|
||||
int ack_w = show_ack ? (3 + ackGlyphWidth(display, ACK_OK, 1)) : 0;
|
||||
int ack_w = show_ack ? (3 + ackGlyphWidth(display, ACK_OK, 1, relay_count)) : 0;
|
||||
int header_w = 3 + display.getTextWidth(sender) + ack_w + age_w + 3;
|
||||
int body_w, nl = 0;
|
||||
if (portrait_expand) {
|
||||
@@ -1458,7 +1469,7 @@ public:
|
||||
display.drawTextEllipsized(box.x + 3, y + 1, box.w - 6 - age_w, sender);
|
||||
if (show_ack) {
|
||||
int gx = box.x + 3 + display.getTextWidth(sender) + 3;
|
||||
drawAckGlyph(display, gx, y + 1, ACK_OK);
|
||||
drawAckGlyph(display, gx, y + 1, ACK_OK, 1, relay_count);
|
||||
}
|
||||
if (age[0]) { display.setCursor(box.x + box.w - age_w, y + 1); display.print(age); }
|
||||
if (!sel) display.setColor(DisplayDriver::LIGHT);
|
||||
|
||||
@@ -125,6 +125,96 @@ MINI_ICON(ICON_CROSS, 4, // ✗
|
||||
packRow(".##."),
|
||||
packRow("#..#"));
|
||||
|
||||
// Tiny 3×5 digits — for a small count that needs to sit in an icon-sized slot
|
||||
// (e.g. next to ICON_CHECK) where the normal font is too tall to fit. See
|
||||
// miniIconDrawNumber/miniIconNumberWidth below.
|
||||
MINI_ICON(ICON_DIGIT_0, 3,
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
packRow("#.#"),
|
||||
packRow("#.#"),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_1, 3,
|
||||
packRow(".#."),
|
||||
packRow("##."),
|
||||
packRow(".#."),
|
||||
packRow(".#."),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_2, 3,
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("###"),
|
||||
packRow("#.."),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_3, 3,
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_4, 3,
|
||||
packRow("#.#"),
|
||||
packRow("#.#"),
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("..#"));
|
||||
MINI_ICON(ICON_DIGIT_5, 3,
|
||||
packRow("###"),
|
||||
packRow("#.."),
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_6, 3,
|
||||
packRow("###"),
|
||||
packRow("#.."),
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_7, 3,
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("..#"),
|
||||
packRow("..#"),
|
||||
packRow("..#"));
|
||||
MINI_ICON(ICON_DIGIT_8, 3,
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
packRow("###"));
|
||||
MINI_ICON(ICON_DIGIT_9, 3,
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
packRow("###"),
|
||||
packRow("..#"),
|
||||
packRow("###"));
|
||||
|
||||
static constexpr const MiniIcon* MINI_ICON_DIGITS[10] = {
|
||||
&ICON_DIGIT_0, &ICON_DIGIT_1, &ICON_DIGIT_2, &ICON_DIGIT_3, &ICON_DIGIT_4,
|
||||
&ICON_DIGIT_5, &ICON_DIGIT_6, &ICON_DIGIT_7, &ICON_DIGIT_8, &ICON_DIGIT_9,
|
||||
};
|
||||
|
||||
// Width a count would occupy via miniIconDrawNumber (digit width + 1px gap
|
||||
// between digits, scaled) — needed up front to size a header around it.
|
||||
// Clamped to 2 digits (0-99): callers showing a repeater/echo count never see
|
||||
// more than MAX_HIST_PATH_BYTES distinct hashes anyway (16 max).
|
||||
inline int miniIconNumberWidth(DisplayDriver& d, int n) {
|
||||
const int s = miniIconScale(d);
|
||||
int digits = (n >= 10) ? 2 : 1;
|
||||
return digits * 3 * s + (digits - 1) * s;
|
||||
}
|
||||
|
||||
// Draws `n` (clamped to 0-99) as a left-to-right run of tiny digit icons —
|
||||
// e.g. a repeater/echo count too small a slot for the normal font to fit
|
||||
// legibly. Vertically centred in the text line the same way miniIconDraw is.
|
||||
inline void miniIconDrawNumber(DisplayDriver& d, int x, int top_y, int n) {
|
||||
const int s = miniIconScale(d);
|
||||
if (n < 0) n = 0;
|
||||
if (n > 99) n = 99;
|
||||
if (n >= 10) { miniIconDraw(d, x, top_y, *MINI_ICON_DIGITS[n / 10]); x += 3 * s + s; }
|
||||
miniIconDraw(d, x, top_y, *MINI_ICON_DIGITS[n % 10]);
|
||||
}
|
||||
|
||||
// Top-bar status glyphs (replace the single-letter M / B / A indicators).
|
||||
MINI_ICON(ICON_MUTE, 6, // speaker + cross (sound off)
|
||||
packRow("..#..."),
|
||||
|
||||
Reference in New Issue
Block a user