forked from Ninjalama/streamyfin_mirror
fix: remove splashscreen provider and handle loading in jellyfinprovider
This commit is contained in:
@@ -10,10 +10,6 @@ import {
|
|||||||
} from "@/providers/JellyfinProvider";
|
} from "@/providers/JellyfinProvider";
|
||||||
import { JobQueueProvider } from "@/providers/JobQueueProvider";
|
import { JobQueueProvider } from "@/providers/JobQueueProvider";
|
||||||
import { PlaySettingsProvider } from "@/providers/PlaySettingsProvider";
|
import { PlaySettingsProvider } from "@/providers/PlaySettingsProvider";
|
||||||
import {
|
|
||||||
SplashScreenProvider,
|
|
||||||
useSplashScreenLoading,
|
|
||||||
} from "@/providers/SplashScreenProvider";
|
|
||||||
import { WebSocketProvider } from "@/providers/WebSocketProvider";
|
import { WebSocketProvider } from "@/providers/WebSocketProvider";
|
||||||
import { Settings, useSettings } from "@/utils/atoms/settings";
|
import { Settings, useSettings } from "@/utils/atoms/settings";
|
||||||
import { BACKGROUND_FETCH_TASK } from "@/utils/background-tasks";
|
import { BACKGROUND_FETCH_TASK } from "@/utils/background-tasks";
|
||||||
@@ -36,6 +32,7 @@ import { useFonts } from "expo-font";
|
|||||||
import { useKeepAwake } from "expo-keep-awake";
|
import { useKeepAwake } from "expo-keep-awake";
|
||||||
const Notifications = !Platform.isTV ? require("expo-notifications") : null;
|
const Notifications = !Platform.isTV ? require("expo-notifications") : null;
|
||||||
import { router, Stack } from "expo-router";
|
import { router, Stack } from "expo-router";
|
||||||
|
import * as SplashScreen from "expo-splash-screen";
|
||||||
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
|
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
|
||||||
const TaskManager = !Platform.isTV ? require("expo-task-manager") : null;
|
const TaskManager = !Platform.isTV ? require("expo-task-manager") : null;
|
||||||
import { getLocales } from "expo-localization";
|
import { getLocales } from "expo-localization";
|
||||||
@@ -58,6 +55,15 @@ if (!Platform.isTV) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep the splash screen visible while we fetch resources
|
||||||
|
SplashScreen.preventAutoHideAsync();
|
||||||
|
|
||||||
|
// Set the animation options. This is optional.
|
||||||
|
SplashScreen.setOptions({
|
||||||
|
duration: 500,
|
||||||
|
fade: true,
|
||||||
|
});
|
||||||
|
|
||||||
function useNotificationObserver() {
|
function useNotificationObserver() {
|
||||||
if (Platform.isTV) return;
|
if (Platform.isTV) return;
|
||||||
|
|
||||||
@@ -224,17 +230,15 @@ export default function RootLayout() {
|
|||||||
Appearance.setColorScheme("dark");
|
Appearance.setColorScheme("dark");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SplashScreenProvider>
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||||
<GestureHandlerRootView style={{ flex: 1 }}>
|
<JotaiProvider>
|
||||||
<JotaiProvider>
|
<ActionSheetProvider>
|
||||||
<ActionSheetProvider>
|
<I18nextProvider i18n={i18n}>
|
||||||
<I18nextProvider i18n={i18n}>
|
<Layout />
|
||||||
<Layout />
|
</I18nextProvider>
|
||||||
</I18nextProvider>
|
</ActionSheetProvider>
|
||||||
</ActionSheetProvider>
|
</JotaiProvider>
|
||||||
</JotaiProvider>
|
</GestureHandlerRootView>
|
||||||
</GestureHandlerRootView>
|
|
||||||
</SplashScreenProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,16 +307,6 @@ function Layout() {
|
|||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [loaded] = useFonts({
|
|
||||||
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
|
|
||||||
});
|
|
||||||
|
|
||||||
useSplashScreenLoading(!loaded);
|
|
||||||
|
|
||||||
if (!loaded) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<JobQueueProvider>
|
<JobQueueProvider>
|
||||||
@@ -324,7 +318,7 @@ function Layout() {
|
|||||||
<BottomSheetModalProvider>
|
<BottomSheetModalProvider>
|
||||||
<SystemBars style="light" hidden={false} />
|
<SystemBars style="light" hidden={false} />
|
||||||
<ThemeProvider value={DarkTheme}>
|
<ThemeProvider value={DarkTheme}>
|
||||||
<Stack>
|
<Stack initialRouteName="(auth)/(tabs)">
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="(auth)/(tabs)"
|
name="(auth)/(tabs)"
|
||||||
options={{
|
options={{
|
||||||
|
|||||||
@@ -237,7 +237,6 @@ const Login: React.FC = () => {
|
|||||||
setCredentials({ ...credentials, username: text })
|
setCredentials({ ...credentials, username: text })
|
||||||
}
|
}
|
||||||
value={credentials.username}
|
value={credentials.username}
|
||||||
autoFocus
|
|
||||||
secureTextEntry={false}
|
secureTextEntry={false}
|
||||||
keyboardType="default"
|
keyboardType="default"
|
||||||
returnKeyType="done"
|
returnKeyType="done"
|
||||||
|
|||||||
2
bun.lock
2
bun.lock
@@ -44,7 +44,7 @@
|
|||||||
"expo-router": "~4.0.17",
|
"expo-router": "~4.0.17",
|
||||||
"expo-screen-orientation": "~8.0.4",
|
"expo-screen-orientation": "~8.0.4",
|
||||||
"expo-sensors": "~14.0.2",
|
"expo-sensors": "~14.0.2",
|
||||||
"expo-splash-screen": "~0.29.21",
|
"expo-splash-screen": "~0.29.22",
|
||||||
"expo-status-bar": "~2.0.1",
|
"expo-status-bar": "~2.0.1",
|
||||||
"expo-system-ui": "~4.0.8",
|
"expo-system-ui": "~4.0.8",
|
||||||
"expo-task-manager": "~12.0.5",
|
"expo-task-manager": "~12.0.5",
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ import { Colors } from "@/constants/Colors";
|
|||||||
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
|
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
|
||||||
import { useDownload } from "@/providers/DownloadProvider";
|
import { useDownload } from "@/providers/DownloadProvider";
|
||||||
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||||
import {
|
|
||||||
useSplashScreenLoading,
|
|
||||||
useSplashScreenVisible,
|
|
||||||
} from "@/providers/SplashScreenProvider";
|
|
||||||
import { useSettings } from "@/utils/atoms/settings";
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
import { Feather, Ionicons } from "@expo/vector-icons";
|
import { Feather, Ionicons } from "@expo/vector-icons";
|
||||||
import { Api } from "@jellyfin/sdk";
|
import { Api } from "@jellyfin/sdk";
|
||||||
@@ -156,10 +152,6 @@ export const SettingsIndex = () => {
|
|||||||
staleTime: 60 * 1000,
|
staleTime: 60 * 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// show splash screen until query loaded
|
|
||||||
useSplashScreenLoading(l1);
|
|
||||||
const splashScreenVisible = useSplashScreenVisible();
|
|
||||||
|
|
||||||
const userViews = useMemo(
|
const userViews = useMemo(
|
||||||
() => data?.filter((l) => !settings?.hiddenLibraries?.includes(l.Id!)),
|
() => data?.filter((l) => !settings?.hiddenLibraries?.includes(l.Id!)),
|
||||||
[data, settings?.hiddenLibraries]
|
[data, settings?.hiddenLibraries]
|
||||||
@@ -414,9 +406,7 @@ export const SettingsIndex = () => {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
// this spinner should only show up, when user navigates here
|
if (l1)
|
||||||
// on launch the splash screen is used for loading
|
|
||||||
if (l1 && !splashScreenVisible)
|
|
||||||
return (
|
return (
|
||||||
<View className="justify-center items-center h-full">
|
<View className="justify-center items-center h-full">
|
||||||
<Loader />
|
<Loader />
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ import { Loader } from "@/components/Loader";
|
|||||||
import { MediaListSection } from "@/components/medialists/MediaListSection";
|
import { MediaListSection } from "@/components/medialists/MediaListSection";
|
||||||
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
|
import { useInvalidatePlaybackProgressCache } from "@/hooks/useRevalidatePlaybackProgressCache";
|
||||||
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||||
import {
|
|
||||||
useSplashScreenLoading,
|
|
||||||
useSplashScreenVisible,
|
|
||||||
} from "@/providers/SplashScreenProvider";
|
|
||||||
import { useSettings } from "@/utils/atoms/settings";
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { Api } from "@jellyfin/sdk";
|
import { Api } from "@jellyfin/sdk";
|
||||||
@@ -124,10 +120,6 @@ export const SettingsIndex = () => {
|
|||||||
staleTime: 60 * 1000,
|
staleTime: 60 * 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
// show splash screen until query loaded
|
|
||||||
useSplashScreenLoading(l1);
|
|
||||||
const splashScreenVisible = useSplashScreenVisible();
|
|
||||||
|
|
||||||
const userViews = useMemo(
|
const userViews = useMemo(
|
||||||
() => data?.filter((l) => !settings?.hiddenLibraries?.includes(l.Id!)),
|
() => data?.filter((l) => !settings?.hiddenLibraries?.includes(l.Id!)),
|
||||||
[data, settings?.hiddenLibraries]
|
[data, settings?.hiddenLibraries]
|
||||||
@@ -382,9 +374,7 @@ export const SettingsIndex = () => {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
// this spinner should only show up, when user navigates here
|
if (l1)
|
||||||
// on launch the splash screen is used for loading
|
|
||||||
if (l1 && !splashScreenVisible)
|
|
||||||
return (
|
return (
|
||||||
<View className="justify-center items-center h-full">
|
<View className="justify-center items-center h-full">
|
||||||
<Loader />
|
<Loader />
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
"expo-router": "~4.0.17",
|
"expo-router": "~4.0.17",
|
||||||
"expo-screen-orientation": "~8.0.4",
|
"expo-screen-orientation": "~8.0.4",
|
||||||
"expo-sensors": "~14.0.2",
|
"expo-sensors": "~14.0.2",
|
||||||
"expo-splash-screen": "~0.29.21",
|
"expo-splash-screen": "~0.29.22",
|
||||||
"expo-status-bar": "~2.0.1",
|
"expo-status-bar": "~2.0.1",
|
||||||
"expo-system-ui": "~4.0.8",
|
"expo-system-ui": "~4.0.8",
|
||||||
"expo-task-manager": "~12.0.5",
|
"expo-task-manager": "~12.0.5",
|
||||||
|
|||||||
BIN
providers/.JellyfinProvider.tsx.swp
Normal file
BIN
providers/.JellyfinProvider.tsx.swp
Normal file
Binary file not shown.
@@ -1,5 +1,7 @@
|
|||||||
import "@/augmentations";
|
import "@/augmentations";
|
||||||
import { useInterval } from "@/hooks/useInterval";
|
import { useInterval } from "@/hooks/useInterval";
|
||||||
|
import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
|
||||||
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
import { storage } from "@/utils/mmkv";
|
import { storage } from "@/utils/mmkv";
|
||||||
import { Api, Jellyfin } from "@jellyfin/sdk";
|
import { Api, Jellyfin } from "@jellyfin/sdk";
|
||||||
import { UserDto } from "@jellyfin/sdk/lib/generated-client/models";
|
import { UserDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||||
@@ -7,6 +9,7 @@ import { getUserApi } from "@jellyfin/sdk/lib/utils/api";
|
|||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import axios, { AxiosError } from "axios";
|
import axios, { AxiosError } from "axios";
|
||||||
import { router, useSegments } from "expo-router";
|
import { router, useSegments } from "expo-router";
|
||||||
|
import * as SplashScreen from "expo-splash-screen";
|
||||||
import { atom, useAtom } from "jotai";
|
import { atom, useAtom } from "jotai";
|
||||||
import React, {
|
import React, {
|
||||||
createContext,
|
createContext,
|
||||||
@@ -17,16 +20,10 @@ import React, {
|
|||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Platform } from "react-native";
|
|
||||||
import uuid from "react-native-uuid";
|
|
||||||
import { getDeviceName } from "react-native-device-info";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useSettings } from "@/utils/atoms/settings";
|
import { Platform } from "react-native";
|
||||||
import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
|
import { getDeviceName } from "react-native-device-info";
|
||||||
import {
|
import uuid from "react-native-uuid";
|
||||||
useSplashScreenLoading,
|
|
||||||
useSplashScreenVisible,
|
|
||||||
} from "./SplashScreenProvider";
|
|
||||||
|
|
||||||
interface Server {
|
interface Server {
|
||||||
address: string;
|
address: string;
|
||||||
@@ -88,22 +85,6 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
] = useSettings();
|
] = useSettings();
|
||||||
const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr();
|
const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr();
|
||||||
|
|
||||||
useQuery({
|
|
||||||
queryKey: ["user", api],
|
|
||||||
queryFn: async () => {
|
|
||||||
if (!api) return null;
|
|
||||||
const response = await getUserApi(api).getCurrentUser();
|
|
||||||
if (response.data) setUser(response.data);
|
|
||||||
return user;
|
|
||||||
},
|
|
||||||
enabled: !!api,
|
|
||||||
refetchOnWindowFocus: true,
|
|
||||||
refetchInterval: 1000 * 60,
|
|
||||||
refetchIntervalInBackground: true,
|
|
||||||
refetchOnMount: true,
|
|
||||||
refetchOnReconnect: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const headers = useMemo(() => {
|
const headers = useMemo(() => {
|
||||||
if (!deviceId) return {};
|
if (!deviceId) return {};
|
||||||
return {
|
return {
|
||||||
@@ -179,14 +160,13 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
}
|
}
|
||||||
}, [api, secret, headers]);
|
}, [api, secret, headers]);
|
||||||
|
|
||||||
useInterval(pollQuickConnect, isPolling ? 1000 : null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
await refreshStreamyfinPluginSettings();
|
await refreshStreamyfinPluginSettings();
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useInterval(pollQuickConnect, isPolling ? 1000 : null);
|
||||||
useInterval(refreshStreamyfinPluginSettings, 60 * 5 * 1000); // 5 min
|
useInterval(refreshStreamyfinPluginSettings, 60 * 5 * 1000); // 5 min
|
||||||
|
|
||||||
const discoverServers = async (url: string): Promise<Server[]> => {
|
const discoverServers = async (url: string): Promise<Server[]> => {
|
||||||
@@ -312,33 +292,44 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { isLoading, isFetching } = useQuery({
|
const [loaded, setLoaded] = useState(false);
|
||||||
queryKey: [
|
const [initialLoaded, setInitialLoaded] = useState(false);
|
||||||
"initializeJellyfin",
|
|
||||||
user?.Id,
|
useEffect(() => {
|
||||||
api?.basePath,
|
if (initialLoaded) {
|
||||||
jellyfin?.clientInfo,
|
setLoaded(true);
|
||||||
],
|
}
|
||||||
queryFn: async () => {
|
}, [initialLoaded]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const initializeJellyfin = async () => {
|
||||||
|
if (!jellyfin) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const token = getTokenFromStorage();
|
const token = getTokenFromStorage();
|
||||||
const serverUrl = getServerUrlFromStorage();
|
const serverUrl = getServerUrlFromStorage();
|
||||||
const user = getUserFromStorage();
|
const storedUser = getUserFromStorage();
|
||||||
if (serverUrl && token && user?.Id && jellyfin) {
|
|
||||||
|
if (serverUrl && token) {
|
||||||
const apiInstance = jellyfin.createApi(serverUrl, token);
|
const apiInstance = jellyfin.createApi(serverUrl, token);
|
||||||
setApi(apiInstance);
|
setApi(apiInstance);
|
||||||
setUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
if (storedUser?.Id) {
|
||||||
|
setUser(storedUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await getUserApi(apiInstance).getCurrentUser();
|
||||||
|
setUser(response.data);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
return false;
|
} finally {
|
||||||
|
setInitialLoaded(true);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
staleTime: 0,
|
|
||||||
enabled: !user?.Id || !api || !jellyfin,
|
initializeJellyfin();
|
||||||
});
|
}, [jellyfin]);
|
||||||
|
|
||||||
const contextValue: JellyfinContextValue = {
|
const contextValue: JellyfinContextValue = {
|
||||||
discoverServers,
|
discoverServers,
|
||||||
@@ -350,17 +341,17 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
initiateQuickConnect,
|
initiateQuickConnect,
|
||||||
};
|
};
|
||||||
|
|
||||||
let isLoadingOrFetching = isLoading || isFetching;
|
useEffect(() => {
|
||||||
useProtectedRoute(user, isLoadingOrFetching);
|
if (loaded) {
|
||||||
|
SplashScreen.hideAsync();
|
||||||
|
}
|
||||||
|
}, [loaded]);
|
||||||
|
|
||||||
// show splash screen until everything loaded
|
useProtectedRoute(user, loaded);
|
||||||
useSplashScreenLoading(isLoadingOrFetching);
|
|
||||||
const splashScreenVisible = useSplashScreenVisible();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<JellyfinContext.Provider value={contextValue}>
|
<JellyfinContext.Provider value={contextValue}>
|
||||||
{/* don't render login page when loading and splash screen visible */}
|
{children}
|
||||||
{isLoadingOrFetching && splashScreenVisible ? undefined : children}
|
|
||||||
</JellyfinContext.Provider>
|
</JellyfinContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -372,20 +363,24 @@ export const useJellyfin = (): JellyfinContextValue => {
|
|||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
function useProtectedRoute(user: UserDto | null, loading = false) {
|
function useProtectedRoute(user: UserDto | null, loaded = false) {
|
||||||
const segments = useSegments();
|
const segments = useSegments();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loading) return;
|
if (loaded === false) return;
|
||||||
|
|
||||||
|
console.log("Loaded", user);
|
||||||
|
|
||||||
const inAuthGroup = segments[0] === "(auth)";
|
const inAuthGroup = segments[0] === "(auth)";
|
||||||
|
|
||||||
if (!user?.Id && inAuthGroup) {
|
if (!user?.Id && inAuthGroup) {
|
||||||
|
console.log("Redirected to login");
|
||||||
router.replace("/login");
|
router.replace("/login");
|
||||||
} else if (user?.Id && !inAuthGroup) {
|
} else if (user?.Id && !inAuthGroup) {
|
||||||
|
console.log("Redirected to home");
|
||||||
router.replace("/(auth)/(tabs)/(home)/");
|
router.replace("/(auth)/(tabs)/(home)/");
|
||||||
}
|
}
|
||||||
}, [user, segments, loading]);
|
}, [user, segments, loaded]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTokenFromStorage(): string | null {
|
export function getTokenFromStorage(): string | null {
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
import {
|
|
||||||
createContext,
|
|
||||||
ReactNode,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
useRef,
|
|
||||||
} from "react";
|
|
||||||
import * as SplashScreen from "expo-splash-screen";
|
|
||||||
|
|
||||||
type SplashScreenContextValue = {
|
|
||||||
registerLoadingComponent: () => () => void;
|
|
||||||
splashScreenVisible: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SplashScreenContext = createContext<SplashScreenContextValue | undefined>(
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
// Prevent splash screen from auto-hiding
|
|
||||||
void SplashScreen.preventAutoHideAsync();
|
|
||||||
|
|
||||||
export const SplashScreenProvider: React.FC<{ children: ReactNode }> = ({
|
|
||||||
children,
|
|
||||||
}) => {
|
|
||||||
const [splashScreenVisible, setSplashScreenVisible] = useState(true);
|
|
||||||
const loadingComponentsCount = useRef(0);
|
|
||||||
const isHidingRef = useRef(false);
|
|
||||||
|
|
||||||
const hideScreenIfNoLoadingComponents = async () => {
|
|
||||||
if (loadingComponentsCount.current === 0 && !isHidingRef.current) {
|
|
||||||
try {
|
|
||||||
isHidingRef.current = true;
|
|
||||||
await SplashScreen.hideAsync();
|
|
||||||
setSplashScreenVisible(false);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("Failed to hide splash screen:", error);
|
|
||||||
} finally {
|
|
||||||
isHidingRef.current = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const registerLoadingComponent = () => {
|
|
||||||
loadingComponentsCount.current += 1;
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
loadingComponentsCount.current -= 1;
|
|
||||||
void hideScreenIfNoLoadingComponents();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextValue: SplashScreenContextValue = {
|
|
||||||
registerLoadingComponent,
|
|
||||||
splashScreenVisible,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SplashScreenContext.Provider value={contextValue}>
|
|
||||||
{children}
|
|
||||||
</SplashScreenContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the Splash Screen until component is ready to be displayed.
|
|
||||||
*
|
|
||||||
* @param isLoading The loading state of the component
|
|
||||||
*
|
|
||||||
* ## Usage
|
|
||||||
* ```
|
|
||||||
* const isLoading = loadSomething()
|
|
||||||
* useSplashScreenLoading(isLoading) // splash screen visible until isLoading is false
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function useSplashScreenLoading(isLoading: boolean) {
|
|
||||||
const context = useContext(SplashScreenContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"useSplashScreenLoading must be used within a SplashScreenProvider"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isLoading) {
|
|
||||||
return context.registerLoadingComponent();
|
|
||||||
}
|
|
||||||
}, [isLoading]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the visibility of the Splash Screen.
|
|
||||||
* @returns the visibility of the Splash Screen
|
|
||||||
*/
|
|
||||||
export function useSplashScreenVisible() {
|
|
||||||
const context = useContext(SplashScreenContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"useSplashScreenVisible must be used within a SplashScreenProvider"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context.splashScreenVisible;
|
|
||||||
}
|
|
||||||
@@ -268,6 +268,8 @@ export const useSettings = () => {
|
|||||||
const newSettings = { ..._settings, ...update };
|
const newSettings = { ..._settings, ...update };
|
||||||
|
|
||||||
setSettings(newSettings);
|
setSettings(newSettings);
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
saveSettings(newSettings);
|
saveSettings(newSettings);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user