mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Adding login errors
This commit is contained in:
parent
e5027cf00d
commit
b62b272492
@ -26,14 +26,14 @@ import { QueryClientProvider } from "@tanstack/react-query";
|
||||
import i18next from "i18next";
|
||||
import { Stack } from "expo-router";
|
||||
import { getLocales } from "expo-localization";
|
||||
import * as SplashScreen from "expo-splash-screen";
|
||||
import { SplashScreen } from "expo-router";
|
||||
import {
|
||||
useFonts,
|
||||
Poppins_300Light,
|
||||
Poppins_400Regular,
|
||||
Poppins_900Black,
|
||||
} from "@expo-google-fonts/poppins";
|
||||
import { useCallback, useLayoutEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useColorScheme } from "react-native";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import { useTheme } from "yoshiki/native";
|
||||
@ -75,25 +75,12 @@ const ThemedStack = ({ onLayout }: { onLayout?: () => void }) => {
|
||||
);
|
||||
};
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
|
||||
export default function Root() {
|
||||
const [queryClient] = useState(() => createQueryClient());
|
||||
const theme = useColorScheme();
|
||||
const [fontsLoaded] = useFonts({ Poppins_300Light, Poppins_400Regular, Poppins_900Black });
|
||||
|
||||
useLayoutEffect(() => {
|
||||
// This does not seems to work on the global scope so why not.
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
})
|
||||
|
||||
const onLayout = useCallback(async () => {
|
||||
if (fontsLoaded) {
|
||||
await SplashScreen.hideAsync();
|
||||
}
|
||||
}, [fontsLoaded]);
|
||||
|
||||
if (!fontsLoaded) return null;
|
||||
if (!fontsLoaded) return <SplashScreen />;
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ThemeSelector
|
||||
@ -106,7 +93,7 @@ export default function Root() {
|
||||
}}
|
||||
>
|
||||
<PortalProvider>
|
||||
<ThemedStack onLayout={onLayout} />
|
||||
<ThemedStack />
|
||||
</PortalProvider>
|
||||
</ThemeSelector>
|
||||
</QueryClientProvider>
|
||||
|
@ -18,7 +18,7 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { QueryPage } from "@kyoo/models";
|
||||
import { KyooErrors, kyooUrl, QueryPage } from "@kyoo/models";
|
||||
import { Button, P, Input, ts, H1, A, IconButton } from "@kyoo/primitives";
|
||||
import { ComponentProps, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@ -65,6 +65,32 @@ const PasswordInput = (props: ComponentProps<typeof Input>) => {
|
||||
);
|
||||
};
|
||||
|
||||
const login = async (username: string, password: string) => {
|
||||
let resp;
|
||||
try {
|
||||
resp = await fetch(`${kyooUrl}/auth/login`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username,
|
||||
password,
|
||||
}),
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Login error", e);
|
||||
throw { errors: ["Could not reach Kyoo's server."] } as KyooErrors;
|
||||
}
|
||||
if (!resp.ok) {
|
||||
const err = await resp.json() as KyooErrors;
|
||||
return { type: "error", value: null, error: err.errors[0] };
|
||||
}
|
||||
const token = await resp.json();
|
||||
// TODO: Save the token in the secure storage.
|
||||
return { type: "value", value: token, error: null };
|
||||
};
|
||||
|
||||
export const LoginPage: QueryPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { css } = useYoshiki();
|
||||
@ -78,6 +104,10 @@ export const LoginPage: QueryPage = () => {
|
||||
default: {},
|
||||
});
|
||||
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
return (
|
||||
<ImageBackground
|
||||
source={{ uri: src }}
|
||||
@ -110,12 +140,25 @@ export const LoginPage: QueryPage = () => {
|
||||
<Input variant="big" />
|
||||
</>
|
||||
)}
|
||||
<P {...css({ paddingLeft: ts(1) })}>{t("login.email")}</P>
|
||||
<Input autoComplete="email" variant="big" />
|
||||
<P {...css({ paddingLeft: ts(1) })}>{t("login.username")}</P>
|
||||
<Input
|
||||
autoComplete="username"
|
||||
variant="big"
|
||||
onChangeText={(value) => setUsername(value)}
|
||||
/>
|
||||
<P {...css({ paddingLeft: ts(1) })}>{t("login.password")}</P>
|
||||
<PasswordInput autoComplete="password" variant="big" />
|
||||
<PasswordInput
|
||||
autoComplete="password"
|
||||
variant="big"
|
||||
onChangeText={(value) => setPassword(value)}
|
||||
/>
|
||||
{error && <P {...css({ color: (theme) => theme.colors.red })}>{error}</P>}
|
||||
<Button
|
||||
text={t("login.login")}
|
||||
onPress={async () => {
|
||||
const { error } = await login(username, password);
|
||||
setError(error);
|
||||
}}
|
||||
{...css({
|
||||
m: ts(1),
|
||||
width: px(250),
|
||||
|
@ -55,6 +55,7 @@
|
||||
"register": "Register",
|
||||
"server": "Server Address",
|
||||
"email": "Email",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"or-register": "Don’t have an account? <1>Register</1>."
|
||||
}
|
||||
|
@ -55,6 +55,7 @@
|
||||
"register": "Créer un compte",
|
||||
"server": "Addresse du serveur",
|
||||
"email": "Email",
|
||||
"username": "Username",
|
||||
"password": "Mot de passe",
|
||||
"or-register": "Vous n'avez pas de compte ? <1>Inscrivez-vous</1>."
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user