From 1e17f75aafee2aad053798bfc9773e54db78d200 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 10 Feb 2026 17:42:56 +0100 Subject: [PATCH] Sent native users to server url screen --- front/public/translations/en.json | 1 + front/src/primitives/links.tsx | 4 +- front/src/providers/account-provider.tsx | 20 ++++++- front/src/providers/index.tsx | 8 +-- front/src/query/query.tsx | 24 +++++---- front/src/ui/login/form.tsx | 68 +++++++++++------------- front/src/ui/login/login.tsx | 27 +++------- front/src/ui/login/password-input.tsx | 4 -- front/src/ui/login/register.tsx | 40 ++++---------- front/src/ui/login/server-url.tsx | 58 +++++--------------- 10 files changed, 98 insertions(+), 156 deletions(-) diff --git a/front/public/translations/en.json b/front/public/translations/en.json index 62f7899a..84fc33c2 100644 --- a/front/public/translations/en.json +++ b/front/public/translations/en.json @@ -246,6 +246,7 @@ "try-again": "Try again", "re-login": "Re login", "offline": "You are not connected to internet. Try again later.", + "invalid-server": "Could not reach kyoo's server.", "unauthorized": "You are missing the permissions {{permission}} to access this page.", "needVerification": "Your account needs to be verified by your server administrator before you can use it.", "needAccount": "This page can't be accessed in guest mode. You need to create an account or login.", diff --git a/front/src/primitives/links.tsx b/front/src/primitives/links.tsx index 9c606a41..8d2a2ff1 100644 --- a/front/src/primitives/links.tsx +++ b/front/src/primitives/links.tsx @@ -8,10 +8,8 @@ import { Text, type TextProps, } from "react-native"; -import { useTheme } from "yoshiki/native"; -import { cn } from "~/utils"; -import { alpha } from "./theme"; import { useResolveClassNames } from "uniwind"; +import { cn } from "~/utils"; export function useLinkTo({ href, diff --git a/front/src/providers/account-provider.tsx b/front/src/providers/account-provider.tsx index 0d4e099a..602e3cf6 100644 --- a/front/src/providers/account-provider.tsx +++ b/front/src/providers/account-provider.tsx @@ -1,5 +1,7 @@ import { useQueryClient } from "@tanstack/react-query"; +import { useRouter } from "expo-router"; import { type ReactNode, useEffect, useMemo, useRef } from "react"; +import { Platform } from "react-native"; import { z } from "zod/v4"; import { Account, User } from "~/models"; import { RetryableError } from "~/models/retryable-error"; @@ -11,10 +13,11 @@ import { useStoreValue } from "./settings"; export const defaultApiUrl = ""; export const AccountProvider = ({ children }: { children: ReactNode }) => { + const queryClient = useQueryClient(); const accounts = useStoreValue("accounts", z.array(Account)) ?? []; const ret = useMemo(() => { - const acc = accounts.find((x) => x.selected); + const acc = accounts.find((x) => x.selected) ?? accounts[0]; return { apiUrl: acc?.apiUrl ?? defaultApiUrl, authToken: acc?.token ?? null, @@ -27,6 +30,20 @@ export const AccountProvider = ({ children }: { children: ReactNode }) => { }; }, [accounts]); + if (Platform.OS !== "web") { + // biome-ignore lint/correctness/useHookAtTopLevel: static + const router = useRouter(); + // biome-ignore lint/correctness/useHookAtTopLevel: static + useEffect(() => { + if (!ret.apiUrl) { + setTimeout(() => { + console.log("go to login"); + router.replace("/login"); + }, 0); + } + }, [ret.apiUrl, router]); + } + // update user's data from kyoo on startup, it could have changed. const { isSuccess: userIsSuccess, @@ -62,7 +79,6 @@ export const AccountProvider = ({ children }: { children: ReactNode }) => { updateAccount(nUser.id, nUser); }, [user, userIsSuccess, userIsPlaceholder]); - const queryClient = useQueryClient(); const selectedId = ret.selectedAccount?.id; useEffect(() => { selectedId; diff --git a/front/src/providers/index.tsx b/front/src/providers/index.tsx index d6d986e2..4aa3a76e 100644 --- a/front/src/providers/index.tsx +++ b/front/src/providers/index.tsx @@ -83,11 +83,11 @@ export const Providers = ({ children }: { children: ReactNode }) => { - - + + {children} - - + + diff --git a/front/src/query/query.tsx b/front/src/query/query.tsx index 347a58ff..67deca0e 100644 --- a/front/src/query/query.tsx +++ b/front/src/query/query.tsx @@ -59,10 +59,9 @@ export const queryFn = async (context: { if (typeof e === "object" && e && "name" in e && e.name === "AbortError") throw { message: "Aborted", status: "aborted" } as KyooError; console.log("Fetch error", e, context.url); - throw { - message: "Could not reach Kyoo's server.", - status: "aborted", - } as KyooError; + throw new RetryableError({ + key: "offline", + }); } if (resp.status === 404) { throw { message: "Resource not found.", status: 404 } as KyooError; @@ -144,6 +143,7 @@ export type QueryIdentifier = { enabled?: boolean; options?: Partial[0]> & { apiUrl?: string; + returnError?: boolean; }; }; @@ -189,14 +189,16 @@ export const useFetch = (query: QueryIdentifier) => { enabled: query.enabled, }); - if (ret.isPaused) throw new RetryableError({ key: "offline" }); - if (ret.error && (ret.error.status === 401 || ret.error.status === 403)) { - throw new RetryableError({ - key: !selectedAccount ? "needAccount" : "unauthorized", - inner: ret.error, - }); + if (query.options?.returnError !== true) { + if (ret.isPaused) throw new RetryableError({ key: "offline" }); + if (ret.error && (ret.error.status === 401 || ret.error.status === 403)) { + throw new RetryableError({ + key: !selectedAccount ? "needAccount" : "unauthorized", + inner: ret.error, + }); + } + if (ret.error) throw ret.error; } - if (ret.error) throw ret.error; return ret; }; diff --git a/front/src/ui/login/form.tsx b/front/src/ui/login/form.tsx index f4b50de7..cefc078c 100644 --- a/front/src/ui/login/form.tsx +++ b/front/src/ui/login/form.tsx @@ -1,20 +1,25 @@ import type { ReactNode } from "react"; -import { ImageBackground, ScrollView, View } from "react-native"; -import Svg, { Path, type SvgProps } from "react-native-svg"; -import { min, px, type Stylable, useYoshiki, vh } from "yoshiki/native"; -import { ts } from "~/primitives"; +import { + ImageBackground, + ScrollView, + View, + type ViewProps, +} from "react-native"; +import { Path } from "react-native-svg"; +import { Svg } from "~/primitives"; import { defaultApiUrl } from "~/providers/account-provider"; +import { cn } from "~/utils"; -const SvgBlob = (props: SvgProps) => { - const { css, theme } = useYoshiki(); - +const SvgBlob = ({ className, ...props }: ViewProps) => { return ( - - - + + + ); @@ -23,37 +28,26 @@ const SvgBlob = (props: SvgProps) => { export const FormPage = ({ children, apiUrl, + className, ...props -}: { children: ReactNode; apiUrl?: string } & Stylable) => { - const { css } = useYoshiki(); - +}: { + children: ReactNode; + apiUrl?: string; + className?: string; +}) => { return ( theme.dark.background, - })} + className="flex-1 flex-row bg-dark" > - - + + theme.background, - borderBottomRightRadius: ts(25), - paddingBottom: ts(5), - paddingLeft: ts(3), - }, - props, + className={cn( + "max-w-xl rounded-[25rem] bg-background py-10 pl-6", + className, )} + {...props} > {children} diff --git a/front/src/ui/login/login.tsx b/front/src/ui/login/login.tsx index abcbc1a3..5ba11cda 100644 --- a/front/src/ui/login/login.tsx +++ b/front/src/ui/login/login.tsx @@ -2,8 +2,7 @@ import { useRouter } from "expo-router"; import { useState } from "react"; import { Trans, useTranslation } from "react-i18next"; import { Platform } from "react-native"; -import { percent, px, useYoshiki } from "yoshiki/native"; -import { A, Button, H1, Input, P, ts } from "~/primitives"; +import { A, Button, H1, Input, P } from "~/primitives"; import { defaultApiUrl } from "~/providers/account-provider"; import { useQueryState } from "~/utils"; import { FormPage } from "./form"; @@ -18,31 +17,25 @@ export const LoginPage = () => { const [error, setError] = useState(); const { t } = useTranslation(); - const { css } = useYoshiki(); const router = useRouter(); if (Platform.OS !== "web" && !apiUrl) return ; return ( -

{t("login.login")}

- {/* */} - {/* {data?.passwordLoginEnabled && ( */} - {/* <> */} -

{t("login.username")}

+

{t("login.login")}

+

{t("login.username")}

setUsername(value)} autoCapitalize="none" /> -

{t("login.password")}

+

{t("login.password")}

setPassword(value)} /> - {error &&

theme.colors.red })}>{error}

} + {error &&

{error}

}