diff --git a/front/packages/models/src/accounts.tsx b/front/packages/models/src/accounts.tsx new file mode 100644 index 00000000..327ed0fe --- /dev/null +++ b/front/packages/models/src/accounts.tsx @@ -0,0 +1,85 @@ +/* + * Kyoo - A portable and vast media library solution. + * Copyright (c) Kyoo. + * + * See AUTHORS.md and LICENSE file in the project root for full license information. + * + * Kyoo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Kyoo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kyoo. If not, see . + */ + +import { getSecureItem, setSecureItem, storage } from "./secure-store"; +import { setApiUrl } from "./query"; +import { createContext, useEffect, useState } from "react"; +import { useMMKVListener } from "react-native-mmkv"; +import { Account, loginFunc } from "./login"; + +export const AccountContext = createContext>({ type: "loading" }); + +export const useAccounts = () => { + const [accounts, setAccounts] = useState(JSON.parse(getSecureItem("accounts") ?? "[]")); + const [verified, setVerified] = useState<{ + status: "ok" | "error" | "loading" | "unverified"; + error?: string; + }>({ status: "loading" }); + const [retryCount, setRetryCount] = useState(0); + + const sel = getSecureItem("selected"); + let [selected, setSelected] = useState( + sel ? parseInt(sel) : accounts.length > 0 ? 0 : null, + ); + if (selected === null && accounts.length > 0) selected = 0; + if (accounts.length === 0) selected = null; + + useEffect(() => { + async function check() { + setVerified({status: "loading"}); + const selAcc = accounts![selected!]; + setApiUrl(selAcc.apiUrl); + const verif = await loginFunc("refresh", selAcc.refresh_token); + setVerified(verif.ok ? { status: "ok" } : { status: "error", error: verif.error }); + } + + if (accounts.length && selected !== null) check(); + else setVerified({ status: "unverified" }); + // Use the length of the array and not the array directly because we don't care if the refresh token changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [accounts.length, selected, retryCount]); + + useMMKVListener((key) => { + if (key === "accounts") setAccounts(JSON.parse(getSecureItem("accounts") ?? "[]")); + }, storage); + + if (verified.status === "loading") return { type: "loading" } as const; + if (accounts.length && verified.status === "unverified") return { type: "loading" } as const; + if (verified.status === "error") { + return { + type: "error", + error: verified.error, + retry: () => { + setVerified({ status: "loading" }); + setRetryCount((x) => x + 1); + }, + } as const; + } + return { + type: "ok", + accounts, + selected, + setSelected: (selected: number) => { + setSelected(selected); + setSecureItem("selected", selected.toString()); + }, + } as const; +}; + diff --git a/front/packages/models/src/accounts.web.ts b/front/packages/models/src/accounts.web.ts new file mode 100644 index 00000000..a2111fdf --- /dev/null +++ b/front/packages/models/src/accounts.web.ts @@ -0,0 +1,23 @@ +/* + * Kyoo - A portable and vast media library solution. + * Copyright (c) Kyoo. + * + * See AUTHORS.md and LICENSE file in the project root for full license information. + * + * Kyoo is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Kyoo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kyoo. If not, see . + */ + +export const useAccounts = () => {} + +export const AccountContext = 0; diff --git a/front/packages/models/src/index.ts b/front/packages/models/src/index.ts index 337d2c57..cfbd8dbe 100644 --- a/front/packages/models/src/index.ts +++ b/front/packages/models/src/index.ts @@ -18,6 +18,7 @@ * along with Kyoo. If not, see . */ +export * from "./accounts"; export * from "./resources"; export * from "./traits"; export * from "./page"; diff --git a/front/packages/models/src/login.ts b/front/packages/models/src/login.ts index 595c3835..4e457ff1 100644 --- a/front/packages/models/src/login.ts +++ b/front/packages/models/src/login.ts @@ -19,13 +19,11 @@ */ import { z } from "zod"; -import { deleteSecureItem, getSecureItem, setSecureItem, storage } from "./secure-store"; +import { deleteSecureItem, getSecureItem, setSecureItem } from "./secure-store"; import { zdate } from "./utils"; -import { queryFn, setApiUrl } from "./query"; +import { queryFn } from "./query"; import { KyooErrors } from "./kyoo-errors"; import { Platform } from "react-native"; -import { createContext, useEffect, useState } from "react"; -import { useMMKVListener } from "react-native-mmkv"; const TokenP = z.object({ token_type: z.literal("Bearer"), @@ -42,65 +40,6 @@ type Result = export type Account = Token & { apiUrl: string; username: string }; -export const AccountContext = createContext>({ type: "loading" }); - -export const useAccounts = () => { - const [accounts, setAccounts] = useState(JSON.parse(getSecureItem("accounts") ?? "[]")); - const [verified, setVerified] = useState<{ - status: "ok" | "error" | "loading" | "unverified"; - error?: string; - }>({ status: "loading" }); - const [retryCount, setRetryCount] = useState(0); - - const sel = getSecureItem("selected"); - let [selected, setSelected] = useState( - sel ? parseInt(sel) : accounts.length > 0 ? 0 : null, - ); - if (selected === null && accounts.length > 0) selected = 0; - if (accounts.length === 0) selected = null; - - useEffect(() => { - async function check() { - setVerified({status: "loading"}); - const selAcc = accounts![selected!]; - setApiUrl(selAcc.apiUrl); - const verif = await loginFunc("refresh", selAcc.refresh_token); - setVerified(verif.ok ? { status: "ok" } : { status: "error", error: verif.error }); - } - - if (accounts.length && selected !== null) check(); - else setVerified({ status: "unverified" }); - // Use the length of the array and not the array directly because we don't care if the refresh token changes. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [accounts.length, selected, retryCount]); - - useMMKVListener((key) => { - if (key === "accounts") setAccounts(JSON.parse(getSecureItem("accounts") ?? "[]")); - }, storage); - - if (verified.status === "loading") return { type: "loading" } as const; - if (accounts.length && verified.status === "unverified") return { type: "loading" } as const; - if (verified.status === "error") { - return { - type: "error", - error: verified.error, - retry: () => { - setVerified({ status: "loading" }); - setRetryCount((x) => x + 1); - }, - } as const; - } - return { - type: "ok", - accounts, - selected, - setSelected: (selected: number) => { - setSelected(selected); - setSecureItem("selected", selected.toString()); - }, - } as const; -}; - const addAccount = (token: Token, apiUrl: string, username: string | null) => { const accounts: Account[] = JSON.parse(getSecureItem("accounts") ?? "[]"); if (accounts.find((x) => x.username === username && x.apiUrl === apiUrl)) return;