mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Handle offline mode
This commit is contained in:
parent
4a035327ef
commit
022cd239d5
@ -21,6 +21,7 @@
|
||||
import { ConnectionErrorContext, useAccount } from "@kyoo/models";
|
||||
import { CircularProgress } from "@kyoo/primitives";
|
||||
import { NavbarRight, NavbarTitle } from "@kyoo/ui";
|
||||
import { useNetInfo } from "@react-native-community/netinfo";
|
||||
import { Redirect, SplashScreen, Stack } from "expo-router";
|
||||
import { useContext, useEffect } from "react";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
@ -32,13 +33,14 @@ export default function SignGuard() {
|
||||
// TODO: support guest accounts on mobile too.
|
||||
const account = useAccount();
|
||||
const { loading, error } = useContext(ConnectionErrorContext);
|
||||
const netInfo = useNetInfo();
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading) SplashScreen.hideAsync();
|
||||
}, [loading]);
|
||||
|
||||
if (loading) return <CircularProgress />;
|
||||
if (error) return <Redirect href={"/connection-error"} />;
|
||||
if (error && netInfo.isConnected) return <Redirect href={"/connection-error"} />;
|
||||
if (!account) return <Redirect href="/login" />;
|
||||
return (
|
||||
<Stack
|
||||
|
@ -22,7 +22,7 @@ import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models";
|
||||
import { useBreakpointMap, HR } from "@kyoo/primitives";
|
||||
import { ContentStyle, FlashList } from "@shopify/flash-list";
|
||||
import { ComponentProps, ComponentType, isValidElement, ReactElement, useRef } from "react";
|
||||
import { EmptyView, ErrorView, Layout, WithLoading, addHeader } from "./fetch";
|
||||
import { EmptyView, ErrorView, Layout, OfflineView, WithLoading, addHeader } from "./fetch";
|
||||
import { FlatList, View, ViewStyle } from "react-native";
|
||||
|
||||
const emulateGap = (
|
||||
@ -90,10 +90,11 @@ export const InfiniteFetchList = <Data, Props, _, Kind extends number | string>(
|
||||
}): JSX.Element | null => {
|
||||
const { numColumns, size, gap } = useBreakpointMap(layout);
|
||||
const oldItems = useRef<Data[] | undefined>();
|
||||
let { items, error, fetchNextPage, isFetching, refetch, isRefetching } = query;
|
||||
let { items, isPaused, error, fetchNextPage, isFetching, refetch, isRefetching } = query;
|
||||
if (incremental && items) oldItems.current = items;
|
||||
|
||||
if (error) return <ErrorView error={error} />;
|
||||
if (isPaused) return <OfflineView />
|
||||
if (empty && items && items.length === 0) {
|
||||
if (typeof empty !== "string") return addHeader(Header, empty, headerProps);
|
||||
return addHeader(Header, <EmptyView message={empty} />, headerProps);
|
||||
|
@ -21,6 +21,7 @@
|
||||
import { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
|
||||
import { Breakpoint, P } from "@kyoo/primitives";
|
||||
import { ComponentType, ReactElement, isValidElement } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { View } from "react-native";
|
||||
import { useYoshiki } from "yoshiki/native";
|
||||
|
||||
@ -43,7 +44,7 @@ export type WithError<Item> =
|
||||
const isPage = <T = unknown,>(obj: unknown): obj is Page<T> =>
|
||||
(typeof obj === "object" && obj && "items" in obj) || false;
|
||||
|
||||
export const FetchNE = <Data,>({
|
||||
export const Fetch = <Data,>({
|
||||
query,
|
||||
placeholderCount = 1,
|
||||
children,
|
||||
@ -57,10 +58,10 @@ export const FetchNE = <Data,>({
|
||||
i: number,
|
||||
) => JSX.Element | null;
|
||||
}): JSX.Element | null => {
|
||||
const { data, error } = useFetch(query);
|
||||
const { data, isPaused, error } = useFetch(query);
|
||||
|
||||
// @ts-ignore
|
||||
if (error) return children({ isError: true, error }, 0);
|
||||
if (error) return <ErrorView error={error} />;
|
||||
if (isPaused) return <OfflineView />;
|
||||
if (!data) {
|
||||
const placeholders = [...Array(placeholderCount)].map((_, i) =>
|
||||
children({ isLoading: true } as any, i),
|
||||
@ -72,24 +73,21 @@ export const FetchNE = <Data,>({
|
||||
return <>{data.items.map((item, i) => children({ ...item, isLoading: false } as any, i))}</>;
|
||||
};
|
||||
|
||||
export const Fetch = <Data,>({
|
||||
children,
|
||||
...params
|
||||
}: {
|
||||
query: QueryIdentifier<Data>;
|
||||
placeholderCount?: number;
|
||||
children: (
|
||||
item: Data extends Page<infer Item> ? WithLoading<Item> : WithLoading<Data>,
|
||||
i: number,
|
||||
) => JSX.Element | null;
|
||||
}): JSX.Element | null => {
|
||||
export const OfflineView = () => {
|
||||
const { css } = useYoshiki();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<FetchNE {...params}>
|
||||
{({ isError, error, ...item }, i) =>
|
||||
// @ts-ignore
|
||||
isError ? <ErrorView error={error} /> : children(item, i)
|
||||
}
|
||||
</FetchNE>
|
||||
<View
|
||||
{...css({
|
||||
flexGrow: 1,
|
||||
flexShrink: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
})}
|
||||
>
|
||||
<P {...css({ color: (theme) => theme.colors.white })}>{t("errors.offline")}</P>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -121,6 +121,7 @@
|
||||
"connection-tips": "Troublshotting tips:\n - Are you connected to internet?\n - Is your kyoo's server online?\n - Have your account been banned?",
|
||||
"unknown": "Unknown error",
|
||||
"try-again": "Try again",
|
||||
"re-login": "Re login"
|
||||
"re-login": "Re login",
|
||||
"offline": "You are not connected to internet. Try again later."
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,7 @@
|
||||
"connection-tips": "Possible causes:\n - Etes-vous connecté a internet ?\n - Votre serveur kyoo est-il allumé ?\n - Votre compte est-il bannis ?",
|
||||
"unknown": "Erreur inconnue",
|
||||
"try-again": "Réessayer",
|
||||
"re-login": "Se reconnecter"
|
||||
"re-login": "Se reconnecter",
|
||||
"offline": "Vous n'êtes pas connecté à Internet. Réessayez plus tard."
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user