Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 3x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 6x 8x 6x 6x 8x 6x 6x 5x 5x 4x 4x 2x 2x 2x 4x 4x 4x 8x 6x 4x 4x 4x 4x 4x 3x 6x 8x 8x 2x 2x 8x 6x 1x 1x 1x 1x 6x 6x 6x | import { useCallback, useEffect, useRef } from 'react';
import { useIsFocused } from '@react-navigation/native';
import { extractNotificationData } from '@/services/notification/helpers';
import { notificationService } from '@/services/notification/notificationService';
/**
* Handles data refresh triggered by notifications (foreground, tap, or app resume).
*/
export interface UseRefreshNotificationsParams {
onRefresh: () => void;
filterTicketId?: string;
isRefetching?: boolean;
refreshTimeStamp?: number;
notificationId?: string;
}
export const useRefreshNotifications = ({
onRefresh,
filterTicketId,
isRefetching,
refreshTimeStamp,
notificationId,
}: UseRefreshNotificationsParams) => {
const onRefreshRef = useRef(onRefresh);
const isRefetchingRef = useRef(isRefetching);
const lastRefreshTimeRef = useRef(0);
const lastProcessedIdRef = useRef<string | undefined>(undefined);
const lastProcessedStampRef = useRef<number | undefined>(undefined);
const lastProcessedVersionRef = useRef(notificationService.getRefreshVersion());
const hasMountedRef = useRef(false);
const isFocused = useIsFocused();
const isFocusedRef = useRef(isFocused);
useEffect(() => {
isFocusedRef.current = isFocused;
}, [isFocused]);
useEffect(() => {
onRefreshRef.current = onRefresh;
isRefetchingRef.current = isRefetching;
}, [onRefresh, isRefetching]);
const triggerRefresh = useCallback((id?: string, isDirectArrival = false) => {
const now = Date.now();
// 1. DEDUPLICATION
if (!isDirectArrival && id && notificationService.isNotificationProcessed(id)) return;
Iif (id && id === lastProcessedIdRef.current) return;
// 2. DEBOUNCE (500ms safety window)
if (now - lastRefreshTimeRef.current < 500) return;
// 3. REFETCHING GUARD
Iif (isRefetchingRef.current) return;
if (id) {
notificationService.markNotificationAsProcessed(id);
lastProcessedIdRef.current = id;
} else {
notificationService.markAllDisplayedAsProcessed();
}
// Update local version to current global state
lastProcessedVersionRef.current = notificationService.getRefreshVersion();
lastRefreshTimeRef.current = now;
onRefreshRef.current();
}, []);
// Case 1: Foreground notification arrivals
useEffect(() => {
const unsubscribe = notificationService.addMessageListener(data => {
const notificationData = extractNotificationData(data);
const msgId = (data as any)?._messageId;
const notificationTicketId = notificationData?.ticketId;
const isMatchingTicket = !filterTicketId || notificationTicketId === filterTicketId;
if (isMatchingTicket) {
triggerRefresh(msgId, true);
}
});
return () => unsubscribe();
}, [filterTicketId, triggerRefresh]);
// Case 2: Navigation-driven refreshes (via tap/params)
useEffect(() => {
if (refreshTimeStamp && refreshTimeStamp !== lastProcessedStampRef.current) {
lastProcessedStampRef.current = refreshTimeStamp;
triggerRefresh(notificationId);
}
}, [refreshTimeStamp, notificationId, triggerRefresh]);
// Case 3: Reactive Version Monitor
// Subscribes to global version changes to catch background-sync arrivals and foreground updates.
useEffect(() => {
const unsubscribe = notificationService.addVersionListener(currentGlobalVersion => {
const isNew = currentGlobalVersion > lastProcessedVersionRef.current;
Eif (isNew && isFocusedRef.current && hasMountedRef.current) {
triggerRefresh();
}
lastProcessedVersionRef.current = currentGlobalVersion;
});
// Ensure local state is in sync on mount
lastProcessedVersionRef.current = notificationService.getRefreshVersion();
hasMountedRef.current = true;
return () => unsubscribe();
}, [triggerRefresh]);
};
|