Add setup page componant

This commit is contained in:
Zoe Roux 2024-05-26 02:05:23 +02:00
parent db2204258a
commit 97e3257aee
No known key found for this signature in database
7 changed files with 93 additions and 15 deletions

View File

@ -50,7 +50,7 @@ public class InfoApi(PermissionOption options, MiscRepository info) : Controller
new() { DisplayName = x.Value.DisplayName, LogoUrl = x.Value.LogoUrl, } new() { DisplayName = x.Value.DisplayName, LogoUrl = x.Value.LogoUrl, }
)) ))
.ToDictionary(x => x.Key, x => x.Value), .ToDictionary(x => x.Key, x => x.Value),
SetupStatus = await info.GetSetupStep() SetupStatus = await info.GetSetupStep(),
} }
); );
} }

View File

@ -0,0 +1,24 @@
/*
* 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 { SetupPage } from "@kyoo/ui";
import { withRoute } from "~/router";
export default withRoute(SetupPage);

View File

@ -33,6 +33,12 @@ export const OidcInfoP = z.object({
logoUrl: z.string().nullable(), logoUrl: z.string().nullable(),
}); });
export enum SetupStep {
MissingAdminAccount = "MissingAdminAccount",
NoVideoFound = "NoVideoFound",
Done = "Done",
}
export const ServerInfoP = z export const ServerInfoP = z
.object({ .object({
/* /*
@ -51,6 +57,10 @@ export const ServerInfoP = z
* The list of oidc providers configured for this instance of kyoo. * The list of oidc providers configured for this instance of kyoo.
*/ */
oidc: z.record(z.string(), OidcInfoP), oidc: z.record(z.string(), OidcInfoP),
/*
* Check if kyoo's setup is finished.
*/
setupStatus: z.nativeEnum(SetupStep),
}) })
.transform((x) => { .transform((x) => {
const baseUrl = Platform.OS === "web" ? x.publicUrl : "kyoo://"; const baseUrl = Platform.OS === "web" ? x.publicUrl : "kyoo://";

View File

@ -21,3 +21,4 @@
export * from "./error"; export * from "./error";
export * from "./unauthorized"; export * from "./unauthorized";
export * from "./connection"; export * from "./connection";
export * from "./setup";

View File

@ -0,0 +1,31 @@
import { SetupStep, type QueryPage } from "@kyoo/models";
import { Button, Icon, Link, P, ts } from "@kyoo/primitives";
import { useTranslation } from "react-i18next";
import { Main } from "@expo/html-elements";
import { useYoshiki } from "yoshiki/native";
import Register from "@material-symbols/svg-400/rounded/app_registration.svg";
import { Navbar, NavbarProfile } from "../navbar";
export const SetupPage: QueryPage<{ step: Exclude<SetupStep, SetupStep.Done> }> = ({ step }) => {
const { css } = useYoshiki();
const { t } = useTranslation();
return (
<>
<Navbar left={null} right={<NavbarProfile />} />
<Main
{...css({ flexGrow: 1, flexShrink: 1, justifyContent: "center", alignItems: "center" })}
>
<P>{t(`errors.setup.${step}`)}</P>
{step === SetupStep.MissingAdminAccount && (
<Button
as={Link}
href={"/register"}
text={t("login.register")}
licon={<Icon icon={Register} {...css({ marginRight: ts(2) })} />}
/>
)}
</Main>
</>
);
};

View File

@ -38,7 +38,7 @@ import Login from "@material-symbols/svg-400/rounded/login.svg";
import Logout from "@material-symbols/svg-400/rounded/logout.svg"; import Logout from "@material-symbols/svg-400/rounded/logout.svg";
import Search from "@material-symbols/svg-400/rounded/search-fill.svg"; import Search from "@material-symbols/svg-400/rounded/search-fill.svg";
import Settings from "@material-symbols/svg-400/rounded/settings.svg"; import Settings from "@material-symbols/svg-400/rounded/settings.svg";
import { forwardRef, useEffect, useRef, useState } from "react"; import { ReactElement, forwardRef, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Platform, type TextInput, View, type ViewProps } from "react-native"; import { Platform, type TextInput, View, type ViewProps } from "react-native";
import { useRouter } from "solito/router"; import { useRouter } from "solito/router";
@ -168,7 +168,11 @@ export const NavbarRight = () => {
); );
}; };
export const Navbar = (props: Stylable) => { export const Navbar = ({
left,
right,
...props
}: { left?: ReactElement | null; right?: ReactElement | null }) => {
const { css } = useYoshiki(); const { css } = useYoshiki();
const { t } = useTranslation(); const { t } = useTranslation();
@ -197,16 +201,20 @@ export const Navbar = (props: Stylable) => {
> >
<View {...css({ flexDirection: "row", alignItems: "center" })}> <View {...css({ flexDirection: "row", alignItems: "center" })}>
<NavbarTitle {...css({ marginX: ts(2) })} /> <NavbarTitle {...css({ marginX: ts(2) })} />
<A {left !== undefined ? (
href="/browse" left
{...css({ ) : (
textTransform: "uppercase", <A
fontWeight: "bold", href="/browse"
color: (theme) => theme.contrast, {...css({
})} textTransform: "uppercase",
> fontWeight: "bold",
{t("navbar.browse")} color: (theme) => theme.contrast,
</A> })}
>
{t("navbar.browse")}
</A>
)}
</View> </View>
<View <View
{...css({ {...css({
@ -217,7 +225,7 @@ export const Navbar = (props: Stylable) => {
marginX: ts(2), marginX: ts(2),
})} })}
/> />
<NavbarRight /> {right !== undefined ? right : <NavbarRight />}
</Header> </Header>
); );
}; };

View File

@ -237,7 +237,11 @@
"offline": "You are not connected to internet. Try again later.", "offline": "You are not connected to internet. Try again later.",
"unauthorized": "You are missing the permissions {{permission}} to access this page.", "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.", "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." "needAccount": "This page can't be accessed in guest mode. You need to create an account or login.",
"setup": {
"MissingAdminAccount": "No admin account has been created yet. Please register to create one.",
"NoVideoFound": "No video was found yet. Add movies or series inside your library's folder for them to show here!"
}
}, },
"mediainfo": { "mediainfo": {
"file": "File", "file": "File",