mirror of
https://github.com/streamyfin/streamyfin.git
synced 2025-08-20 18:37:18 +02:00
chore
This commit is contained in:
7
app.json
7
app.json
@@ -9,8 +9,7 @@
|
|||||||
"userInterfaceStyle": "dark",
|
"userInterfaceStyle": "dark",
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/images/splash.png",
|
"image": "./assets/images/splash.png",
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain"
|
||||||
"backgroundColor": "#2E2E2E"
|
|
||||||
},
|
},
|
||||||
"jsEngine": "hermes",
|
"jsEngine": "hermes",
|
||||||
"assetBundlePatterns": ["**/*"],
|
"assetBundlePatterns": ["**/*"],
|
||||||
@@ -89,7 +88,9 @@
|
|||||||
"jniLibs": {
|
"jniLibs": {
|
||||||
"useLegacyPackaging": true
|
"useLegacyPackaging": true
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"useAndroidX": true,
|
||||||
|
"enableJetifier": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
188
app/_layout.tsx
188
app/_layout.tsx
@@ -1,5 +1,5 @@
|
|||||||
import "@/augmentations";
|
import "@/augmentations";
|
||||||
import { Text } from "@/components/common/Text";
|
import i18n from "@/i18n";
|
||||||
import { DownloadProvider } from "@/providers/DownloadProvider";
|
import { DownloadProvider } from "@/providers/DownloadProvider";
|
||||||
import {
|
import {
|
||||||
getOrSetDeviceId,
|
getOrSetDeviceId,
|
||||||
@@ -8,9 +8,11 @@ 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 {
|
||||||
|
SplashScreenProvider,
|
||||||
|
useSplashScreenLoading,
|
||||||
|
} from "@/providers/SplashScreenProvider";
|
||||||
import { WebSocketProvider } from "@/providers/WebSocketProvider";
|
import { WebSocketProvider } from "@/providers/WebSocketProvider";
|
||||||
import { orientationAtom } from "@/utils/atoms/orientation";
|
|
||||||
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";
|
||||||
import { LogProvider, writeToLog } from "@/utils/log";
|
import { LogProvider, writeToLog } from "@/utils/log";
|
||||||
@@ -30,19 +32,17 @@ import * as BackgroundFetch from "expo-background-fetch";
|
|||||||
import * as FileSystem from "expo-file-system";
|
import * as FileSystem from "expo-file-system";
|
||||||
import { useFonts } from "expo-font";
|
import { useFonts } from "expo-font";
|
||||||
import { useKeepAwake } from "expo-keep-awake";
|
import { useKeepAwake } from "expo-keep-awake";
|
||||||
import * as Linking from "expo-linking";
|
import { getLocales } from "expo-localization";
|
||||||
import * as Notifications from "expo-notifications";
|
import * as Notifications from "expo-notifications";
|
||||||
import { router, Stack } from "expo-router";
|
import { router, Stack } from "expo-router";
|
||||||
import * as ScreenOrientation from "expo-screen-orientation";
|
import * as ScreenOrientation from "expo-screen-orientation";
|
||||||
import * as TaskManager from "expo-task-manager";
|
import * as TaskManager from "expo-task-manager";
|
||||||
import { Provider as JotaiProvider, useAtom } from "jotai";
|
import { Provider as JotaiProvider } from "jotai";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { Appearance, AppState, TouchableOpacity } from "react-native";
|
import { I18nextProvider, useTranslation } from "react-i18next";
|
||||||
|
import { Appearance, AppState } from "react-native";
|
||||||
import { SystemBars } from "react-native-edge-to-edge";
|
import { SystemBars } from "react-native-edge-to-edge";
|
||||||
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
||||||
import { I18nextProvider, useTranslation } from "react-i18next";
|
|
||||||
import i18n from "@/i18n";
|
|
||||||
import { getLocales } from "expo-localization";
|
|
||||||
import "react-native-reanimated";
|
import "react-native-reanimated";
|
||||||
import { Toaster } from "sonner-native";
|
import { Toaster } from "sonner-native";
|
||||||
|
|
||||||
@@ -214,13 +214,17 @@ export default function RootLayout() {
|
|||||||
Appearance.setColorScheme("dark");
|
Appearance.setColorScheme("dark");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<JotaiProvider>
|
<SplashScreenProvider>
|
||||||
<SplashScreenProvider>
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
||||||
<I18nextProvider i18n={i18n}>
|
<JotaiProvider>
|
||||||
<Layout />
|
<ActionSheetProvider>
|
||||||
</I18nextProvider>
|
<I18nextProvider i18n={i18n}>
|
||||||
</SplashScreenProvider>
|
<Layout />
|
||||||
</JotaiProvider>
|
</I18nextProvider>
|
||||||
|
</ActionSheetProvider>
|
||||||
|
</JotaiProvider>
|
||||||
|
</GestureHandlerRootView>
|
||||||
|
</SplashScreenProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,8 +241,7 @@ const queryClient = new QueryClient({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function Layout() {
|
function Layout() {
|
||||||
const [settings, updateSettings] = useSettings();
|
const [settings] = useSettings();
|
||||||
const [orientation, setOrientation] = useAtom(orientationAtom);
|
|
||||||
|
|
||||||
useKeepAwake();
|
useKeepAwake();
|
||||||
useNotificationObserver();
|
useNotificationObserver();
|
||||||
@@ -283,104 +286,77 @@ function Layout() {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const subscription = ScreenOrientation.addOrientationChangeListener(
|
|
||||||
(event) => {
|
|
||||||
setOrientation(event.orientationInfo.orientation);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
ScreenOrientation.getOrientationAsync().then((initialOrientation) => {
|
|
||||||
setOrientation(initialOrientation);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
ScreenOrientation.removeOrientationChangeListener(subscription);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const url = Linking.useURL();
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
const { hostname, path, queryParams } = Linking.parse(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [loaded] = useFonts({
|
const [loaded] = useFonts({
|
||||||
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
|
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
|
||||||
});
|
});
|
||||||
|
|
||||||
// show splash screen until everything loaded
|
useSplashScreenLoading(!loaded);
|
||||||
useSplashScreenLoading(!loaded)
|
|
||||||
|
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GestureHandlerRootView style={{ flex: 1 }}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<JobQueueProvider>
|
||||||
<ActionSheetProvider>
|
<JellyfinProvider>
|
||||||
<JobQueueProvider>
|
<PlaySettingsProvider>
|
||||||
<JellyfinProvider>
|
<LogProvider>
|
||||||
<PlaySettingsProvider>
|
<WebSocketProvider>
|
||||||
<LogProvider>
|
<DownloadProvider>
|
||||||
<WebSocketProvider>
|
<BottomSheetModalProvider>
|
||||||
<DownloadProvider>
|
<SystemBars style="light" hidden={false} />
|
||||||
<BottomSheetModalProvider>
|
<ThemeProvider value={DarkTheme}>
|
||||||
<SystemBars style="light" hidden={false} />
|
<Stack>
|
||||||
<ThemeProvider value={DarkTheme}>
|
<Stack.Screen
|
||||||
<Stack>
|
name="(auth)/(tabs)"
|
||||||
<Stack.Screen
|
options={{
|
||||||
name="(auth)/(tabs)"
|
headerShown: false,
|
||||||
options={{
|
title: "",
|
||||||
headerShown: false,
|
header: () => null,
|
||||||
title: "",
|
}}
|
||||||
header: () => null,
|
/>
|
||||||
}}
|
<Stack.Screen
|
||||||
/>
|
name="(auth)/player"
|
||||||
<Stack.Screen
|
options={{
|
||||||
name="(auth)/player"
|
headerShown: false,
|
||||||
options={{
|
title: "",
|
||||||
headerShown: false,
|
header: () => null,
|
||||||
title: "",
|
}}
|
||||||
header: () => null,
|
/>
|
||||||
}}
|
<Stack.Screen
|
||||||
/>
|
name="login"
|
||||||
<Stack.Screen
|
options={{
|
||||||
name="login"
|
headerShown: true,
|
||||||
options={{
|
title: "",
|
||||||
headerShown: true,
|
headerTransparent: true,
|
||||||
title: "",
|
}}
|
||||||
headerTransparent: true,
|
/>
|
||||||
}}
|
<Stack.Screen name="+not-found" />
|
||||||
/>
|
</Stack>
|
||||||
<Stack.Screen name="+not-found" />
|
<Toaster
|
||||||
</Stack>
|
duration={4000}
|
||||||
<Toaster
|
toastOptions={{
|
||||||
duration={4000}
|
style: {
|
||||||
toastOptions={{
|
backgroundColor: "#262626",
|
||||||
style: {
|
borderColor: "#363639",
|
||||||
backgroundColor: "#262626",
|
borderWidth: 1,
|
||||||
borderColor: "#363639",
|
},
|
||||||
borderWidth: 1,
|
titleStyle: {
|
||||||
},
|
color: "white",
|
||||||
titleStyle: {
|
},
|
||||||
color: "white",
|
}}
|
||||||
},
|
closeButton
|
||||||
}}
|
/>
|
||||||
closeButton
|
</ThemeProvider>
|
||||||
/>
|
</BottomSheetModalProvider>
|
||||||
</ThemeProvider>
|
</DownloadProvider>
|
||||||
</BottomSheetModalProvider>
|
</WebSocketProvider>
|
||||||
</DownloadProvider>
|
</LogProvider>
|
||||||
</WebSocketProvider>
|
</PlaySettingsProvider>
|
||||||
</LogProvider>
|
</JellyfinProvider>
|
||||||
</PlaySettingsProvider>
|
</JobQueueProvider>
|
||||||
</JellyfinProvider>
|
</QueryClientProvider>
|
||||||
</JobQueueProvider>
|
|
||||||
</ActionSheetProvider>
|
|
||||||
</QueryClientProvider>
|
|
||||||
</GestureHandlerRootView>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
package.json
23
package.json
@@ -14,8 +14,9 @@
|
|||||||
"postinstall": "patch-package"
|
"postinstall": "patch-package"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bottom-tabs/react-navigation": "0.8.0",
|
"@bottom-tabs/react-navigation": "0.8.3",
|
||||||
"@config-plugins/ffmpeg-kit-react-native": "^8.0.0",
|
"@config-plugins/ffmpeg-kit-react-native": "^8.0.0",
|
||||||
|
"@expo/config-plugins": "~9.0.0",
|
||||||
"@expo/react-native-action-sheet": "^4.1.0",
|
"@expo/react-native-action-sheet": "^4.1.0",
|
||||||
"@expo/vector-icons": "^14.0.4",
|
"@expo/vector-icons": "^14.0.4",
|
||||||
"@futurejj/react-native-visibility-sensor": "^1.3.5",
|
"@futurejj/react-native-visibility-sensor": "^1.3.5",
|
||||||
@@ -25,8 +26,9 @@
|
|||||||
"@react-native-async-storage/async-storage": "1.23.1",
|
"@react-native-async-storage/async-storage": "1.23.1",
|
||||||
"@react-native-community/netinfo": "11.4.1",
|
"@react-native-community/netinfo": "11.4.1",
|
||||||
"@react-native-menu/menu": "^1.1.6",
|
"@react-native-menu/menu": "^1.1.6",
|
||||||
|
"@react-navigation/bottom-tabs": "^7.0.0",
|
||||||
"@react-navigation/material-top-tabs": "^7.1.0",
|
"@react-navigation/material-top-tabs": "^7.1.0",
|
||||||
"@react-navigation/native": "^7.0.14",
|
"@react-navigation/native": "^7.0.0",
|
||||||
"@shopify/flash-list": "1.7.1",
|
"@shopify/flash-list": "1.7.1",
|
||||||
"@tanstack/react-query": "^5.59.20",
|
"@tanstack/react-query": "^5.59.20",
|
||||||
"@types/lodash": "^4.17.13",
|
"@types/lodash": "^4.17.13",
|
||||||
@@ -34,13 +36,13 @@
|
|||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"add": "^2.0.6",
|
"add": "^2.0.6",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
"expo": "^52.0.0",
|
"expo": "^52.0.28",
|
||||||
"expo-asset": "~11.0.2",
|
"expo-asset": "~11.0.2",
|
||||||
"expo-background-fetch": "~13.0.4",
|
"expo-background-fetch": "~13.0.5",
|
||||||
"expo-blur": "~14.0.3",
|
"expo-blur": "~14.0.3",
|
||||||
"expo-brightness": "~13.0.3",
|
"expo-brightness": "~13.0.3",
|
||||||
"expo-build-properties": "~0.13.2",
|
"expo-build-properties": "~0.13.2",
|
||||||
"expo-constants": "~17.0.4",
|
"expo-constants": "~17.0.5",
|
||||||
"expo-crypto": "~14.0.2",
|
"expo-crypto": "~14.0.2",
|
||||||
"expo-dev-client": "~5.0.10",
|
"expo-dev-client": "~5.0.10",
|
||||||
"expo-device": "~7.0.2",
|
"expo-device": "~7.0.2",
|
||||||
@@ -49,20 +51,21 @@
|
|||||||
"expo-image": "~2.0.4",
|
"expo-image": "~2.0.4",
|
||||||
"expo-keep-awake": "~14.0.2",
|
"expo-keep-awake": "~14.0.2",
|
||||||
"expo-linear-gradient": "~14.0.2",
|
"expo-linear-gradient": "~14.0.2",
|
||||||
"expo-linking": "~7.0.4",
|
"expo-linking": "~7.0.5",
|
||||||
"expo-localization": "~16.0.1",
|
"expo-localization": "~16.0.1",
|
||||||
"expo-network": "~7.0.5",
|
"expo-network": "~7.0.5",
|
||||||
"expo-notifications": "~0.29.12",
|
"expo-notifications": "~0.29.13",
|
||||||
"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.21",
|
||||||
"expo-status-bar": "~2.0.1",
|
"expo-status-bar": "~2.0.1",
|
||||||
"expo-system-ui": "~4.0.7",
|
"expo-system-ui": "~4.0.7",
|
||||||
"expo-task-manager": "~12.0.4",
|
"expo-task-manager": "~12.0.5",
|
||||||
"expo-updates": "~0.26.13",
|
"expo-updates": "~0.26.13",
|
||||||
"expo-web-browser": "~14.0.2",
|
"expo-web-browser": "~14.0.2",
|
||||||
"ffmpeg-kit-react-native": "^6.0.2",
|
"ffmpeg-kit-react-native": "^6.0.2",
|
||||||
|
"i18next": "^24.2.2",
|
||||||
"install": "^0.13.0",
|
"install": "^0.13.0",
|
||||||
"jotai": "^2.10.1",
|
"jotai": "^2.10.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -72,7 +75,7 @@
|
|||||||
"react-i18next": "^15.4.0",
|
"react-i18next": "^15.4.0",
|
||||||
"react-native": "0.76.6",
|
"react-native": "0.76.6",
|
||||||
"react-native-awesome-slider": "^2.5.6",
|
"react-native-awesome-slider": "^2.5.6",
|
||||||
"react-native-bottom-tabs": "0.8.0",
|
"react-native-bottom-tabs": "0.8.3",
|
||||||
"react-native-circular-progress": "^1.4.1",
|
"react-native-circular-progress": "^1.4.1",
|
||||||
"react-native-compressor": "^1.9.0",
|
"react-native-compressor": "^1.9.0",
|
||||||
"react-native-country-flag": "^2.0.2",
|
"react-native-country-flag": "^2.0.2",
|
||||||
@@ -81,7 +84,7 @@
|
|||||||
"react-native-gesture-handler": "~2.20.2",
|
"react-native-gesture-handler": "~2.20.2",
|
||||||
"react-native-get-random-values": "^1.11.0",
|
"react-native-get-random-values": "^1.11.0",
|
||||||
"react-native-google-cast": "^4.8.3",
|
"react-native-google-cast": "^4.8.3",
|
||||||
"react-native-image-colors": "^2.4.0",
|
"react-native-image-colors": "^1.3.1",
|
||||||
"react-native-ios-context-menu": "^2.5.2",
|
"react-native-ios-context-menu": "^2.5.2",
|
||||||
"react-native-ios-utilities": "4.5.3",
|
"react-native-ios-utilities": "4.5.3",
|
||||||
"react-native-mmkv": "^2.12.2",
|
"react-native-mmkv": "^2.12.2",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<base-config cleartextTrafficPermitted="false">
|
<base-config cleartextTrafficPermitted="false">
|
||||||
<trust-anchors>
|
<trust-anchors>
|
||||||
<certificates src="system" />
|
<certificates src="system" />
|
||||||
|
<certificates src="user" />
|
||||||
</trust-anchors>
|
</trust-anchors>
|
||||||
</base-config>
|
</base-config>
|
||||||
</network-security-config>
|
</network-security-config>
|
||||||
@@ -1,115 +1,103 @@
|
|||||||
import { createContext, ReactNode, useContext, useEffect, useMemo, useState } from "react";
|
import {
|
||||||
import * as Crypto from 'expo-crypto';
|
createContext,
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
import * as SplashScreen from "expo-splash-screen";
|
import * as SplashScreen from "expo-splash-screen";
|
||||||
|
|
||||||
class ChangeListenerMap<K, V> extends Map<K, V> {
|
|
||||||
constructor(private readonly onChange: (e: { self: ChangeListenerMap<K, V>, key: K, oldValue: V | undefined, newValue: V }) => void) {
|
|
||||||
super()
|
|
||||||
}
|
|
||||||
|
|
||||||
public set(key: K, value: V): this {
|
|
||||||
const oldValue = this.get(key);
|
|
||||||
super.set(key, value);
|
|
||||||
if(oldValue !== value) {
|
|
||||||
this.onChange({ self: this, key, oldValue, newValue: value })
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type SplashScreenContextValue = {
|
type SplashScreenContextValue = {
|
||||||
splashScreenVisible: boolean,
|
registerLoadingComponent: () => () => void;
|
||||||
componentLoaded: Map<string, boolean>
|
splashScreenVisible: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const SplashScreenContext = createContext<SplashScreenContextValue | undefined>(undefined)
|
const SplashScreenContext = createContext<SplashScreenContextValue | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
SplashScreen.preventAutoHideAsync();
|
// Prevent splash screen from auto-hiding
|
||||||
|
void SplashScreen.preventAutoHideAsync();
|
||||||
|
|
||||||
export const SplashScreenProvider: React.FC<{ children: ReactNode }> = ({
|
export const SplashScreenProvider: React.FC<{ children: ReactNode }> = ({
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [splashScreenVisible, setSplashScreenVisible] = useState(true);
|
||||||
|
const loadingComponentsCount = useRef(0);
|
||||||
|
const isHidingRef = useRef(false);
|
||||||
|
|
||||||
const [splashScreenVisible, setSplashScreenVisible] = useState(true)
|
const hideScreenIfNoLoadingComponents = async () => {
|
||||||
|
if (loadingComponentsCount.current === 0 && !isHidingRef.current) {
|
||||||
const contextValue: SplashScreenContextValue = {
|
try {
|
||||||
splashScreenVisible,
|
isHidingRef.current = true;
|
||||||
componentLoaded: new ChangeListenerMap(({ self }) => {
|
await SplashScreen.hideAsync();
|
||||||
for(const entry of self.entries()) {
|
setSplashScreenVisible(false);
|
||||||
if(!entry[1]) {
|
} catch (error) {
|
||||||
// one component not loaded yet, not hiding splash screen
|
console.warn("Failed to hide splash screen:", error);
|
||||||
return
|
} finally {
|
||||||
}
|
isHidingRef.current = false;
|
||||||
}
|
}
|
||||||
SplashScreen.hideAsync()
|
|
||||||
setSplashScreenVisible(false)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
const registerLoadingComponent = () => {
|
||||||
<SplashScreenContext.Provider value={contextValue}>
|
loadingComponentsCount.current += 1;
|
||||||
{children}
|
|
||||||
</SplashScreenContext.Provider>
|
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.
|
* Show the Splash Screen until component is ready to be displayed.
|
||||||
*
|
*
|
||||||
* This only has an effect when component is mounted before Splash Screen is hidden,
|
|
||||||
* so it should only be used in components that show up on launch.
|
|
||||||
*
|
|
||||||
* @param isLoading The loading state of the component
|
* @param isLoading The loading state of the component
|
||||||
*
|
*
|
||||||
* ## Usage
|
* ## Usage
|
||||||
* ```
|
* ```
|
||||||
* // Example 1:
|
|
||||||
* const isLoading = loadSomething()
|
* const isLoading = loadSomething()
|
||||||
* useSplashScreenLoading(isLoading) // splash screen visible until isLoading is false
|
* useSplashScreenLoading(isLoading) // splash screen visible until isLoading is false
|
||||||
* ```
|
* ```
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* // Example 2: multiple loading states
|
|
||||||
* const isLoading1 = loadSomething()
|
|
||||||
* useSplashScreenLoading(isLoading1) // splash screen visible until isLoading1 and isLoading2 are false
|
|
||||||
*
|
|
||||||
* // this could be in different component and still have the same effect
|
|
||||||
* const isLoading2 = loadSomethingElse()
|
|
||||||
* useSplashScreenLoading(isLoading2)
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
export function useSplashScreenLoading(isLoading: boolean) {
|
export function useSplashScreenLoading(isLoading: boolean) {
|
||||||
const id = useMemo(() => Crypto.randomUUID(), []);
|
const context = useContext(SplashScreenContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
"useSplashScreenLoading must be used within a SplashScreenProvider"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const context = useContext(SplashScreenContext);
|
useEffect(() => {
|
||||||
if(!context) {
|
if (isLoading) {
|
||||||
throw new Error("useSplashScreenLoading must be used within a SplashScreenProvider");
|
return context.registerLoadingComponent();
|
||||||
}
|
}
|
||||||
|
}, [isLoading]);
|
||||||
useEffect(() => {
|
|
||||||
// update the loading state of component
|
|
||||||
context.componentLoaded.set(id, !isLoading)
|
|
||||||
|
|
||||||
// cleanup when unmounting component
|
|
||||||
return () => {
|
|
||||||
context.componentLoaded.delete(id);
|
|
||||||
};
|
|
||||||
}, [isLoading])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the visiblity of the Splash Screen.
|
* Get the visibility of the Splash Screen.
|
||||||
* @returns the visibility of the Splash Screen
|
* @returns the visibility of the Splash Screen
|
||||||
*
|
|
||||||
* ## Usage
|
|
||||||
* ```
|
|
||||||
* const splashScreenIsVisible = useSplashScreenVisible()
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
export function useSplashScreenVisible() {
|
export function useSplashScreenVisible() {
|
||||||
const context = useContext(SplashScreenContext);
|
const context = useContext(SplashScreenContext);
|
||||||
if(!context) {
|
if (!context) {
|
||||||
throw new Error("useSplashScreenVisible must be used within a SplashScreenProvider");
|
throw new Error(
|
||||||
}
|
"useSplashScreenVisible must be used within a SplashScreenProvider"
|
||||||
return context.splashScreenVisible
|
);
|
||||||
|
}
|
||||||
|
return context.splashScreenVisible;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user