From 07b41716e8e6d708d4ea20ad906c5211473f2882 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Fri, 4 Nov 2022 01:08:03 +0900 Subject: [PATCH] wip Native navbar --- front/apps/web/src/components/navbar.tsx | 123 ----------------- front/apps/web/src/components/poster.tsx | 129 ------------------ front/apps/web/src/pages/_app.tsx | 2 +- front/apps/web/src/pages/browse/index.tsx | 19 ++- front/packages/primitives/src/avatar.tsx | 38 ++++++ front/packages/primitives/src/icon.tsx | 21 +++ front/packages/primitives/src/image.tsx | 103 ++++++++++++++ front/packages/primitives/src/index.tsx | 24 ++++ front/packages/primitives/src/text.tsx | 73 ++++++++++ .../primitives/src}/theme.tsx | 0 front/packages/ui/src/index.tsx | 25 +++- front/packages/ui/src/navbar/icon.tsx | 74 ++++++++++ front/packages/ui/src/navbar/navbar.tsx | 59 ++++++++ 13 files changed, 423 insertions(+), 267 deletions(-) delete mode 100644 front/apps/web/src/components/navbar.tsx delete mode 100644 front/apps/web/src/components/poster.tsx create mode 100644 front/packages/primitives/src/avatar.tsx create mode 100644 front/packages/primitives/src/icon.tsx create mode 100644 front/packages/primitives/src/image.tsx create mode 100644 front/packages/primitives/src/index.tsx create mode 100644 front/packages/primitives/src/text.tsx rename front/{apps/web/src/utils/themes => packages/primitives/src}/theme.tsx (100%) create mode 100644 front/packages/ui/src/navbar/icon.tsx create mode 100644 front/packages/ui/src/navbar/navbar.tsx diff --git a/front/apps/web/src/components/navbar.tsx b/front/apps/web/src/components/navbar.tsx deleted file mode 100644 index eb3543bb..00000000 --- a/front/apps/web/src/components/navbar.tsx +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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, - Avatar, - IconButton, - Tooltip, - Box, - Skeleton, - AppBarProps, -} from "@mui/material"; -import MenuIcon from "@mui/icons-material/Menu"; -import useTranslation from "next-translate/useTranslation"; -import { ButtonLink } from "~/utils/link"; -import { Library, LibraryP, Page, Paged } from "~/models"; -import { QueryIdentifier, useFetch } from "~/utils/query"; -import { ErrorSnackbar } from "./errors"; - -const KyooTitle = () => { - const { t } = useTranslation("common"); - - return ( - - - - - Kyoo - - - - ); -}; - -export const Navbar = (barProps: AppBarProps) => { - const { t } = useTranslation("common"); - const { data, error, isSuccess, isError } = useFetch(Navbar.query()); - - return ( - - - - - - - - - - {isSuccess - ? data.items.map((library) => ( - - {library.name} - - )) - : [...Array(4)].map((_, i) => ( - - - - ))} - - - - - - - - {isError && } - - ); -}; - -Navbar.query = (): QueryIdentifier> => ({ - parser: Paged(LibraryP), - path: ["libraries"], -}); diff --git a/front/apps/web/src/components/poster.tsx b/front/apps/web/src/components/poster.tsx deleted file mode 100644 index 0c6b9f67..00000000 --- a/front/apps/web/src/components/poster.tsx +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 { Box, Skeleton, styled } from "@mui/material"; -import { SyntheticEvent, useEffect, useLayoutEffect, useRef, useState } from "react"; -import { ComponentsOverrides, ComponentsProps, ComponentsVariants } from "@mui/material"; -import { withThemeProps } from "~/utils/with-theme"; -import type { Property } from "csstype"; -import { ResponsiveStyleValue } from "@mui/system"; - -type ImageOptions = { - radius?: string; - fallback?: string; -}; - -type ImageProps = { - img?: string | null; - alt?: string; -} & ImageOptions; - -type ImagePropsWithLoading = - | (ImageProps & { loading?: boolean }) - | (Partial & { loading: true }); - -type Width = ResponsiveStyleValue>; -type Height = ResponsiveStyleValue>; - -const _Image = ({ - img, - alt, - radius, - fallback, - loading = false, - aspectRatio = undefined, - width = undefined, - height = undefined, - ...others -}: ImagePropsWithLoading & - ( - | { aspectRatio?: string; width: Width; height: Height } - | { aspectRatio: string; width?: Width; height?: Height } - )) => { - const [showLoading, setLoading] = useState(loading); - const imgRef = useRef(null); - - // This allow the loading bool to be false with SSR but still be on client-side - useLayoutEffect(() => { - if (!imgRef.current?.complete && img) setLoading(true); - if (!img && !loading) setLoading(false); - }, [img, loading]); - - return ( - *": { width: "100%", height: "100%" }, - }} - {...others} - > - {showLoading && } - {!loading && img && ( - setLoading(false)} - onError={({ currentTarget }: SyntheticEvent) => { - if (fallback && currentTarget.src !== fallback) currentTarget.src = fallback; - else setLoading(false); - }} - sx={{ objectFit: "cover", display: showLoading ? "hidden" : undefined }} - /> - )} - - ); -}; - -export const Image = styled(_Image)({}); - -// eslint-disable-next-line jsx-a11y/alt-text -const _Poster = (props: ImagePropsWithLoading & { width?: Width; height?: Height }) => ( - <_Image aspectRatio="2 / 3" {...props} /> -); - -declare module "@mui/material/styles" { - interface ComponentsPropsList { - Poster: ImageOptions; - } - - interface ComponentNameToClassKey { - Poster: Record; - } - - interface Components { - Poster?: { - defaultProps?: ComponentsProps["Poster"]; - styleOverrides?: ComponentsOverrides["Poster"]; - variants?: ComponentsVariants["Poster"]; - }; - } -} - -export const Poster = withThemeProps(_Poster, { - name: "Poster", - slot: "Root", -}); diff --git a/front/apps/web/src/pages/_app.tsx b/front/apps/web/src/pages/_app.tsx index 4b8235b7..0472e119 100755 --- a/front/apps/web/src/pages/_app.tsx +++ b/front/apps/web/src/pages/_app.tsx @@ -30,7 +30,7 @@ import superjson from "superjson"; import Head from "next/head"; import { useMobileHover } from "~/utils/utils"; import { catppuccin } from "~/utils/themes/catppuccin"; -import { selectMode } from "~/utils/themes/theme"; +import { selectMode } from "@kyoo/primitives"; // Simply silence a SSR warning (see https://github.com/facebook/react/issues/14927 for more details) if (typeof window === "undefined") { diff --git a/front/apps/web/src/pages/browse/index.tsx b/front/apps/web/src/pages/browse/index.tsx index 8c0211c0..1995e28d 100644 --- a/front/apps/web/src/pages/browse/index.tsx +++ b/front/apps/web/src/pages/browse/index.tsx @@ -34,10 +34,10 @@ import { } from "@mui/material"; import useTranslation from "next-translate/useTranslation"; import { useRouter } from "next/router"; -import { MouseEvent, useState } from "react"; +import { useState } from "react"; import { ErrorPage } from "~/components/errors"; -import { Navbar } from "~/components/navbar"; -import { Poster, Image } from "~/components/poster"; +import { Navbar } from "@kyoo/ui"; +import { Poster, Image } from "@kyoo/primitives"; import { ItemType, LibraryItem, LibraryItemP } from "~/models"; import { getDisplayDate } from "~/models/utils"; import { InfiniteScroll } from "~/utils/infinite-scroll"; @@ -89,7 +89,7 @@ const ItemGrid = ({ m: [1, 2], }} > - + {name ?? } {(loading || subtitle) && ( @@ -136,12 +136,12 @@ const ItemList = ({ }} > {name} @@ -433,7 +432,7 @@ BrowsePage.getLayout = (page) => { BrowsePage.getFetchUrls = ({ slug, sortBy }) => [ query(slug, sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd), - Navbar.query(), + /* Navbar.query(), */ ]; export default withRoute(BrowsePage); diff --git a/front/packages/primitives/src/avatar.tsx b/front/packages/primitives/src/avatar.tsx new file mode 100644 index 00000000..b57c1388 --- /dev/null +++ b/front/packages/primitives/src/avatar.tsx @@ -0,0 +1,38 @@ +/* + * 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 type { Property } from "csstype"; +import { View, Image } from "react-native"; + +export const Avatar = ({ + src, + alt, + size = "24px", +}: { + src: string; + alt: string; + size: Property.InlineSize; +}) => { + return ( + + {alt} + + ); +}; diff --git a/front/packages/primitives/src/icon.tsx b/front/packages/primitives/src/icon.tsx new file mode 100644 index 00000000..9364701f --- /dev/null +++ b/front/packages/primitives/src/icon.tsx @@ -0,0 +1,21 @@ +/* + * 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 . + */ + +/* export { MaterialIcons as Icon } from "@expo/vector-icons"; */ diff --git a/front/packages/primitives/src/image.tsx b/front/packages/primitives/src/image.tsx new file mode 100644 index 00000000..d29a4eb1 --- /dev/null +++ b/front/packages/primitives/src/image.tsx @@ -0,0 +1,103 @@ +/* + * 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 { useState } from "react"; +import { + View, + Image as Img, + ImageSourcePropType, +} from "react-native"; +import type { Property } from "csstype"; + +type ImageOptions = { + radius?: string; + fallback?: string | ImageSourcePropType; +}; + +type ImageProps = { + src?: string | ImageSourcePropType | null; + alt?: string; +} & ImageOptions; + +type ImagePropsWithLoading = + | (ImageProps & { loading?: boolean }) + | (Partial & { loading: true }); + +type Width = Property.Width<(string & {}) | 0>; +type Height = Property.Height<(string & {}) | 0>; + +export const Image = ({ + src, + alt, + radius, + fallback, + loading = false, + aspectRatio = undefined, + width = undefined, + height = undefined, + ...others +}: ImagePropsWithLoading & + ( + | { aspectRatio?: string; width: Width; height: Height } + | { aspectRatio: string; width?: Width; height?: Height } + )) => { + const [showLoading, setLoading] = useState(loading); + const [source, setSource] = useState(src); + /* const imgRef = useRef(null); */ + + // This allow the loading bool to be false with SSR but still be on client-side + /* useLayoutEffect(() => { */ + /* if (!imgRef.current?.complete && src) setLoading(true); */ + /* if (!src && !loading) setLoading(false); */ + /* }, [src, loading]); */ + + return ( + *": { width: "100%", height: "100%" }, + }} + {...others} + > + {/* {showLoading && } */} + {!loading && source && ( + setLoading(false)} + onError={() => { + if (fallback) setSource(fallback); + else setLoading(false); + }} + css={{ objectFit: "cover", display: showLoading ? "hidden" : undefined }} + /> + )} + + ); +}; + +export const Poster = (props: ImagePropsWithLoading & { width?: Width; height?: Height }) => ( + +); diff --git a/front/packages/primitives/src/index.tsx b/front/packages/primitives/src/index.tsx new file mode 100644 index 00000000..b24202c8 --- /dev/null +++ b/front/packages/primitives/src/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 . + */ + +export * from "./text"; +export * from "./theme"; +export * from "./icon"; +export * from "./image"; diff --git a/front/packages/primitives/src/text.tsx b/front/packages/primitives/src/text.tsx new file mode 100644 index 00000000..bc5fdb7f --- /dev/null +++ b/front/packages/primitives/src/text.tsx @@ -0,0 +1,73 @@ +/* + * 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 { forwardRef } from "react"; +import { Platform, Text } from "react-native"; + +export const Heading = forwardRef< + Text, + { + level: 1 | 2 | 3 | 4 | 5 | 6; + children?: JSX.Element | JSX.Element[]; + } +>(function Heading({ level = 1, children, ...props }, ref) { + const nativeProps: any = Platform.select({ + web: { + "aria-level": level.toString(), + }, + default: {}, + }); + + return ( + ({ + font: theme.fonts.heading, + color: theme.heading, + })} + > + {children} + + ); +}); + +export const Paragraph = forwardRef< + Text, + { + variant: "normal" | "subtext"; + children?: string | JSX.Element | JSX.Element[]; + } +>(function Paragraph({ variant, children, ...props }, ref) { + return ( + theme.fonts.paragraph, + color: theme => variant === "normal" ? theme.paragraph : theme.subtext, + })} + > + {children} + + ); +}); diff --git a/front/apps/web/src/utils/themes/theme.tsx b/front/packages/primitives/src/theme.tsx similarity index 100% rename from front/apps/web/src/utils/themes/theme.tsx rename to front/packages/primitives/src/theme.tsx diff --git a/front/packages/ui/src/index.tsx b/front/packages/ui/src/index.tsx index cc317287..58a32d71 100644 --- a/front/packages/ui/src/index.tsx +++ b/front/packages/ui/src/index.tsx @@ -1,4 +1,21 @@ -// leave this blank -// don't re-export files from this workspace. it'll break next.js tree shaking -// https://github.com/vercel/next.js/issues/12557 -export { Toto } from "./toto"; +/* + * 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 . + */ + +export * from "./navbar/navbar"; diff --git a/front/packages/ui/src/navbar/icon.tsx b/front/packages/ui/src/navbar/icon.tsx new file mode 100644 index 00000000..a5ead79b --- /dev/null +++ b/front/packages/ui/src/navbar/icon.tsx @@ -0,0 +1,74 @@ +/* + * 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 Svg, { SvgProps, Path } from "react-native-svg"; + +/* export const KyooLogo = (props: SvgProps) => ( */ +/* */ +/* */ +/* */ +/* */ +/* ); */ + +export const KyooLongLogo = (props: SvgProps) => + ( + + + + + + + + +); diff --git a/front/packages/ui/src/navbar/navbar.tsx b/front/packages/ui/src/navbar/navbar.tsx new file mode 100644 index 00000000..6924b06e --- /dev/null +++ b/front/packages/ui/src/navbar/navbar.tsx @@ -0,0 +1,59 @@ +/* + * 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 { Paragraph } from "@kyoo/primitives"; +import { View } from "react-native"; +import { KyooLongLogo } from "./icon"; + +export const Navbar = () => { + /* const { t } = useTranslation("common"); */ + /* const { data, error, isSuccess, isError } = useFetch(Navbar.query()); */ + + return ( + ({ backgroundColor: theme.appbar })}> + + Toto + {/* */} + {/* {isSuccess */} + {/* ? data.items.map((library) => ( */} + {/* */} + {/* {library.name} */} + {/* */} + {/* )) */} + {/* : [...Array(4)].map((_, i) => ( */} + {/* */} + {/* */} + {/* */} + {/* ))} */} + {/* */} + {/* */} + {/* {isError && } */} + + ); +}; + +/* Navbar.query = (): QueryIdentifier> => ({ */ +/* parser: Paged(LibraryP), */ +/* path: ["libraries"], */ +/* }); */