fix(ui/channels): unread badge no longer outlives evicted history

The channel history is a single ring shared by all channels (was 32
entries), while unread counts live in a separate per-channel array.
Once 32 messages had accumulated across channels, the oldest entry was
evicted on each new message — but the matching _ch_unread[] counter was
left untouched. The Messages badge then claimed unread messages the ring
could no longer surface, so a channel showed "N unread" but opened empty.
(The companion app stores its own copy over the protocol, which is why
the phone could still read them.)

Two changes:
- addChannelMsg() now decrements _ch_unread[evicted.ch_idx] when an entry
  is pushed out of the ring, keeping the badge consistent with what is
  actually displayable.
- CH_HIST_MAX raised 32 → 96 (~14 KB RAM) so eviction is far less frequent
  under normal multi-channel traffic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-31 16:23:07 +02:00
parent d4926da792
commit 43d989821a

View File

@@ -36,7 +36,11 @@ class QuickMsgScreen : public UIScreen {
FullscreenMsgView _fs;
int _unread_at_entry; // _ch_unread value when entering CHANNEL_HIST
int _viewing_max_seen; // highest _hist_sel reached in current session
static const int CH_HIST_MAX = 32;
// Shared ring for all channels combined. Sized to comfortably exceed
// typical inter-visit accumulation; addChannelMsg() decrements the
// matching _ch_unread when an entry is evicted so the badge can't claim
// unread messages that no longer exist in the ring.
static const int CH_HIST_MAX = 96;
// KEYBOARD
KeyboardWidget _kb;
@@ -422,6 +426,12 @@ public:
_hist_count++;
} else {
pos = _hist_head;
// Evicting the oldest entry — drop its share of the unread counter so
// the badge can't claim a message the ring no longer holds.
uint8_t evicted = _hist[pos].ch_idx;
if (evicted < MAX_GROUP_CHANNELS && _ch_unread[evicted] > 0) {
_ch_unread[evicted]--;
}
_hist_head = (_hist_head + 1) % CH_HIST_MAX;
}
_hist[pos].ch_idx = ch_idx;