Skip to content

Commit 4802e81

Browse files
committed
fix(webapp): the unread dot skips the chat that's on screen
The toast still shows for every wake; the dot only counts wakes the user isn't already looking at.
1 parent 8e71546 commit 4802e81

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

apps/webapp/app/components/dashboard-agent/DashboardAgent.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ export function DashboardAgent({
6464
// wake the user has already been shown (and maybe dismissed) must not come
6565
// back every 60s while the chat stays unread.
6666
const toastedWakes = useRef(new Set<string>());
67+
// The chat currently on screen (panel open). A wake there streams into the
68+
// visible transcript, so it toasts but must not light the dot.
69+
const visibleChat = useRef<string | null>(null);
6770
// The side panel is the default; someone who last worked fullscreen gets
6871
// fullscreen back. Read lazily so SSR always renders the side panel.
6972
const [fullscreen, setFullscreen] = useState(readAgentFullscreen);
@@ -116,6 +119,8 @@ export function DashboardAgent({
116119
// Closing drops both pending requests: the panel unmounts, so a stale one
117120
// would re-apply on the next open instead of restoring the last chat.
118121
if (!next) {
122+
// No chat is on screen any more — the dot counts every unread wake again.
123+
visibleChat.current = null;
119124
setRequestedMessage(undefined);
120125
setOpenChatRequest(undefined);
121126
// An abandoned card leaves no trace (§2.2) — including no pending request
@@ -158,7 +163,10 @@ export function DashboardAgent({
158163
if (!res.ok) return;
159164
const data = (await res.json()) as { unreadWakes?: number; wakes?: WatchWake[] };
160165
if (cancelled) return;
161-
setUnreadWakes(data.unreadWakes ?? 0);
166+
const wakesInView = (data.wakes ?? []).filter(
167+
(wake) => wake.chatId === visibleChat.current
168+
).length;
169+
setUnreadWakes(Math.max(0, (data.unreadWakes ?? 0) - wakesInView));
162170

163171
const fresh = (data.wakes ?? []).filter((wake) => !toastedWakes.current.has(wake.watchId));
164172
for (const wake of fresh) toastedWakes.current.add(wake.watchId);
@@ -191,6 +199,7 @@ export function DashboardAgent({
191199
// persists the read marker for the chat that's actually visible.
192200
const markChatRead = useCallback(
193201
async (chatId: string) => {
202+
visibleChat.current = chatId;
194203
setUnreadWakes(0);
195204
const body = new FormData();
196205
body.set("intent", "read");

0 commit comments

Comments
 (0)