diff --git a/front/src/pages/toto.tsx b/front/src/components/error-snackbar.tsx
similarity index 56%
rename from front/src/pages/toto.tsx
rename to front/src/components/error-snackbar.tsx
index 3ef0929d..aaf121b6 100644
--- a/front/src/pages/toto.tsx
+++ b/front/src/components/error-snackbar.tsx
@@ -18,26 +18,22 @@
* along with Kyoo. If not, see .
*/
-import { QueryPage, useFetch } from "~/utils/query";
-import useTranslation from "next-translate/useTranslation";
+import { Alert, Snackbar, SnackbarCloseReason } from "@mui/material";
+import { SyntheticEvent, useState } from "react";
+import { KyooErrors } from "~/models";
-const Toto: QueryPage = ({}) => {
- const libraries = useFetch("libraries");
- const { t } = useTranslation("common");
-
- if (libraries.error) return oups
;
- if (!libraries.data) return loading
;
+export const ErrorSnackbar = ({ error }: { error: KyooErrors }) => {
+ const [isOpen, setOpen] = useState(true);
+ const close = (_: Event | SyntheticEvent, reason?: SnackbarCloseReason) => {
+ if (reason !== "clickaway") setOpen(false);
+ };
+ if (!isOpen) return null;
return (
- <>
- {t("navbar.home")}
- {libraries.data.items.map((x: any) => (
- {x.name}
- ))}
- >
+
+
+ {error.errors[0]}
+
+
);
};
-
-Toto.getFetchUrls = () => [["libraries"]];
-
-export default Toto;
diff --git a/front/src/components/navbar.tsx b/front/src/components/navbar.tsx
new file mode 100644
index 00000000..60d8e242
--- /dev/null
+++ b/front/src/components/navbar.tsx
@@ -0,0 +1,121 @@
+/*
+ * 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 {
+ AppBar,
+ Toolbar,
+ Typography,
+ SxProps,
+ Theme,
+ Avatar,
+ IconButton,
+ Tooltip,
+ Box,
+ Skeleton,
+} from "@mui/material";
+import MenuIcon from "@mui/icons-material/Menu";
+import logo from "../../public/icons/icon.svg";
+import useTranslation from "next-translate/useTranslation";
+import Image from "next/image";
+import { ButtonLink } from "~/utils/link";
+import { Library, Page } from "~/models";
+import { useFetch } from "~/utils/query";
+import { ErrorSnackbar } from "./error-snackbar";
+
+export const KyooTitle = (props: { sx: SxProps }) => {
+ const { t } = useTranslation("common");
+
+ return (
+
+
+
+
+ Kyoo
+
+
+
+ );
+};
+
+export const Navbar = () => {
+ const { t } = useTranslation("common");
+ const { data, error, isSuccess, isError } = useFetch>("libraries");
+
+ return (
+
+
+
+
+
+
+
+
+
+ {isSuccess
+ ? data.items.map((library) => (
+
+ {library.name}
+
+ ))
+ : [...Array(4)].map((_, i) => (
+
+
+
+ ))}
+
+
+
+
+
+
+
+ {isError && }
+
+ );
+};
diff --git a/front/src/global.css b/front/src/global.css
new file mode 100644
index 00000000..fffb5a5d
--- /dev/null
+++ b/front/src/global.css
@@ -0,0 +1,3 @@
+body {
+ margin: 0 !important;
+}
diff --git a/front/src/pages/_app.tsx b/front/src/pages/_app.tsx
index daf7a40d..37a52654 100755
--- a/front/src/pages/_app.tsx
+++ b/front/src/pages/_app.tsx
@@ -26,6 +26,8 @@ import type { AppProps } from "next/app";
import { Hydrate, QueryClientProvider } from "react-query";
import { createQueryClient, fetchQuery } from "~/utils/query";
import { defaultTheme } from "~/utils/themes/default-theme";
+import { Navbar } from "~/components/navbar";
+import "../global.css"
const App = ({ Component, pageProps }: AppProps) => {
const [queryClient] = useState(() => createQueryClient());
@@ -33,6 +35,9 @@ const App = ({ Component, pageProps }: AppProps) => {
+
+ {/* TODO: add a container to allow the component to be scrolled without the navbar */}
+ {/* TODO: add an option to disable the navbar in the component */}
@@ -44,7 +49,10 @@ App.getInitialProps = async (ctx: AppContext) => {
const appProps = await NextApp.getInitialProps(ctx);
const getUrl = (ctx.Component as any).getFetchUrls;
- if (getUrl) appProps.pageProps.queryState = await fetchQuery(getUrl(ctx.router.query));
+ const urls: [[string]] = getUrl ? getUrl(ctx.router.query) : [];
+ // TODO: check if the navbar is needed for this
+ urls.push(["libraries"]);
+ appProps.pageProps.queryState = await fetchQuery(urls);
return appProps;
};
diff --git a/front/src/utils/link.tsx b/front/src/utils/link.tsx
index 37ee297f..00b2542c 100644
--- a/front/src/utils/link.tsx
+++ b/front/src/utils/link.tsx
@@ -18,106 +18,30 @@
* along with Kyoo. If not, see .
*/
-// This file was shamelessly taken from:
-// https://github.com/mui/material-ui/tree/master/examples/nextjs
+import React, { forwardRef, Ref } from "react";
+import NLink, { LinkProps as NLinkProps} from "next/link";
+import { Button as MButton, ButtonProps, Link as MLink, LinkProps as MLinkProps} from "@mui/material";
-import * as React from "react";
-import clsx from "clsx";
-import { useRouter } from "next/router";
-import NextLink, { LinkProps as NextLinkProps } from "next/link";
-import MuiLink, { LinkProps as MuiLinkProps } from "@mui/material/Link";
-import { styled } from "@mui/material/styles";
+type ButtonRef = HTMLButtonElement;
+type ButtonLinkProps = Omit &
+ Pick;
-// Add support for the sx prop for consistency with the other branches.
-const Anchor = styled("a")({});
-
-interface NextLinkComposedProps
- extends Omit, "href">,
- Omit {
- to: NextLinkProps["href"];
- linkAs?: NextLinkProps["as"];
-}
-
-export const NextLinkComposed = React.forwardRef(
- function NextLinkComposed(props, ref) {
- const { to, linkAs, replace, scroll, shallow, prefetch, locale, ...other } = props;
-
- return (
-
-
-
- );
- },
+const NextButton = ({ href, as, prefetch, locale, ...props }: ButtonLinkProps, ref: Ref) => (
+
+
+
);
-export type LinkProps = {
- activeClassName?: string;
- as?: NextLinkProps["as"];
- href: NextLinkProps["href"];
- linkAs?: NextLinkProps["as"]; // Useful when the as prop is shallow by styled().
- noLinkStyle?: boolean;
-} & Omit &
- Omit;
+export const ButtonLink = forwardRef(NextButton);
-// A styled version of the Next.js Link component:
-// https://nextjs.org/docs/api-reference/next/link
-export const Link = React.forwardRef(function Link(props, ref) {
- const {
- activeClassName = "active",
- as,
- className: classNameProps,
- href,
- linkAs: linkAsProp,
- locale,
- noLinkStyle,
- prefetch,
- replace,
- role, // Link don't have roles.
- scroll,
- shallow,
- ...other
- } = props;
+type LinkRef = HTMLAnchorElement;
+type LinkProps = Omit &
+ Pick;
- const router = useRouter();
- const pathname = typeof href === "string" ? href : href.pathname;
- const className = clsx(classNameProps, {
- [activeClassName]: router.pathname === pathname && activeClassName,
- });
+const NextLink = ({ href, as, prefetch, locale, ...props }: LinkProps, ref: Ref) => (
+
+
+
+);
- const isExternal =
- typeof href === "string" && (href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
-
- if (isExternal) {
- if (noLinkStyle) {
- return ;
- }
-
- return ;
- }
-
- const linkAs = linkAsProp || as;
- const nextjsProps = { to: href, linkAs, replace, scroll, shallow, prefetch, locale };
-
- if (noLinkStyle) {
- return ;
- }
-
- return (
-
- );
-});
+export const Link = forwardRef(NextLink);
diff --git a/front/src/utils/query.ts b/front/src/utils/query.ts
index f1333885..1c4def36 100644
--- a/front/src/utils/query.ts
+++ b/front/src/utils/query.ts
@@ -19,7 +19,14 @@
*/
import { ComponentType } from "react";
-import { dehydrate, QueryClient, QueryFunctionContext, useQuery } from "react-query";
+import {
+ dehydrate,
+ QueryClient,
+ QueryFunctionContext,
+ useInfiniteQuery,
+ useQuery,
+} from "react-query";
+import { imageList, KyooErrors, Page } from "~/models";
const queryFn = async (context: QueryFunctionContext): Promise => {
try {
@@ -55,8 +62,30 @@ export type QueryPage = ComponentType & {
getFetchUrls?: (route: { [key: string]: string }) => [[string]];
};
+const imageSelector = (obj: T): T => {
+ for (const img of imageList) {
+ // @ts-ignore
+ if (img in obj && !obj[img].startWith("/api")) {
+ // @ts-ignore
+ obj[img] = `/api/${obj[img]}`;
+ }
+ }
+ return obj;
+};
+
export const useFetch = (...params: [string]) => {
- return useQuery(params);
+ return useQuery(params, {
+ select: imageSelector,
+ });
+};
+
+export const useInfiniteFetch = (...params: [string]) => {
+ return useInfiniteQuery, KyooErrors>(params, {
+ select: (pages) => {
+ pages.pages.map((x) => x.items.map(imageSelector));
+ return pages;
+ },
+ });
};
export const fetchQuery = async (queries: [[string]]) => {