diff --git a/front/src/providers/account-provider.tsx b/front/src/providers/account-provider.tsx
index 44f033d4..f170b349 100644
--- a/front/src/providers/account-provider.tsx
+++ b/front/src/providers/account-provider.tsx
@@ -1,7 +1,8 @@
-import { type ReactNode, createContext, useEffect, useMemo } from "react";
+import { useQueryClient } from "@tanstack/react-query";
+import { type ReactNode, createContext, useEffect, useMemo, useRef } from "react";
import { Platform } from "react-native";
import { z } from "zod";
-import { type Account, AccountP, type Token, type User, UserP } from "~/models";
+import { type Account, AccountP, type Token, UserP } from "~/models";
import { useFetch } from "~/query";
import { removeAccounts, updateAccount } from "./account-store";
import { useSetError } from "./error-provider";
@@ -9,37 +10,19 @@ import { useStoreValue } from "./settings";
const AccountContext = createContext<{
apiUrl: string;
- authToken: Token;
+ authToken: Token | undefined;
selectedAccount?: Account;
accounts: (Account & { select: () => void; remove: () => void })[];
}>(undefined!);
-export const AccountProvider = ({
- children,
- ssrAccount,
-}: {
- children: ReactNode;
- ssrAccount?: Account;
-}) => {
- if (Platform.OS === "web" && typeof window === "undefined") {
- const accounts = ssrAccount
- ? [{ ...ssrAccount, selected: true, select: () => {}, remove: () => {} }]
- : [];
-
- return (
-
- {children}
-
- );
- }
-
- const setError = useSetError();
+export const AccountProvider = ({ children }: { children: ReactNode }) => {
+ const [setError, clearError] = useSetError("account");
const accounts = useStoreValue("accounts", z.array(AccountP)) ?? [];
const ret = useMemo(() => {
const acc = accounts.find((x) => x.selected);
return {
- apiUrl: Platform.OS === "web" ? "/api" : acc?.apiUrl,
+ apiUrl: Platform.OS === "web" ? "/api" : acc?.apiUrl!,
authToken: acc?.token,
selectedAccount: acc,
accounts: accounts.map((account) => ({
@@ -53,8 +36,6 @@ export const AccountProvider = ({
// update user's data from kyoo on startup, it could have changed.
const {
isSuccess: userIsSuccess,
- isError: userIsError,
- isLoading: userIsLoading,
isPlaceholderData: userIsPlaceholder,
data: user,
error: userError,
@@ -71,8 +52,8 @@ export const AccountProvider = ({
// Use a ref here because we don't want the effect to trigger when the selected
// value has changed, only when the fetch result changed
// If we trigger the effect when the selected value change, we enter an infinite render loop
- const selectedRef = useRef(selected);
- selectedRef.current = selected;
+ const selectedRef = useRef(ret.selectedAccount);
+ selectedRef.current = ret.selectedAccount;
useEffect(() => {
if (!selectedRef.current || !userIsSuccess || userIsPlaceholder) return;
// The id is different when user is stale data, we need to wait for the use effect to invalidate the query.
@@ -81,41 +62,22 @@ export const AccountProvider = ({
updateAccount(nUser.id, nUser);
}, [user, userIsSuccess, userIsPlaceholder]);
+ useEffect(() => {
+ if (!userError) return clearError();
+ setError({
+ error: userError,
+ retry: () => {
+ queryClient.resetQueries();
+ },
+ });
+ }, [userError]);
+
const queryClient = useQueryClient();
- const oldSelected = useRef<{ id: string; token: string } | null>(
- selected ? { id: selected.id, token: selected.token.access_token } : null,
- );
-
- const [permissionError, setPermissionError] = useState(null);
-
+ const selectedId = ret.selectedAccount?.id;
useEffect(() => {
// if the user change account (or connect/disconnect), reset query cache.
- if (
- // biome-ignore lint/suspicious/noDoubleEquals: id can be an id, null or undefined
- selected?.id != oldSelected.current?.id ||
- (userIsError && selected?.token.access_token !== oldSelected.current?.token)
- ) {
- setPermissionError(null);
- queryClient.resetQueries();
- }
- oldSelected.current = selected ? { id: selected.id, token: selected.token.access_token } : null;
-
- // update cookies for ssr (needs to contains token, theme, language...)
- if (Platform.OS === "web") {
- setCookie("account", selected);
- // cookie used for images and videos since we can't add Authorization headers in img or video tags.
- setCookie("X-Bearer", selected?.token.access_token);
- }
- }, [selected, queryClient, userIsError]);
- // {
- // queryClient.invalidateQueries({ queryKey: ["auth", "me"] });
- // },
- // setError: setPermissionError,
- // }}
+ queryClient.resetQueries();
+ }, [selectedId, queryClient]);
return {children};
};
diff --git a/front/src/providers/error-provider.tsx b/front/src/providers/error-provider.tsx
index 04df98ac..1afe794e 100644
--- a/front/src/providers/error-provider.tsx
+++ b/front/src/providers/error-provider.tsx
@@ -37,7 +37,11 @@ export const ErrorConsumer = ({ children, scope }: { children: ReactNode; scope:
const Handler = handler.view;
return ;
};
-export const useSetError = () => {
- const { setError } = useContext(ErrorContext);
- return setError;
+export const useSetError = (key: string) => {
+ const { error, setError } = useContext(ErrorContext);
+ const set = (obj: Omit) => setError({ key, ...obj });
+ const clearError = () => {
+ if (error?.key === key) setError(null);
+ };
+ return [set, clearError] as const;
};