import NetInfo from "@react-native-community/netinfo"; import { useQueryClient } from "@tanstack/react-query"; import { useAtom } from "jotai"; import { createContext, type ReactNode, useCallback, useContext, useEffect, useRef, useState, } from "react"; import { apiAtom } from "@/providers/JellyfinProvider"; interface NetworkStatusContextType { isConnected: boolean; serverConnected: boolean | null; loading: boolean; retryCheck: () => Promise; } const NetworkStatusContext = createContext( null, ); async function checkApiReachable(basePath?: string): Promise { if (!basePath) return false; try { const url = basePath.endsWith("/") ? basePath : `${basePath}/`; const response = await fetch(url, { method: "HEAD" }); return response.ok; } catch { return false; } } export function NetworkStatusProvider({ children }: { children: ReactNode }) { const [isConnected, setIsConnected] = useState(false); const [serverConnected, setServerConnected] = useState(null); const [loading, setLoading] = useState(false); const [api] = useAtom(apiAtom); const queryClient = useQueryClient(); const wasServerConnected = useRef(null); const validateConnection = useCallback(async () => { if (!api?.basePath) return false; const reachable = await checkApiReachable(api.basePath); setServerConnected(reachable); return reachable; }, [api?.basePath]); const retryCheck = useCallback(async () => { setLoading(true); await validateConnection(); setLoading(false); }, [validateConnection]); useEffect(() => { const unsubscribe = NetInfo.addEventListener(async (state) => { setIsConnected(!!state.isConnected); if (state.isConnected) { await validateConnection(); } else { setServerConnected(false); } }); // Initial check NetInfo.fetch().then((state) => { if (state.isConnected) { validateConnection(); } else { setServerConnected(false); } }); return () => unsubscribe(); }, [validateConnection]); // Refetch active queries when server becomes reachable useEffect(() => { if (serverConnected && wasServerConnected.current === false) { queryClient.refetchQueries({ type: "active" }); } wasServerConnected.current = serverConnected; }, [serverConnected, queryClient]); return ( {children} ); } export function useNetworkStatus(): NetworkStatusContextType { const context = useContext(NetworkStatusContext); if (!context) { throw new Error( "useNetworkStatus must be used within NetworkStatusProvider", ); } return context; }