fix: align notification unread badge with panel visibility rules (#1520)

Stack success events were hidden from the panel but still counted unread on the bell and dashboard.

Share one visibility helper across badge, panel, and Recent Alerts.

Harden mark-all-read against partial API failures.

Fixes #1513
This commit is contained in:
Anso
2026-06-29 18:19:18 -04:00
committed by GitHub
parent 624b586887
commit 1b9a40f874
6 changed files with 136 additions and 22 deletions
@@ -222,12 +222,37 @@ export function useNotifications({ nodes, onStateInvalidate, onImageUpdatesChang
try {
const localNode = nodesRef.current.find(n => n.type === 'local');
const unreadNodeIds = [...new Set(notifications.filter(n => !n.is_read && n.nodeId != null).map(n => n.nodeId as number))];
await Promise.allSettled(unreadNodeIds.map(nodeId =>
if (unreadNodeIds.length === 0) return;
const results = await Promise.allSettled(unreadNodeIds.map(nodeId =>
nodeId === localNode?.id
? apiFetch('/notifications/read', { method: 'POST', localOnly: true } as Parameters<typeof apiFetch>[1])
: fetchForNode('/notifications/read', nodeId, { method: 'POST' }),
));
setNotifications(prev => prev.map(n => ({ ...n, is_read: 1 })));
const succeededNodeIds = new Set<number>();
let hadFailure = false;
for (let i = 0; i < results.length; i++) {
const result = results[i];
const nodeId = unreadNodeIds[i];
if (result.status === 'fulfilled' && result.value.ok) {
succeededNodeIds.add(nodeId);
} else {
hadFailure = true;
}
}
if (succeededNodeIds.size > 0) {
setNotifications(prev => prev.map(n =>
n.nodeId != null && succeededNodeIds.has(n.nodeId) ? { ...n, is_read: 1 } : n,
));
}
if (hadFailure) {
toast.error('Some notifications could not be marked as read');
}
void fetchNotificationsRef.current();
} catch (e: unknown) {
const err = e as { message?: string; error?: string };
toast.error(err?.message || err?.error || 'Failed to mark notifications as read');