diff --git a/CHANGELOG.md b/CHANGELOG.md index 104822a33..e7ab33051 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel - Show toast notification when API token is copied to clipboard. - Dataset versions: (1) file changes should be `Access: Restricted` instead of `isResticted: true/false`; (2) logic of View Detail button. (#879) - File versions: (1) logic of linking to a file version; (2)If file not included, show text information "File not included in this version.". (#879) +- Notifications unread count now refreshes immediately (without waiting for polling) after notifications are read and after dataset/collection create or dataset publish actions that generate notifications. ### Removed diff --git a/src/notifications/domain/hooks/useNeedsUpdate.ts b/src/notifications/domain/hooks/useNeedsUpdate.ts index c8f6c03e7..fa0d2451b 100644 --- a/src/notifications/domain/hooks/useNeedsUpdate.ts +++ b/src/notifications/domain/hooks/useNeedsUpdate.ts @@ -1,30 +1,5 @@ -// hooks/useNeedsUpdate.ts import { useSyncExternalStore } from 'react' -type Listener = () => void - -class NeedsUpdateStore { - private needsUpdate = false - private listeners = new Set() - - getSnapshot = () => this.needsUpdate - - subscribe = (callback: Listener) => { - this.listeners.add(callback) - return () => this.listeners.delete(callback) - } - - setNeedsUpdate(value: boolean) { - if (this.needsUpdate !== value) { - this.needsUpdate = value - this.emit() - } - } - - private emit() { - this.listeners.forEach((listener) => listener()) - } -} -const needsUpdateStore = new NeedsUpdateStore() +import { needsUpdateStore } from './needsUpdateStore' export function useNeedsUpdate() { return useSyncExternalStore(needsUpdateStore.subscribe, needsUpdateStore.getSnapshot) diff --git a/src/notifications/domain/hooks/useNotifications.ts b/src/notifications/domain/hooks/useNotifications.ts index cb9a1d1d9..7afa097d3 100644 --- a/src/notifications/domain/hooks/useNotifications.ts +++ b/src/notifications/domain/hooks/useNotifications.ts @@ -4,6 +4,7 @@ import { Notification } from '@/notifications/domain/models/Notification' import { NotificationRepository } from '@/notifications/domain/repositories/NotificationRepository' import { NotificationsPaginationInfo } from '@/notifications/domain/models/NotificationsPaginationInfo' import { getAllNotificationsByUser } from '@/notifications/domain/useCases/getAllNotificationsByUser' +import { needsUpdateStore } from './needsUpdateStore' const POLLING_NOTIFICATIONS_INTERVAL_TIME = 30_000 @@ -67,6 +68,7 @@ export function useNotifications( try { await Promise.all(ids.map((id) => repository.markNotificationAsRead(id))) setError(null) + needsUpdateStore.setNeedsUpdate(true) } catch (err) { const message = err instanceof Error ? err.message : 'Failed to mark as read' setError(message) @@ -78,6 +80,7 @@ export function useNotifications( try { await Promise.all(ids.map((id) => repository.deleteNotification(id))) setError(null) + needsUpdateStore.setNeedsUpdate(true) } catch (err) { const message = err instanceof Error ? err.message : 'Failed to delete notifications' setError(message) diff --git a/src/sections/account/notifications-section/NotificationsSection.tsx b/src/sections/account/notifications-section/NotificationsSection.tsx index c64429db7..7b43fc01d 100644 --- a/src/sections/account/notifications-section/NotificationsSection.tsx +++ b/src/sections/account/notifications-section/NotificationsSection.tsx @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { Alert, Button, CloseButton, Stack } from '@iqss/dataverse-design-system' import { getTranslatedNotification } from '@/sections/account/notifications-section/NotificationsHelper' -import { needsUpdateStore } from '@/notifications/domain/hooks/needsUpdateStore' import { useNotifications } from '@/notifications/domain/hooks/useNotifications' import { NotificationRepository } from '@/notifications/domain/repositories/NotificationRepository' import { NotificationsPaginationInfo } from '@/notifications/domain/models/NotificationsPaginationInfo' @@ -39,7 +38,6 @@ export const NotificationsSection = ({ notificationRepository }: NotificationsSe await markAsRead(unreadIds) setReadIds((prev) => [...prev, ...unreadIds]) await refetch() - needsUpdateStore.setNeedsUpdate(true) })() }, 2000) return () => clearTimeout(timer) @@ -86,7 +84,9 @@ export const NotificationsSection = ({ notificationRepository }: NotificationsSe direction="horizontal" gap={2} style={{ width: '100%', justifyContent: 'space-between', alignItems: 'center' }}> -
{t('notifications.displayingNotifications', { start, end, total })}
+ {notifications.length > 0 && ( +
{t('notifications.displayingNotifications', { start, end, total })}
+ )} {notifications.length > 0 && (