Handle offline mode

This commit is contained in:
Zoe Roux 2023-12-19 18:25:27 +01:00
parent 4a035327ef
commit 022cd239d5
5 changed files with 29 additions and 26 deletions

View File

@ -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

View File

@ -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);

View File

@ -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>
);
};

View File

@ -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."
}
}

View File

@ -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."
}
}