Start server url selector page for native

This commit is contained in:
Zoe Roux 2024-03-04 23:44:56 +01:00
parent f4464578c0
commit df6f9ea71d
11 changed files with 132 additions and 27 deletions

View File

@ -59,7 +59,7 @@ namespace Kyoo.Tests.Database
SeasonRepository season = new(_NewContext(), thumbs.Object);
LibraryItemRepository libraryItem = new(_NewConnection(), new(null));
EpisodeRepository episode = new(_NewContext(), show, thumbs.Object);
UserRepository user = new(_NewContext(), thumbs.Object);
UserRepository user = new(_NewContext(), _NewConnection(), new(null), thumbs.Object);
_repositories = new IBaseRepository[]
{

View File

@ -35,7 +35,7 @@ export default function SignGuard() {
const netInfo = useNetInfo();
if (error && netInfo.isConnected) return <Redirect href={"/connection-error"} />;
if (!account) return <Redirect href="/login" />;
if (!account) return <Redirect href="/server-url" />;
return (
<Stack
screenOptions={{

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
import { ServerUrlPage } from "@kyoo/ui";
export default ServerUrlPage;

View File

@ -25,7 +25,7 @@ export { MovieDetails, ShowDetails } from "./details";
export { CollectionPage } from "./collection";
export { Player } from "./player";
export { SearchPage } from "./search";
export { LoginPage, RegisterPage, OidcCallbackPage } from "./login";
export { ServerUrlPage, LoginPage, RegisterPage, OidcCallbackPage } from "./login";
export { DownloadPage, DownloadProvider } from "./downloads";
export { SettingsPage } from "./settings";
export { AdminPage } from "./admin";

View File

@ -20,4 +20,5 @@
export { LoginPage } from "./login";
export { RegisterPage } from "./register";
export { ServerUrlPage } from "./server-url";
export { OidcCallbackPage } from "./oidc";

View File

@ -31,15 +31,7 @@ import { FormPage } from "./form";
import { PasswordInput } from "./password-input";
import { OidcLogin } from "./oidc";
export const cleanApiUrl = (apiUrl: string) => {
if (Platform.OS === "web") return undefined;
if (!/https?:\/\//.test(apiUrl)) apiUrl = "http://" + apiUrl;
apiUrl = apiUrl.replace(/\/$/, "");
return apiUrl + "/api";
};
export const LoginPage: QueryPage<{ error?: string }> = ({ error: initialError }) => {
const [apiUrl, setApiUrl] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | undefined>(initialError);
@ -49,19 +41,9 @@ export const LoginPage: QueryPage<{ error?: string }> = ({ error: initialError }
const { css } = useYoshiki();
return (
<FormPage
{...css({
marginTop: Platform.OS === "web" ? ts(6) : 0,
})}
>
<FormPage>
<H1>{t("login.login")}</H1>
<OidcLogin />
{Platform.OS !== "web" && (
<>
<P {...css({ paddingLeft: ts(1) })}>{t("login.server")}</P>
<Input variant="big" onChangeText={setApiUrl} />
</>
)}
<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>

View File

@ -19,7 +19,6 @@
*/
import {
KyooErrors,
QueryIdentifier,
QueryPage,
ServerInfo,
@ -31,7 +30,7 @@ import { Button, HR, P, Skeleton, ts } from "@kyoo/primitives";
import { View, ImageBackground } from "react-native";
import { percent, rem, useYoshiki } from "yoshiki/native";
import { useTranslation } from "react-i18next";
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef } from "react";
import { useRouter } from "solito/router";
import { ErrorView } from "../errors";

View File

@ -29,11 +29,9 @@ import { percent, px, useYoshiki } from "yoshiki/native";
import { DefaultLayout } from "../layout";
import { FormPage } from "./form";
import { PasswordInput } from "./password-input";
import { cleanApiUrl } from "./login";
import { OidcLogin } from "./oidc";
export const RegisterPage: QueryPage = () => {
const [apiUrl, setApiUrl] = useState("");
const [email, setEmail] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
@ -86,7 +84,6 @@ export const RegisterPage: QueryPage = () => {
const { error } = await login(
"register",
{ email, username, password, apiUrl: cleanApiUrl(apiUrl) },
5_000,
);
setError(error);
if (error) return;

View File

@ -0,0 +1,101 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { QueryIdentifier, QueryPage, ServerInfo, ServerInfoP, useFetch } from "@kyoo/models";
import { Button, P, Input, ts, H1, HR } from "@kyoo/primitives";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { Platform, View } from "react-native";
import { useRouter } from "solito/router";
import { Theme, useYoshiki } from "yoshiki/native";
import { DefaultLayout } from "../layout";
export const cleanApiUrl = (apiUrl: string) => {
if (Platform.OS === "web") return undefined;
if (!/https?:\/\//.test(apiUrl)) apiUrl = "http://" + apiUrl;
apiUrl = apiUrl.replace(/\/$/, "");
return apiUrl + "/api";
};
const query: QueryIdentifier<ServerInfo> = {
path: ["info"],
parser: ServerInfoP,
};
export const ServerUrlPage: QueryPage = () => {
const [apiUrl, setApiUrl] = useState("");
const { data, error } = useFetch(query);
const router = useRouter();
const { t } = useTranslation();
const { css } = useYoshiki();
return (
<View
{...css({
marginX: ts(3),
justifyContent: "space-between",
flexGrow: 1,
})}
>
<H1>{t("login.server")}</H1>
<View {...css({ justifyContent: "center" })}>
<Input variant="big" onChangeText={setApiUrl} />
{error && (
<P {...css({ color: (theme: Theme) => theme.colors.red, alignSelf: "center" })}>
{error.errors[0]}
</P>
)}
</View>
<View {...css({ marginTop: ts(5) })}>
<Button
text={t("login.guest")}
onPress={() => {}}
disabled={error != null || data?.allowGuests != true}
/>
<HR />
<View {...css({ flexDirection: "row", gap: ts(2) })}>
<Button
text={t("login.login")}
onPress={async () => {
router.replace(`/login?apiUrl=${apiUrl}`, undefined, {
experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false },
});
}}
disabled={error != null}
{...css({ flexGrow: 1, flexShrink: 1 })}
/>
<Button
text={t("login.register")}
onPress={async () => {
router.replace(`/register?apiUrl=${apiUrl}`, undefined, {
experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false },
});
}}
disabled={error != null}
{...css({ flexGrow: 1, flexShrink: 1 })}
/>
</View>
</View>
<View />
</View>
);
};
ServerUrlPage.getLayout = DefaultLayout;

View File

@ -166,6 +166,7 @@
"login": {
"login": "Login",
"register": "Register",
"guest": "Continue as guest",
"via": "Continue with {{provider}}",
"add-account": "Add account",
"logout": "Logout",

View File

@ -167,6 +167,7 @@
"login": "Connexion",
"via": "Continuer avec {{provider}}",
"register": "Créer un compte",
"guest": "Continuer en tant qu'invité",
"add-account": "Ajouter un compte",
"logout": "Déconnexion",
"server": "Addresse du serveur",