mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 15:48:05 +00:00
106 lines
2.8 KiB
TypeScript
106 lines
2.8 KiB
TypeScript
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<void>;
|
|
}
|
|
|
|
const NetworkStatusContext = createContext<NetworkStatusContextType | null>(
|
|
null,
|
|
);
|
|
|
|
async function checkApiReachable(basePath?: string): Promise<boolean> {
|
|
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<boolean | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const [api] = useAtom(apiAtom);
|
|
const queryClient = useQueryClient();
|
|
const wasServerConnected = useRef<boolean | null>(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 (
|
|
<NetworkStatusContext.Provider
|
|
value={{ isConnected, serverConnected, loading, retryCheck }}
|
|
>
|
|
{children}
|
|
</NetworkStatusContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useNetworkStatus(): NetworkStatusContextType {
|
|
const context = useContext(NetworkStatusContext);
|
|
if (!context) {
|
|
throw new Error(
|
|
"useNetworkStatus must be used within NetworkStatusProvider",
|
|
);
|
|
}
|
|
return context;
|
|
}
|