diff --git a/front/src/providers/error-provider.tsx b/front/src/providers/error-provider.tsx new file mode 100644 index 00000000..04df98ac --- /dev/null +++ b/front/src/providers/error-provider.tsx @@ -0,0 +1,43 @@ +import { type ReactNode, createContext, useContext, useState } from "react"; +import type { KyooError } from "~/models"; +import { ErrorView, errorHandlers } from "~/ui/errors"; + +type Error = { + key: string; + error?: KyooError; + retry?: () => void; +}; + +const ErrorContext = createContext<{ + error: Error | null; + setError: (error: Error | null) => void; +}>({ error: null, setError: () => {} }); + +export const ErrorProvider = ({ children }: { children: ReactNode }) => { + const [error, setError] = useState(null); + + return ( + + {children} + + ); +}; + +export const ErrorConsumer = ({ children, scope }: { children: ReactNode; scope: string }) => { + const { error } = useContext(ErrorContext); + if (!error) return children; + + const handler = errorHandlers[error.key] ?? { view: ErrorView }; + if (handler.forbid && handler.forbid !== scope) return children; + const Handler = handler.view; + return ; +}; +export const useSetError = () => { + const { setError } = useContext(ErrorContext); + return setError; +}; diff --git a/front/src/providers.tsx b/front/src/providers/index.tsx similarity index 81% rename from front/src/providers.tsx rename to front/src/providers/index.tsx index 0245254b..ff22dc68 100644 --- a/front/src/providers.tsx +++ b/front/src/providers/index.tsx @@ -1,8 +1,9 @@ import { QueryClientProvider } from "@tanstack/react-query"; import { type ReactNode, useState } from "react"; -import { createQueryClient } from "~/query"; // import { useUserTheme } from "@kyoo/models"; import { ThemeSelector } from "~/primitives/theme"; +import { createQueryClient } from "~/query"; +import { ErrorConsumer, ErrorProvider } from "./error-provider"; const QueryProvider = ({ children }: { children: ReactNode }) => { const [queryClient] = useState(() => createQueryClient()); @@ -23,7 +24,11 @@ const ThemeProvider = ({ children }: { children: ReactNode }) => { export const Providers = ({ children }: { children: ReactNode }) => { return ( - {children} + + + {children} + + ); }; diff --git a/front/src/query/fetch.tsx b/front/src/query/fetch.tsx index 537501d6..3d400714 100644 --- a/front/src/query/fetch.tsx +++ b/front/src/query/fetch.tsx @@ -1,5 +1,6 @@ import type { ReactElement } from "react"; -import { ErrorView, OfflineView } from "~/ui/errors"; +import { useSetError } from "~/providers/error-provider"; +import { ErrorView } from "~/ui/errors"; import { type QueryIdentifier, useFetch } from "./query"; export const Fetch = ({ @@ -12,9 +13,17 @@ export const Fetch = ({ Loader: () => ReactElement; }): JSX.Element | null => { const { data, isPaused, error } = useFetch(query); + const setError = useSetError(); - if (error) return ; - if (isPaused) return ; + if (error) { + if (error.status === 401 || error.status === 403) { + setError({ key: "unauthorized", error }); + } + return ; + } + if (isPaused) { + setError({ key: "offline" }); + } if (!data) return ; return ; }; diff --git a/front/src/ui/errors/connection.tsx b/front/src/ui/errors/connection.tsx index 31902266..a1c1e10f 100644 --- a/front/src/ui/errors/connection.tsx +++ b/front/src/ui/errors/connection.tsx @@ -1,59 +1,20 @@ -import { ConnectionErrorContext, useAccount } from "@kyoo/models"; -import { Button, H1, Icon, Link, P, ts } from "@kyoo/primitives"; -import Register from "@material-symbols/svg-400/rounded/app_registration.svg"; -import { useContext } from "react"; import { useTranslation } from "react-i18next"; import { View } from "react-native"; -import { useRouter } from "solito/router"; import { useYoshiki } from "yoshiki/native"; -import { DefaultLayout } from "../../../packages/ui/src/layout"; +import type { KyooError } from "~/models"; +import { Button, H1, Link, P, ts } from "~/primitives"; -export const ConnectionError = () => { +export const ConnectionError = ({ error, retry }: { error: KyooError; retry: () => void }) => { const { css } = useYoshiki(); const { t } = useTranslation(); - const router = useRouter(); - const { error, retry } = useContext(ConnectionErrorContext); - const account = useAccount(); - if (error && (error.status === 401 || error.status === 403)) { - if (!account) { - return ( - -

{t("errors.needAccount")}

-