mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-12 17:00:23 +01:00
- swap direct i18next t imports for the useTranslation hook so the four touched components re-render on language change - localize the buffer seconds unit via a buffer_seconds key instead of a literal trailing s - reword the useAppRouter guard comment to match its real scope
103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
// Imported from expo-router's bundled copy, NOT "@react-navigation/*": as of
|
|
// SDK 56 expo-router's Metro check rejects direct @react-navigation imports.
|
|
import { useRouter } from "expo-router";
|
|
import { NavigationContext } from "expo-router/react-navigation";
|
|
import { useCallback, useContext, useMemo } from "react";
|
|
import { useOfflineMode } from "@/providers/OfflineModeProvider";
|
|
|
|
/**
|
|
* Drop-in replacement for expo-router's useRouter that automatically
|
|
* preserves offline state across navigation and guards against duplicate
|
|
* screens from rapid taps.
|
|
*
|
|
* - For object-form navigation, automatically adds offline=true when in offline context
|
|
* - For string URLs, passes through unchanged (caller handles offline param)
|
|
* - push() is a no-op while the source screen is not focused, so taps fired
|
|
* before the pushed screen has rendered (slow devices) can't stack duplicates
|
|
*
|
|
* @example
|
|
* import useRouter from "@/hooks/useAppRouter";
|
|
*
|
|
* const router = useRouter();
|
|
* router.push({ pathname: "/items/page", params: { id: item.Id } }); // offline added automatically
|
|
*/
|
|
export function useAppRouter() {
|
|
const router = useRouter();
|
|
const isOffline = useOfflineMode();
|
|
|
|
// Optional: undefined when used outside a navigator (root layout, providers).
|
|
// When present it reflects the focus state of the screen this hook lives in.
|
|
const navigation = useContext(NavigationContext);
|
|
|
|
const push = useCallback(
|
|
(href: Parameters<typeof router.push>[0]) => {
|
|
// Rapid-push guard: a push blurs the source screen synchronously in the
|
|
// navigation state (only the native render is slow). Any further push from
|
|
// this screen — duplicate or not — is dropped until focus returns, so taps
|
|
// fired before the pushed screen renders can't stack screens.
|
|
// No navigation context => nothing to guard (deep-link pushes from root).
|
|
if (navigation?.isFocused?.() === false) return;
|
|
if (typeof href === "string") {
|
|
router.push(href as any);
|
|
} else {
|
|
const callerParams = (href.params ?? {}) as Record<string, unknown>;
|
|
const hasExplicitOffline = "offline" in callerParams;
|
|
router.push({
|
|
...href,
|
|
params: {
|
|
// Only add offline if caller hasn't explicitly set it
|
|
...(isOffline && !hasExplicitOffline && { offline: "true" }),
|
|
...callerParams,
|
|
},
|
|
} as any);
|
|
}
|
|
},
|
|
[router, isOffline, navigation],
|
|
);
|
|
|
|
const replace = useCallback(
|
|
(href: Parameters<typeof router.replace>[0]) => {
|
|
if (typeof href === "string") {
|
|
router.replace(href as any);
|
|
} else {
|
|
const callerParams = (href.params ?? {}) as Record<string, unknown>;
|
|
const hasExplicitOffline = "offline" in callerParams;
|
|
router.replace({
|
|
...href,
|
|
params: {
|
|
// Only add offline if caller hasn't explicitly set it
|
|
...(isOffline && !hasExplicitOffline && { offline: "true" }),
|
|
...callerParams,
|
|
},
|
|
} as any);
|
|
}
|
|
},
|
|
[router, isOffline],
|
|
);
|
|
|
|
const setParams = useCallback(
|
|
(params: Parameters<typeof router.setParams>[0]) => {
|
|
const callerParams = (params ?? {}) as Record<string, unknown>;
|
|
const hasExplicitOffline = "offline" in callerParams;
|
|
router.setParams({
|
|
// Only add offline if caller hasn't explicitly set it
|
|
...(isOffline && !hasExplicitOffline && { offline: "true" }),
|
|
...callerParams,
|
|
});
|
|
},
|
|
[router, isOffline],
|
|
);
|
|
|
|
return useMemo(
|
|
() => ({
|
|
...router,
|
|
push,
|
|
replace,
|
|
setParams,
|
|
}),
|
|
[router, push, replace, setParams],
|
|
);
|
|
}
|
|
|
|
export default useAppRouter;
|