diff --git a/back/src/Kyoo.Core/Views/InfoApi.cs b/back/src/Kyoo.Core/Views/InfoApi.cs index 113e32f2..48cd132d 100644 --- a/back/src/Kyoo.Core/Views/InfoApi.cs +++ b/back/src/Kyoo.Core/Views/InfoApi.cs @@ -50,7 +50,7 @@ public class InfoApi(PermissionOption options, MiscRepository info) : Controller new() { DisplayName = x.Value.DisplayName, LogoUrl = x.Value.LogoUrl, } )) .ToDictionary(x => x.Key, x => x.Value), - SetupStatus = await info.GetSetupStep() + SetupStatus = await info.GetSetupStep(), } ); } diff --git a/front/apps/web/src/pages/setup/index.tsx b/front/apps/web/src/pages/setup/index.tsx new file mode 100644 index 00000000..022e242e --- /dev/null +++ b/front/apps/web/src/pages/setup/index.tsx @@ -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 . + */ + +import { SetupPage } from "@kyoo/ui"; +import { withRoute } from "~/router"; + +export default withRoute(SetupPage); diff --git a/front/packages/models/src/resources/server-info.ts b/front/packages/models/src/resources/server-info.ts index 370ba6d2..05fa90e6 100644 --- a/front/packages/models/src/resources/server-info.ts +++ b/front/packages/models/src/resources/server-info.ts @@ -33,6 +33,12 @@ export const OidcInfoP = z.object({ logoUrl: z.string().nullable(), }); +export enum SetupStep { + MissingAdminAccount = "MissingAdminAccount", + NoVideoFound = "NoVideoFound", + Done = "Done", +} + export const ServerInfoP = z .object({ /* @@ -51,6 +57,10 @@ export const ServerInfoP = z * The list of oidc providers configured for this instance of kyoo. */ oidc: z.record(z.string(), OidcInfoP), + /* + * Check if kyoo's setup is finished. + */ + setupStatus: z.nativeEnum(SetupStep), }) .transform((x) => { const baseUrl = Platform.OS === "web" ? x.publicUrl : "kyoo://"; diff --git a/front/packages/ui/src/errors/index.tsx b/front/packages/ui/src/errors/index.tsx index c7a6e21b..19c9c722 100644 --- a/front/packages/ui/src/errors/index.tsx +++ b/front/packages/ui/src/errors/index.tsx @@ -21,3 +21,4 @@ export * from "./error"; export * from "./unauthorized"; export * from "./connection"; +export * from "./setup"; diff --git a/front/packages/ui/src/errors/setup.tsx b/front/packages/ui/src/errors/setup.tsx new file mode 100644 index 00000000..eeb239db --- /dev/null +++ b/front/packages/ui/src/errors/setup.tsx @@ -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 }> = ({ step }) => { + const { css } = useYoshiki(); + const { t } = useTranslation(); + + return ( + <> + } /> +
+

{t(`errors.setup.${step}`)}

+ {step === SetupStep.MissingAdminAccount && ( +
+ + ); +}; diff --git a/front/packages/ui/src/navbar/index.tsx b/front/packages/ui/src/navbar/index.tsx index ec001dc4..31ed2a33 100644 --- a/front/packages/ui/src/navbar/index.tsx +++ b/front/packages/ui/src/navbar/index.tsx @@ -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 Search from "@material-symbols/svg-400/rounded/search-fill.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 { Platform, type TextInput, View, type ViewProps } from "react-native"; 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 { t } = useTranslation(); @@ -197,16 +201,20 @@ export const Navbar = (props: Stylable) => { > - theme.contrast, - })} - > - {t("navbar.browse")} - + {left !== undefined ? ( + left + ) : ( + theme.contrast, + })} + > + {t("navbar.browse")} + + )} { marginX: ts(2), })} /> - + {right !== undefined ? right : } ); }; diff --git a/front/translations/en.json b/front/translations/en.json index d004aed0..89a285bc 100644 --- a/front/translations/en.json +++ b/front/translations/en.json @@ -237,7 +237,11 @@ "offline": "You are not connected to internet. Try again later.", "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." + "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": { "file": "File",