fix: v0.9.4 inbox badge clears when seen
Opening the bell marks its events seen; viewing a session (or returning to the tab) reads that session's events. The badge now drops to what is live instead of climbing with every background "finished". Closes #42 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WHRLCCdXYm41Qx5kNhehaP
This commit is contained in:
Vendored
+9
@@ -1,3 +1,12 @@
|
|||||||
|
devdesk (0.9.4) bookworm; urgency=medium
|
||||||
|
|
||||||
|
* The inbox badge no longer only grows (#42). Opening the bell marks its
|
||||||
|
events seen, leaving just what is live (sessions waiting on you,
|
||||||
|
firing alerts). Viewing a session reads the events it reported while
|
||||||
|
you were away.
|
||||||
|
|
||||||
|
-- Jared Vititoe <jjvititoe1@gmail.com> Sun, 11 Oct 2026 22:46:00 -0400
|
||||||
|
|
||||||
devdesk (0.9.3) bookworm; urgency=medium
|
devdesk (0.9.3) bookworm; urgency=medium
|
||||||
|
|
||||||
* Claude's footer shows 5-hour plan use instead of a dollar figure on a
|
* Claude's footer shows 5-hour plan use instead of a dollar figure on a
|
||||||
|
|||||||
+26
-2
@@ -69,7 +69,27 @@ export class Inbox {
|
|||||||
this.button.setAttribute('aria-expanded', String(open));
|
this.button.setAttribute('aria-expanded', String(open));
|
||||||
if (!open) this.peeking = null;
|
if (!open) this.peeking = null;
|
||||||
this.panel.classList.toggle('is-peek', false);
|
this.panel.classList.toggle('is-peek', false);
|
||||||
if (open) this.render();
|
if (open) {
|
||||||
|
this.render();
|
||||||
|
this.markSeen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opening the bell counts as seeing what's in it (devdesk#42): the badge clears
|
||||||
|
// but the entries keep their highlight until the panel is redrawn.
|
||||||
|
markSeen() {
|
||||||
|
if (!this.events.some((e) => !e.read)) return;
|
||||||
|
this.events = this.events.map((e) => ({ ...e, read: true }));
|
||||||
|
save(this.events);
|
||||||
|
this.renderBadge();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looking at a session reads what it reported (finished, waiting) while you were away.
|
||||||
|
markSessionRead(session) {
|
||||||
|
if (!session || !this.events.some((e) => !e.read && e.session === session && !e.url)) return;
|
||||||
|
this.events = this.events.map((e) => (e.session === session && !e.url ? { ...e, read: true } : e));
|
||||||
|
save(this.events);
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Something happened. The same kind for the same session within a minute is
|
// Something happened. The same kind for the same session within a minute is
|
||||||
@@ -102,6 +122,11 @@ export class Inbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
this.renderBadge();
|
||||||
|
if (this.isOpen) this.renderPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderBadge() {
|
||||||
const count = this.waiting.length + this.alerts.length + this.unread();
|
const count = this.waiting.length + this.alerts.length + this.unread();
|
||||||
const urgent = this.waiting.length > 0 || this.alerts.some((a) => a.severity === 'critical');
|
const urgent = this.waiting.length > 0 || this.alerts.some((a) => a.severity === 'critical');
|
||||||
this.badge.textContent = count ? String(count) : '';
|
this.badge.textContent = count ? String(count) : '';
|
||||||
@@ -114,7 +139,6 @@ export class Inbox {
|
|||||||
this.unread() && `${this.unread()} new event(s)`,
|
this.unread() && `${this.unread()} new event(s)`,
|
||||||
].filter(Boolean).join(' · ')
|
].filter(Boolean).join(' · ')
|
||||||
: 'Inbox: nothing new';
|
: 'Inbox: nothing new';
|
||||||
if (this.isOpen) this.renderPanel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------ answer from here
|
// ------------------------------------------------------------ answer from here
|
||||||
|
|||||||
+5
-1
@@ -181,6 +181,7 @@ function renderPanelsBadge() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onSessionData({ fetched = false } = {}) {
|
function onSessionData({ fetched = false } = {}) {
|
||||||
|
if (document.visibilityState === 'visible') inbox?.markSessionRead(state.session);
|
||||||
renderUsage();
|
renderUsage();
|
||||||
renderSessionChip();
|
renderSessionChip();
|
||||||
renderAttention(fetched);
|
renderAttention(fetched);
|
||||||
@@ -1074,7 +1075,10 @@ function wireChrome() {
|
|||||||
|
|
||||||
window.addEventListener('online', retrySoon);
|
window.addEventListener('online', retrySoon);
|
||||||
document.addEventListener('visibilitychange', () => {
|
document.addEventListener('visibilitychange', () => {
|
||||||
if (!document.hidden) retrySoon();
|
if (!document.hidden) {
|
||||||
|
retrySoon();
|
||||||
|
inbox.markSessionRead(state.session);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// Session states feed the header chip and the notifications for other sessions,
|
// Session states feed the header chip and the notifications for other sessions,
|
||||||
// so poll even in a background tab (browsers throttle that to about once a
|
// so poll even in a background tab (browsers throttle that to about once a
|
||||||
|
|||||||
Reference in New Issue
Block a user