mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Finish account provider cleanup
This commit is contained in:
parent
ea7cb8b4d1
commit
7ee6c2e666
@ -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 { Platform } from "react-native";
|
||||||
import { z } from "zod";
|
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 { useFetch } from "~/query";
|
||||||
import { removeAccounts, updateAccount } from "./account-store";
|
import { removeAccounts, updateAccount } from "./account-store";
|
||||||
import { useSetError } from "./error-provider";
|
import { useSetError } from "./error-provider";
|
||||||
@ -9,37 +10,19 @@ import { useStoreValue } from "./settings";
|
|||||||
|
|
||||||
const AccountContext = createContext<{
|
const AccountContext = createContext<{
|
||||||
apiUrl: string;
|
apiUrl: string;
|
||||||
authToken: Token;
|
authToken: Token | undefined;
|
||||||
selectedAccount?: Account;
|
selectedAccount?: Account;
|
||||||
accounts: (Account & { select: () => void; remove: () => void })[];
|
accounts: (Account & { select: () => void; remove: () => void })[];
|
||||||
}>(undefined!);
|
}>(undefined!);
|
||||||
|
|
||||||
export const AccountProvider = ({
|
export const AccountProvider = ({ children }: { children: ReactNode }) => {
|
||||||
children,
|
const [setError, clearError] = useSetError("account");
|
||||||
ssrAccount,
|
|
||||||
}: {
|
|
||||||
children: ReactNode;
|
|
||||||
ssrAccount?: Account;
|
|
||||||
}) => {
|
|
||||||
if (Platform.OS === "web" && typeof window === "undefined") {
|
|
||||||
const accounts = ssrAccount
|
|
||||||
? [{ ...ssrAccount, selected: true, select: () => {}, remove: () => {} }]
|
|
||||||
: [];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AccountContext.Provider value={{ ...ssrAccount, accounts }}>
|
|
||||||
{children}
|
|
||||||
</AccountContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const setError = useSetError();
|
|
||||||
const accounts = useStoreValue("accounts", z.array(AccountP)) ?? [];
|
const accounts = useStoreValue("accounts", z.array(AccountP)) ?? [];
|
||||||
|
|
||||||
const ret = useMemo(() => {
|
const ret = useMemo(() => {
|
||||||
const acc = accounts.find((x) => x.selected);
|
const acc = accounts.find((x) => x.selected);
|
||||||
return {
|
return {
|
||||||
apiUrl: Platform.OS === "web" ? "/api" : acc?.apiUrl,
|
apiUrl: Platform.OS === "web" ? "/api" : acc?.apiUrl!,
|
||||||
authToken: acc?.token,
|
authToken: acc?.token,
|
||||||
selectedAccount: acc,
|
selectedAccount: acc,
|
||||||
accounts: accounts.map((account) => ({
|
accounts: accounts.map((account) => ({
|
||||||
@ -53,8 +36,6 @@ export const AccountProvider = ({
|
|||||||
// update user's data from kyoo on startup, it could have changed.
|
// update user's data from kyoo on startup, it could have changed.
|
||||||
const {
|
const {
|
||||||
isSuccess: userIsSuccess,
|
isSuccess: userIsSuccess,
|
||||||
isError: userIsError,
|
|
||||||
isLoading: userIsLoading,
|
|
||||||
isPlaceholderData: userIsPlaceholder,
|
isPlaceholderData: userIsPlaceholder,
|
||||||
data: user,
|
data: user,
|
||||||
error: userError,
|
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
|
// 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
|
// 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
|
// If we trigger the effect when the selected value change, we enter an infinite render loop
|
||||||
const selectedRef = useRef(selected);
|
const selectedRef = useRef(ret.selectedAccount);
|
||||||
selectedRef.current = selected;
|
selectedRef.current = ret.selectedAccount;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedRef.current || !userIsSuccess || userIsPlaceholder) return;
|
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.
|
// 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);
|
updateAccount(nUser.id, nUser);
|
||||||
}, [user, userIsSuccess, userIsPlaceholder]);
|
}, [user, userIsSuccess, userIsPlaceholder]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!userError) return clearError();
|
||||||
|
setError({
|
||||||
|
error: userError,
|
||||||
|
retry: () => {
|
||||||
|
queryClient.resetQueries();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, [userError]);
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const oldSelected = useRef<{ id: string; token: string } | null>(
|
const selectedId = ret.selectedAccount?.id;
|
||||||
selected ? { id: selected.id, token: selected.token.access_token } : null,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [permissionError, setPermissionError] = useState<KyooErrors | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if the user change account (or connect/disconnect), reset query cache.
|
// if the user change account (or connect/disconnect), reset query cache.
|
||||||
if (
|
queryClient.resetQueries();
|
||||||
// biome-ignore lint/suspicious/noDoubleEquals: id can be an id, null or undefined
|
}, [selectedId, queryClient]);
|
||||||
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]);
|
|
||||||
// <ConnectionErrorContext.Provider
|
|
||||||
// value={{
|
|
||||||
// error: (selected ? (userError) : null) ?? permissionError,
|
|
||||||
// loading: userIsLoading,
|
|
||||||
// retry: () => {
|
|
||||||
// queryClient.invalidateQueries({ queryKey: ["auth", "me"] });
|
|
||||||
// },
|
|
||||||
// setError: setPermissionError,
|
|
||||||
// }}
|
|
||||||
|
|
||||||
return <AccountContext.Provider value={ret}>{children}</AccountContext.Provider>;
|
return <AccountContext.Provider value={ret}>{children}</AccountContext.Provider>;
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,11 @@ export const ErrorConsumer = ({ children, scope }: { children: ReactNode; scope:
|
|||||||
const Handler = handler.view;
|
const Handler = handler.view;
|
||||||
return <Handler {...(error as any)} />;
|
return <Handler {...(error as any)} />;
|
||||||
};
|
};
|
||||||
export const useSetError = () => {
|
export const useSetError = (key: string) => {
|
||||||
const { setError } = useContext(ErrorContext);
|
const { error, setError } = useContext(ErrorContext);
|
||||||
return setError;
|
const set = (obj: Omit<Error, "key">) => setError({ key, ...obj });
|
||||||
|
const clearError = () => {
|
||||||
|
if (error?.key === key) setError(null);
|
||||||
|
};
|
||||||
|
return [set, clearError] as const;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user