improvement: notification feature polished. feature tabs following the same notification socket emmited data to be updated.
This commit is contained in:
@@ -12,6 +12,9 @@ import {
|
||||
} from 'react';
|
||||
import { io, type Socket } from 'socket.io-client';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { accessTokenRefreshedEventName } from '@/lib/auth/accessTokenEvents';
|
||||
import { notifyTabBadgesChanged } from '@/lib/tabBadgeUtils';
|
||||
import { notifyPendingConnectionsChanged } from '@/lib/hooks/usePendingConnectionsCount';
|
||||
import type { UserNotificationItem } from '@/types/notifications';
|
||||
|
||||
type RealtimeContextValue = {
|
||||
@@ -37,13 +40,33 @@ function apiOrigin(): string {
|
||||
}
|
||||
}
|
||||
|
||||
function invalidateSidebarBadges(notification?: UserNotificationItem | null) {
|
||||
// Sidebar Cases/Tasks/Treatment badges + open tab soft-refetch (via window event).
|
||||
notifyTabBadgesChanged();
|
||||
// Orgs pending badge/list — only for connection-related inbox events.
|
||||
if (
|
||||
notification?.type === 'CONNECTION_REQUEST' ||
|
||||
notification?.href?.startsWith('/organizations')
|
||||
) {
|
||||
notifyPendingConnectionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
export function RealtimeProvider({ children }: { children: ReactNode }) {
|
||||
const { user, currentOrganization, isAuthReady } = useAuth();
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [lastNotification, setLastNotification] = useState<UserNotificationItem | null>(null);
|
||||
const [unreadCount, setUnreadCount] = useState<number | null>(null);
|
||||
/** Bumped after access-token refresh so the socket reconnects with the new cookie. */
|
||||
const [socketEpoch, setSocketEpoch] = useState(0);
|
||||
const socketRef = useRef<Socket | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const onRefreshed = () => setSocketEpoch((n) => n + 1);
|
||||
window.addEventListener(accessTokenRefreshedEventName(), onRefreshed);
|
||||
return () => window.removeEventListener(accessTokenRefreshedEventName(), onRefreshed);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthReady || !user || !currentOrganization?.id) {
|
||||
socketRef.current?.disconnect();
|
||||
@@ -63,6 +86,9 @@ export function RealtimeProvider({ children }: { children: ReactNode }) {
|
||||
socket.on('notification.created', (payload: { notification?: UserNotificationItem }) => {
|
||||
if (payload?.notification) {
|
||||
setLastNotification(payload.notification);
|
||||
invalidateSidebarBadges(payload.notification);
|
||||
} else {
|
||||
invalidateSidebarBadges(null);
|
||||
}
|
||||
});
|
||||
socket.on('notification.unreadCount', (payload: { count?: number }) => {
|
||||
@@ -76,7 +102,7 @@ export function RealtimeProvider({ children }: { children: ReactNode }) {
|
||||
socketRef.current = null;
|
||||
setConnected(false);
|
||||
};
|
||||
}, [isAuthReady, user, currentOrganization?.id]);
|
||||
}, [isAuthReady, user, currentOrganization?.id, socketEpoch]);
|
||||
|
||||
const setUnreadCountStable = useCallback((count: number) => {
|
||||
setUnreadCount(count);
|
||||
|
||||
Reference in New Issue
Block a user