mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-05-31 19:18:26 +01:00
fix: better api calls
Some checks failed
🕒 Handle Stale Issues / 🗑️ Cleanup Stale Issues (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
Some checks failed
🕒 Handle Stale Issues / 🗑️ Cleanup Stale Issues (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
This commit is contained in:
67
hooks/useInView.ts
Normal file
67
hooks/useInView.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { type LayoutRectangle, useWindowDimensions } from "react-native";
|
||||
|
||||
interface UseInViewOptions {
|
||||
threshold?: number; // Distance in pixels before component is considered "in view"
|
||||
enabled?: boolean; // Allow disabling the hook
|
||||
}
|
||||
|
||||
interface UseInViewReturn {
|
||||
ref: (node: any) => void;
|
||||
isInView: boolean;
|
||||
onLayout: () => void;
|
||||
}
|
||||
|
||||
export const useInView = (
|
||||
scrollY: number = 0,
|
||||
options: UseInViewOptions = {},
|
||||
): UseInViewReturn => {
|
||||
const { threshold = 400, enabled = true } = options;
|
||||
const { height: windowHeight } = useWindowDimensions();
|
||||
const [layout, setLayout] = useState<LayoutRectangle | null>(null);
|
||||
const [hasBeenInView, setHasBeenInView] = useState(false);
|
||||
const nodeRef = useRef<any>(null);
|
||||
|
||||
const ref = useCallback((node: any) => {
|
||||
nodeRef.current = node;
|
||||
}, []);
|
||||
|
||||
const onLayout = useCallback(() => {
|
||||
if (!nodeRef.current) return;
|
||||
|
||||
// Use measure to get absolute position
|
||||
nodeRef.current.measure(
|
||||
(
|
||||
_x: number,
|
||||
_y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
pageX: number,
|
||||
pageY: number,
|
||||
) => {
|
||||
setLayout({ x: pageX, y: pageY, width, height });
|
||||
},
|
||||
);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled || hasBeenInView || !layout) return;
|
||||
|
||||
// Calculate if the section is in view or about to be
|
||||
const sectionTop = layout.y;
|
||||
const viewportBottom = scrollY + windowHeight;
|
||||
|
||||
// Check if section is within threshold distance of viewport
|
||||
const isNearView = viewportBottom + threshold >= sectionTop;
|
||||
|
||||
if (isNearView) {
|
||||
setHasBeenInView(true);
|
||||
}
|
||||
}, [scrollY, windowHeight, threshold, layout, hasBeenInView, enabled]);
|
||||
|
||||
return {
|
||||
ref,
|
||||
isInView: hasBeenInView,
|
||||
onLayout,
|
||||
};
|
||||
};
|
||||
@@ -1,58 +1,2 @@
|
||||
import NetInfo from "@react-native-community/netinfo";
|
||||
import { useAtom } from "jotai";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
|
||||
async function checkApiReachable(basePath?: string): Promise<boolean> {
|
||||
if (!basePath) return false;
|
||||
try {
|
||||
const response = await fetch(basePath, { method: "HEAD" });
|
||||
return response.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function useNetworkStatus() {
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
const [serverConnected, setServerConnected] = useState<boolean | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [api] = useAtom(apiAtom);
|
||||
|
||||
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: wait for NetInfo first
|
||||
NetInfo.fetch().then((state) => {
|
||||
if (state.isConnected) {
|
||||
validateConnection();
|
||||
} else {
|
||||
setServerConnected(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => unsubscribe();
|
||||
}, [validateConnection]);
|
||||
|
||||
return { isConnected, serverConnected, loading, retryCheck };
|
||||
}
|
||||
// Re-export from provider to maintain backward compatibility
|
||||
export { useNetworkStatus } from "@/providers/NetworkStatusProvider";
|
||||
|
||||
Reference in New Issue
Block a user