import React, { createContext, useContext, useEffect, useRef } from 'react' import { useLocation } from '@tanstack/react-router' import { EventBus, REFRESH_EVENT } from './event-bus' import { getQueryClient } from './query-client' // Web port of packages/ui refresh-context + useManualRefresh + // useMarkDataFetchers + useFocusCallback. Navigation focus (expo) is // approximated with route-pathname changes; manual refresh uses the bus. const RefreshContext = createContext<{ refreshAll: () => void } | null>(null) export const RefreshProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const refreshAll = () => { getQueryClient().invalidateQueries() EventBus.emit(REFRESH_EVENT) } return {children} } export const useRefresh = () => { const context = useContext(RefreshContext) if (!context) throw new Error('useRefresh must be used within RefreshProvider') return context } export function useManualRefresh(callback: () => void) { const ref = useRef(callback) ref.current = callback useEffect(() => { const sub = EventBus.addListener(REFRESH_EVENT, () => ref.current()) return () => sub.remove() }, []) } // Refetch on 2nd+ visit to the current route (mirrors useMarkDataFetchers: // skip first focus, refetch on subsequent focuses). export function useMarkDataFetchers(callback: () => void) { const location = useLocation() const ref = useRef(callback) ref.current = callback const visitsRef = useRef>({}) useEffect(() => { const key = location.pathname + location.searchStr const count = visitsRef.current[key] ?? 0 visitsRef.current[key] = count + 1 if (count >= 1) { ref.current() } // eslint-disable-next-line react-hooks/exhaustive-deps }, [location.pathname, location.searchStr]) } // Run callback when the window regains focus (web analogue of screen focus). export default function useFocusCallback(callback: () => void) { const ref = useRef(callback) ref.current = callback useEffect(() => { const onFocus = () => ref.current() window.addEventListener('focus', onFocus) return () => window.removeEventListener('focus', onFocus) }, []) }