diff --git a/front/apps/mobile/app/browse/index.tsx b/front/apps/mobile/app/browse/index.tsx
index 1815e516..a9cc8d79 100644
--- a/front/apps/mobile/app/browse/index.tsx
+++ b/front/apps/mobile/app/browse/index.tsx
@@ -1,3 +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 .
+ */
+
import { BrowsePage } from "@kyoo/ui";
-export default BrowsePage
+export default BrowsePage;
diff --git a/front/apps/mobile/app/movie/index.tsx b/front/apps/mobile/app/movie/index.tsx
new file mode 100644
index 00000000..c19e0d73
--- /dev/null
+++ b/front/apps/mobile/app/movie/index.tsx
@@ -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 .
+ */
+
+import { MovieDetails } from "@kyoo/ui";
+
+export default MovieDetails;
diff --git a/front/apps/mobile/package.json b/front/apps/mobile/package.json
index 500e9197..31aa7031 100644
--- a/front/apps/mobile/package.json
+++ b/front/apps/mobile/package.json
@@ -31,7 +31,7 @@
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-svg": "13.4.0",
- "yoshiki": "0.2.9"
+ "yoshiki": "0.2.11"
},
"devDependencies": {
"@babel/core": "^7.19.3",
diff --git a/front/apps/web/package.json b/front/apps/web/package.json
index 4ffdd705..decc5b87 100644
--- a/front/apps/web/package.json
+++ b/front/apps/web/package.json
@@ -41,7 +41,7 @@
"react-native-web": "^0.18.10",
"solito": "^2.0.5",
"superjson": "^1.11.0",
- "yoshiki": "0.2.9",
+ "yoshiki": "0.2.11",
"zod": "^3.19.1"
},
"devDependencies": {
diff --git a/front/apps/web/src/pages/browse/[slug].tsx b/front/apps/web/src/pages/browse/[slug].tsx
index 47273d31..f1d11355 100644
--- a/front/apps/web/src/pages/browse/[slug].tsx
+++ b/front/apps/web/src/pages/browse/[slug].tsx
@@ -18,6 +18,7 @@
* along with Kyoo. If not, see .
*/
-import BrowsePage from "./index";
+import { BrowsePage } from "@kyoo/ui";
+import { withRoute } from "~/utils/router";
-export default BrowsePage;
+export default withRoute(BrowsePage);
diff --git a/front/apps/web/src/pages/browse/index.tsx b/front/apps/web/src/pages/browse/index.tsx
index 98cae566..f1d11355 100644
--- a/front/apps/web/src/pages/browse/index.tsx
+++ b/front/apps/web/src/pages/browse/index.tsx
@@ -22,423 +22,3 @@ import { BrowsePage } from "@kyoo/ui";
import { withRoute } from "~/utils/router";
export default withRoute(BrowsePage);
-
-/* import { FilterList, GridView, North, Sort, South, ViewList } from "@mui/icons-material"; */
-/* import { */
-/* Box, */
-/* Button, */
-/* ButtonGroup, */
-/* ListItemIcon, */
-/* ListItemText, */
-/* MenuItem, */
-/* Menu, */
-/* Skeleton, */
-/* Divider, */
-/* Tooltip, */
-/* Typography, */
-/* } from "@mui/material"; */
-/* import useTranslation from "next-translate/useTranslation"; */
-/* import { useRouter } from "next/router"; */
-/* import { useState } from "react"; */
-/* import { ErrorPage } from "~/components/errors"; */
-/* import { Navbar } from "@kyoo/ui"; */
-/* import { Poster, Image } from "@kyoo/primitives"; */
-/* import { ItemType, LibraryItem, LibraryItemP } from "~/models"; */
-/* import { getDisplayDate } from "@kyoo/models"; */
-/* import { InfiniteScroll } from "~/utils/infinite-scroll"; */
-/* import { Link } from "~/utils/link"; */
-/* import { withRoute } from "~/utils/router"; */
-/* import { QueryIdentifier, QueryPage, useInfiniteFetch } from "@kyoo/models"; */
-/* import { px } from "yoshiki/native"; */
-
-/* enum SortBy { */
-/* Name = "name", */
-/* StartAir = "startAir", */
-/* EndAir = "endAir", */
-/* } */
-
-/* enum SortOrd { */
-/* Asc = "asc", */
-/* Desc = "desc", */
-/* } */
-
-/* enum Layout { */
-/* Grid, */
-/* List, */
-/* } */
-
-/* const ItemGrid = ({ */
-/* href, */
-/* name, */
-/* subtitle, */
-/* poster, */
-/* loading, */
-/* }: { */
-/* href?: string; */
-/* name?: string; */
-/* subtitle?: string | null; */
-/* poster?: string | null; */
-/* loading?: boolean; */
-/* }) => { */
-/* return ( */
-/* */
-/* */
-/* {name ?? } */
-/* {(loading || subtitle) && ( */
-/* */
-/* {subtitle ?? } */
-/* */
-/* )} */
-/* */
-/* ); */
-/* }; */
-
-/* const ItemList = ({ */
-/* href, */
-/* name, */
-/* subtitle, */
-/* thumbnail, */
-/* poster, */
-/* loading, */
-/* }: { */
-/* href?: string; */
-/* name?: string; */
-/* subtitle?: string | null; */
-/* poster?: string | null; */
-/* thumbnail?: string | null; */
-/* loading?: boolean; */
-/* }) => { */
-/* return ( */
-/* */
-/* */
-/* */
-/* */
-/* {name ?? } */
-/* */
-/* {(loading || subtitle) && ( */
-/* */
-/* {subtitle ?? } */
-/* */
-/* )} */
-/* */
-/* */
-/* */
-/* ); */
-/* }; */
-
-/* const Item = ({ item, layout }: { item?: LibraryItem; layout: Layout }) => { */
-/* let href; */
-/* if (item?.type === ItemType.Movie) href = `/movie/${item.slug}`; */
-/* else if (item?.type === ItemType.Show) href = `/show/${item.slug}`; */
-/* else if (item?.type === ItemType.Collection) href = `/collection/${item.slug}`; */
-
-/* switch (layout) { */
-/* case Layout.Grid: */
-/* return ( */
-/* */
-/* ); */
-/* case Layout.List: */
-/* return ( */
-/* */
-/* ); */
-/* } */
-/* }; */
-
-/* const SortByMenu = ({ */
-/* sortKey, */
-/* setSort, */
-/* sortOrd, */
-/* setSortOrd, */
-/* anchor, */
-/* onClose, */
-/* }: { */
-/* sortKey: SortBy; */
-/* setSort: (sort: SortBy) => void; */
-/* sortOrd: SortOrd; */
-/* setSortOrd: (sort: SortOrd) => void; */
-/* anchor: HTMLElement; */
-/* onClose: () => void; */
-/* }) => { */
-/* const router = useRouter(); */
-/* const { t } = useTranslation("browse"); */
-
-/* return ( */
-/*
*/
-/* ); */
-/* }; */
-
-/* const BrowseSettings = ({ */
-/* sortKey, */
-/* setSort, */
-/* sortOrd, */
-/* setSortOrd, */
-/* layout, */
-/* setLayout, */
-/* }: { */
-/* sortKey: SortBy; */
-/* setSort: (sort: SortBy) => void; */
-/* sortOrd: SortOrd; */
-/* setSortOrd: (sort: SortOrd) => void; */
-/* layout: Layout; */
-/* setLayout: (layout: Layout) => void; */
-/* }) => { */
-/* const [sortAnchor, setSortAnchor] = useState(null); */
-/* const { t } = useTranslation("browse"); */
-
-/* const switchViewTitle = */
-/* layout === Layout.Grid ? t("browse.switchToList") : t("browse.switchToGrid"); */
-
-/* return ( */
-/* <> */
-/* */
-/* */
-/* */
-/* */
-/* */
-/* */
-/* setSortAnchor(event.currentTarget)} */
-/* > */
-/* */
-/* {t("browse.sortby", { key: t(`browse.sortkey.${sortKey}`) })} */
-/* {sortOrd === SortOrd.Asc ? : } */
-/* */
-/* */
-/* */
-/* setLayout(layout === Layout.List ? Layout.Grid : Layout.List)} */
-/* aria-label={switchViewTitle} */
-/* > */
-/* {layout === Layout.List ? : } */
-/* */
-/* */
-/* */
-/* */
-/* {sortAnchor && ( */
-/* setSortAnchor(null)} */
-/* /> */
-/* )} */
-/* > */
-/* ); */
-/* }; */
-
-/* const query = ( */
-/* slug?: string, */
-/* sortKey?: SortBy, */
-/* sortOrd?: SortOrd, */
-/* ): QueryIdentifier => ({ */
-/* parser: LibraryItemP, */
-/* path: slug ? ["library", slug, "items"] : ["items"], */
-/* infinite: true, */
-/* params: { */
-/* // The API still uses title isntead of name */
-/* sortBy: sortKey */
-/* ? `${sortKey === SortBy.Name ? "title" : sortKey}:${sortOrd ?? "asc"}` */
-/* : "title:asc", */
-/* }, */
-/* }); */
-
-/* const BrowsePage: QueryPage<{ slug?: string }> = ({ slug }) => { */
-/* const [sortKey, setSort] = useState(SortBy.Name); */
-/* const [sortOrd, setSortOrd] = useState(SortOrd.Asc); */
-/* const [layout, setLayout] = useState(Layout.Grid); */
-/* const { items, fetchNextPage, hasNextPage, error } = useInfiniteFetch( */
-/* query(slug, sortKey, sortOrd), */
-/* ); */
-
-/* if (error) return ; */
-
-/* return ( */
-/* <> */
-/* */
-/* )]} */
-/* sx={{ */
-/* display: "flex", */
-/* flexWrap: "wrap", */
-/* alignItems: "flex-start", */
-/* justifyContent: "center", */
-/* }} */
-/* > */
-/* {(items ?? [...Array(12)]).map((x, i) => ( */
-/* */
-/* ))} */
-/* */
-/* > */
-/* ); */
-/* }; */
-
-/* BrowsePage.getLayout = (page) => { */
-/* return ( */
-/* <> */
-/* */
-/* {page} */
-/* > */
-/* ); */
-/* }; */
-
-/* BrowsePage.getFetchUrls = ({ slug, sortBy }) => [ */
-/* query(slug, sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd), */
-/* Navbar.query(), */
-/* ]; */
-
-/* export default withRoute(BrowsePage); */
diff --git a/front/apps/web/src/pages/movie/[slug].tsx b/front/apps/web/src/pages/movie/[slug].tsx
index f62ceed6..3b0adf8f 100644
--- a/front/apps/web/src/pages/movie/[slug].tsx
+++ b/front/apps/web/src/pages/movie/[slug].tsx
@@ -18,294 +18,7 @@
* along with Kyoo. If not, see .
*/
-import { LocalMovies, PlayArrow } from "@mui/icons-material";
-import {
- Box,
- Divider,
- Fab,
- IconButton,
- Skeleton,
- SxProps,
- Tooltip,
- Typography,
-} from "@mui/material";
-import useTranslation from "next-translate/useTranslation";
-import Head from "next/head";
-import { Navbar } from "~/components/navbar";
-import { Image, Poster } from "~/components/poster";
-import { Movie, MovieP, Show } from "~/models";
-import { QueryIdentifier, QueryPage, useFetch, useInfiniteFetch } from "~/utils/query";
-import { getDisplayDate } from "~/models/utils";
+import { MovieDetails } from "@kyoo/ui";
import { withRoute } from "~/utils/router";
-import { Container } from "~/components/container";
-import { makeTitle } from "~/utils/utils";
-import { Link } from "~/utils/link";
-import { Studio } from "~/models/resources/studio";
-import { Person, PersonP } from "~/models";
-import { PersonAvatar } from "~/components/person";
-import { ErrorComponent, ErrorPage } from "~/components/errors";
-import { HorizontalList } from "~/components/horizontal-list";
-import NextLink from "next/link";
-
-const StudioText = ({
- studio,
- loading = false,
- sx,
-}: {
- studio?: Studio | null;
- loading?: boolean;
- sx?: SxProps;
-}) => {
- const { t } = useTranslation("browse");
-
- if (!loading && !studio) return null;
- return (
-
- {t("show.studio")}:{" "}
- {loading ? (
-
- ) : (
- {studio!.name}
- )}
-
- );
-};
-
-export const ShowHeader = ({ data }: { data?: Show | Movie }) => {
- /* const scroll = useScroll(); */
- const { t } = useTranslation("browse");
- // TODO: tweek the navbar color with the theme.
-
- return (
- <>
- {/* TODO: Add a shadow on navbar items */}
- {/* TODO: Put the navbar outside of the scrollbox */}
-
-
-
-
-
-
-
- {data?.name ?? }
-
- {(!data || getDisplayDate(data)) && (
-
- {data != undefined ? (
- getDisplayDate(data)
- ) : (
-
- )}
-
- )}
- *": { m: ".3rem !important" } }}>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {data?.logo && (
-
- )}
-
-
-
-
-
-
-
- {t("show.genre")}
- {": "}
- {!data ? (
-
- ) : data?.genres && data.genres.length ? (
- data.genres.map((genre, i) => [
- i > 0 && ", ",
-
- {genre.name}
- ,
- ])
- ) : (
- t("show.genre-none")
- )}
-
-
-
-
-
- {data
- ? data.overview ?? t("show.noOverview")
- : [...Array(4)].map((_, i) => )}
-
-
-
-
-
-
- {t("show.genre")}
-
- {!data || data.genres?.length ? (
-
- {(data ? data.genres! : [...Array(3)]).map((genre, i) => (
-
-
- {genre ? (
- {genre.name}
- ) : (
-
- )}
-
-
- ))}
-
- ) : (
- {t("show.genre-none")}
- )}
-
-
- >
- );
-};
-
-export const ShowStaff = ({ slug }: { slug: string }) => {
- const { items, isError, error } = useInfiniteFetch(ShowStaff.query(slug));
- const { t } = useTranslation("browse");
-
- // TODO: handle infinite scroll
-
- if (isError) return ;
-
- return (
-
- {(items ?? [...Array(20)]).map((x, i) => (
-
- ))}
-
- );
-};
-
-ShowStaff.query = (slug: string): QueryIdentifier => ({
- parser: PersonP,
- path: ["shows", slug, "people"],
- infinite: true,
-});
-
-const query = (slug: string): QueryIdentifier => ({
- parser: MovieP,
- path: ["shows", slug],
- params: {
- fields: ["genres", "studio"],
- },
-});
-
-const MovieDetails: QueryPage<{ slug: string }> = ({ slug }) => {
- const { data, error } = useFetch(query(slug));
-
- if (error) return ;
-
- return (
- <>
-
- {makeTitle(data?.name)}
-
-
-
-
- >
- );
-};
-
-MovieDetails.getFetchUrls = ({ slug }) => [query(slug), ShowStaff.query(slug), Navbar.query()];
export default withRoute(MovieDetails);
diff --git a/front/packages/primitives/src/container.tsx b/front/packages/primitives/src/container.tsx
new file mode 100644
index 00000000..b7064bb6
--- /dev/null
+++ b/front/packages/primitives/src/container.tsx
@@ -0,0 +1,44 @@
+/*
+ * 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 { View, ViewProps } from "react-native";
+import { useYoshiki } from "yoshiki/native";
+
+export const Container = (props: ViewProps) => {
+ const { css } = useYoshiki();
+
+ return (
+
+ );
+};
diff --git a/front/packages/primitives/src/icons.tsx b/front/packages/primitives/src/icons.tsx
index 71fb941a..69824a0b 100644
--- a/front/packages/primitives/src/icons.tsx
+++ b/front/packages/primitives/src/icons.tsx
@@ -19,28 +19,69 @@
*/
import MIcon from "@expo/vector-icons/MaterialIcons";
-import { ComponentProps } from "react";
-import { Pressable, useTheme } from "yoshiki/native";
+import { ComponentProps, ComponentType } from "react";
+import { PressableProps } from "react-native";
+import { Pressable, px, useYoshiki } from "yoshiki/native";
+import { Breakpoint, ts } from ".";
export type IconProps = {
icon: ComponentProps["name"];
size?: number;
- color?: string;
+ color?: Breakpoint;
};
-export const Icon = ({ icon, size, color }: IconProps) => {
- return ;
+export const Icon = ({ icon, size = 24, color }: IconProps) => {
+ const { css, theme } = useYoshiki();
+ return (
+
+ );
};
-export const IconButton = ({
+export const IconButton = ({
icon,
size,
color,
- ...props
-}: ComponentProps & IconProps) => {
+ as,
+ ...asProps
+}: IconProps & { as?: ComponentType } & AsProps) => {
+ const { css } = useYoshiki();
+
+ const Container = as ?? Pressable;
+
return (
-
+
-
+
+ );
+};
+
+export const IconFab = (
+ props: ComponentProps>,
+) => {
+ const { css, theme } = useYoshiki();
+
+ return (
+ theme.accent,
+ },
+ props,
+ ) as any)}
+ />
);
};
diff --git a/front/packages/primitives/src/image.tsx b/front/packages/primitives/src/image.tsx
index fbc624b1..557efeb7 100644
--- a/front/packages/primitives/src/image.tsx
+++ b/front/packages/primitives/src/image.tsx
@@ -132,8 +132,8 @@ export const ImageBackground = ({
as?: ComponentType;
gradient?: Partial | boolean;
children: ReactNode;
- containerStyle?: StyleList;
- imageStyle?: StyleList;
+ containerStyle?: YoshikiEnhanced;
+ imageStyle?: YoshikiEnhanced;
} & AsProps &
Props) => {
const [isErrored, setErrored] = useState(false);
diff --git a/front/packages/primitives/src/index.ts b/front/packages/primitives/src/index.ts
index 20de36ff..38bba259 100644
--- a/front/packages/primitives/src/index.ts
+++ b/front/packages/primitives/src/index.ts
@@ -18,7 +18,7 @@
* along with Kyoo. If not, see .
*/
-export { Header, Nav, Footer } from "@expo/html-elements";
+export { Header, Main, Nav, Footer } from "@expo/html-elements";
export * from "./text";
export * from "./themes";
export * from "./icons";
@@ -27,23 +27,15 @@ export * from "./avatar";
export * from "./image";
export * from "./skeleton";
export * from "./tooltip";
+export * from "./container";
export * from "./animated";
export * from "./utils/breakpoints";
export * from "./utils/nojs";
-import { Dimensions } from "react-native";
import { px } from "yoshiki/native";
export const ts = (spacing: number) => {
return px(spacing * 8);
};
-
-export const vw = (spacing: number) => {
- return px(spacing * Dimensions.get('window').width / 100);
-};
-
-export const vh = (spacing: number) => {
- return px(spacing * Dimensions.get('window').height / 100);
-};
diff --git a/front/packages/primitives/src/skeleton.tsx b/front/packages/primitives/src/skeleton.tsx
index bca1c654..2fef683b 100644
--- a/front/packages/primitives/src/skeleton.tsx
+++ b/front/packages/primitives/src/skeleton.tsx
@@ -69,7 +69,6 @@ export const Skeleton = ({
borderRadius: px(6),
},
variant === "text" && {
- margin: rem(1),
width: percent(75),
height: rem(1.2),
},
diff --git a/front/packages/primitives/src/themes/catppuccin.ts b/front/packages/primitives/src/themes/catppuccin.ts
index 09a3a614..99108b1c 100644
--- a/front/packages/primitives/src/themes/catppuccin.ts
+++ b/front/packages/primitives/src/themes/catppuccin.ts
@@ -63,7 +63,7 @@ export const catppuccin: ThemeBuilder = {
overlay1: "#9399b2",
default: {
background: "#1e1e2e",
- accent: "##f5c2e7",
+ accent: "#f5c2e7",
divider: "#7f849c",
heading: "#cdd6f4",
paragraph: "#bac2de",
diff --git a/front/packages/primitives/src/themes/theme.tsx b/front/packages/primitives/src/themes/theme.tsx
index 88bfe388..399b0dca 100644
--- a/front/packages/primitives/src/themes/theme.tsx
+++ b/front/packages/primitives/src/themes/theme.tsx
@@ -23,6 +23,7 @@ import { Property } from "csstype";
import { Theme, ThemeProvider } from "yoshiki";
import { useTheme, useYoshiki } from "yoshiki/native";
import "yoshiki";
+import "yoshiki/native";
import { catppuccin } from "./catppuccin";
type ThemeSettings = {
@@ -57,11 +58,19 @@ type Variant = {
};
declare module "yoshiki" {
- // TODO: Add specifics colors
export interface Theme extends ThemeSettings, Mode, Variant {
- builder: ThemeBuilder;
+ light: Mode & Variant;
+ dark: Mode & Variant;
+ user: Mode & Variant;
}
}
+// declare module "yoshiki/native" {
+// export interface Theme extends ThemeSettings, Mode, Variant {
+// light: Mode & Variant;
+// dark: Mode & Variant;
+// user: Mode & Variant;
+// }
+// }
export type { Theme } from "yoshiki";
export type ThemeBuilder = ThemeSettings & {
@@ -69,14 +78,21 @@ export type ThemeBuilder = ThemeSettings & {
dark: Mode & { default: Variant };
};
-export const selectMode = (theme: ThemeBuilder, mode: "light" | "dark"): Theme => {
- const { light, dark, ...options } = theme;
+const selectMode = (theme: ThemeBuilder, mode: "light" | "dark"): Theme => {
+ const { light: lightBuilder, dark: darkBuilder, ...options } = theme;
+ const light = { ...lightBuilder, ...lightBuilder.default };
+ const dark = { ...darkBuilder, ...darkBuilder.default };
const value = mode === "light" ? light : dark;
- const { default: def, ...modeOpt } = value;
- return { ...options, ...modeOpt, ...def, variant: value.variant, builder: theme };
+ return {
+ ...options,
+ ...value,
+ light,
+ dark,
+ user: value,
+ };
};
-export const switchVariant = (theme: Theme) => {
+const switchVariant = (theme: Theme) => {
return {
...theme,
...theme.variant,
@@ -122,7 +138,7 @@ export const ContrastArea = ({
contrastText?: boolean;
}) => {
const oldTheme = useTheme();
- const theme = selectMode(oldTheme.builder, mode);
+ const theme: Theme = { ...oldTheme, ...oldTheme[mode] };
return (
.
*/
-import { ToastAndroid, PressableProps } from "react-native";
+import { ToastAndroid, Platform } from "react-native";
import { Theme } from "yoshiki/native";
export const tooltip = (tooltip: string) =>
- ({
- dataSet: { tooltip },
- onLongPress: () => {
- // TODO handle IOS.
- ToastAndroid.show(tooltip, ToastAndroid.SHORT);
+ Platform.select({
+ web: {
+ dataSet: { tooltip, label: tooltip },
},
- } satisfies PressableProps);
+ android: {
+ onLongPress: () => {
+ ToastAndroid.show(tooltip, ToastAndroid.SHORT);
+ },
+ },
+ default: {},
+ });
export const WebTooltip = ({ theme }: { theme: Theme }) => {
const background = `${theme.colors.black}CC`;
@@ -41,6 +45,7 @@ export const WebTooltip = ({ theme }: { theme: Theme }) => {
[data-tooltip]::after {
content: attr(data-tooltip);
+ display: flex;
position: absolute;
top: 100%;
@@ -55,6 +60,7 @@ export const WebTooltip = ({ theme }: { theme: Theme }) => {
color: ${theme.colors.white};
background-color: ${background};
font-family: ${theme.fonts.paragraph};
+ text-align: center;
opacity: 0;
visibility: hidden;
diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx
index 5db02e6f..1bba9361 100644
--- a/front/packages/ui/src/browse/header.tsx
+++ b/front/packages/ui/src/browse/header.tsx
@@ -18,6 +18,8 @@
* along with Kyoo. If not, see .
*/
+export {}
+
// const SortByMenu = ({
// sortKey,
// setSort,
diff --git a/front/packages/ui/src/details/header.tsx b/front/packages/ui/src/details/header.tsx
new file mode 100644
index 00000000..aefcb5d3
--- /dev/null
+++ b/front/packages/ui/src/details/header.tsx
@@ -0,0 +1,308 @@
+/*
+ * 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 { Movie, QueryIdentifier, Show, getDisplayDate } from "@kyoo/models";
+import {
+ Container,
+ H1,
+ Main,
+ ImageBackground,
+ Skeleton,
+ Poster,
+ P,
+ tooltip,
+ Link,
+ IconButton,
+ IconFab,
+} from "@kyoo/primitives";
+import { useTranslation } from "react-i18next";
+import { Platform, StyleSheet, View } from "react-native";
+import { em, percent, rem, vh, useYoshiki, Stylable } from "yoshiki/native";
+import { Fetch, WithLoading } from "../fetch";
+import { Navbar } from "../navbar";
+
+// const StudioText = ({
+// studio,
+// loading = false,
+// sx,
+// }: {
+// studio?: Studio | null;
+// loading?: boolean;
+// sx?: SxProps;
+// }) => {
+// const { t } = useTranslation("browse");
+
+// if (!loading && !studio) return null;
+// return (
+//
+// {t("show.studio")}:{" "}
+// {loading ? (
+//
+// ) : (
+// {studio!.name}
+// )}
+//
+// );
+// };
+
+const TitleLine = ({
+ isLoading,
+ slug,
+ name,
+ date,
+ poster,
+ ...props
+}: {
+ isLoading: boolean;
+ slug: string;
+ name?: string;
+ date?: string;
+ poster?: string | null;
+} & Stylable) => {
+ const { css, theme } = useYoshiki();
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+ {isLoading || (
+ ({ xs: theme.user.heading, md: theme.heading }),
+ })}
+ >
+ {name}
+
+ )}
+
+ {(isLoading || date) && (
+
+ {isLoading || (
+ ({ xs: theme.user.heading, md: theme.heading }),
+ })}
+ >
+ {date}
+
+ )}
+
+ )}
+ *": { m: ".3rem !important" } }} */>
+
+
+
+
+ {/* */}
+ {/* {(isLoading || logo || true) && ( */}
+ {/* */}
+ {/* )} */}
+ {/* {/1* *1/} */}
+ {/* */}
+
+ );
+};
+
+// const Tata = () => {
+// return (
+//
+//
+// {data
+// ? data.overview ?? t("show.noOverview")
+// : [...Array(4)].map((_, i) => )}
+//
+//
+//
+//
+
+//
+// {t("show.genre")}
+//
+// {!data || data.genres?.length ? (
+//
+// {(data ? data.genres! : [...Array(3)]).map((genre, i) => (
+//
+//
+// {genre ? {genre.name} : }
+//
+//
+// ))}
+//
+// ) : (
+// {t("show.genre-none")}
+// )}
+//
+//
+// );
+// };
+
+const min = Platform.OS === "web"
+ ? (...values: number[]): number => `min(${values.join(", ")})` as unknown as number
+ : (...values: number[]): number => Math.min(...values);
+const max = Platform.OS === "web"
+ ? (...values: number[]): number => `max(${values.join(", ")})` as unknown as number
+ : (...values: number[]): number => Math.max(...values);
+const px = Platform.OS === "web"
+ ? (value: number): number => `${value}px` as unknown as number
+ : (value: number): number => value;
+
+export const ShowHeader = ({
+ query,
+ slug,
+}: {
+ query: QueryIdentifier;
+ slug: string;
+}) => {
+ /* const scroll = useScroll(); */
+ const { css } = useYoshiki();
+ // TODO: tweek the navbar color with the theme.
+
+ return (
+ <>
+
+
+ {({ isLoading, ...data }) => (
+ <>
+ {/* TODO: HEAD element for SEO*/}
+ {/* TODO: Add a shadow on navbar items */}
+ {/* TODO: Put the navbar outside of the scrollbox */}
+
+
+ {/* */}
+ {/* */}
+ {/* */}
+ {/* {t("show.genre")} */}
+ {/* {": "} */}
+ {/* {!data ? ( */}
+ {/* */}
+ {/* ) : data?.genres && data.genres.length ? ( */}
+ {/* data.genres.map((genre, i) => [ */}
+ {/* i > 0 && ", ", */}
+ {/* */}
+ {/* {genre.name} */}
+ {/* , */}
+ {/* ]) */}
+ {/* ) : ( */}
+ {/* t("show.genre-none") */}
+ {/* )} */}
+ {/* */}
+ {/* */}
+
+ >
+ )}
+
+ >
+ );
+};
diff --git a/front/packages/ui/src/details/index.tsx b/front/packages/ui/src/details/index.tsx
new file mode 100644
index 00000000..f99e1951
--- /dev/null
+++ b/front/packages/ui/src/details/index.tsx
@@ -0,0 +1,47 @@
+/*
+ * 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 { Movie, MovieP, QueryIdentifier, QueryPage } from "@kyoo/models";
+import { ShowHeader } from "./header";
+
+const query = (slug: string): QueryIdentifier => ({
+ parser: MovieP,
+ path: ["shows", slug],
+ params: {
+ fields: ["genres", "studio"],
+ },
+});
+
+export const MovieDetails: QueryPage<{ slug: string }> = ({ slug }) => {
+ return (
+ <>
+ {/* */}
+ {/* {makeTitle(data?.name)} */}
+ {/* */}
+ {/* */}
+
+ {/* */}
+ >
+ );
+};
+
+MovieDetails.getFetchUrls = ({ slug }) => [//query(slug),
+ // ShowStaff.query(slug), Navbar.query()
+];
diff --git a/front/packages/ui/src/details/staff.tsx b/front/packages/ui/src/details/staff.tsx
new file mode 100644
index 00000000..1976b648
--- /dev/null
+++ b/front/packages/ui/src/details/staff.tsx
@@ -0,0 +1,47 @@
+/*
+ * 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 {}
+// export const ShowStaff = ({ slug }: { slug: string }) => {
+// const { items, isError, error } = useInfiniteFetch(ShowStaff.query(slug));
+// const { t } = useTranslation("browse");
+
+// // TODO: handle infinite scroll
+
+// if (isError) return ;
+
+// return (
+//
+// {(items ?? [...Array(20)]).map((x, i) => (
+//
+// ))}
+//
+// );
+// };
+
+// ShowStaff.query = (slug: string): QueryIdentifier => ({
+// parser: PersonP,
+// path: ["shows", slug, "people"],
+// infinite: true,
+// });
diff --git a/front/packages/ui/src/fetch.tsx b/front/packages/ui/src/fetch.tsx
index 49f4a074..5718726a 100644
--- a/front/packages/ui/src/fetch.tsx
+++ b/front/packages/ui/src/fetch.tsx
@@ -34,11 +34,11 @@ const isPage = (obj: unknown): obj is Page =>
export const Fetch = ({
query,
- placeholderCount,
+ placeholderCount = 1,
children,
}: {
query: QueryIdentifier;
- placeholderCount: number;
+ placeholderCount?: number;
children: (
item: Data extends Page ? WithLoading- : WithLoading
,
i: number,
@@ -52,7 +52,9 @@ export const Fetch = ({
<>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))}>
);
if (!isPage(data))
- return children(data ? { ...data, isLoading: false } : ({ isLoading: true } as any), 0);
+ return (
+ <> {children(data ? { ...data, isLoading: false } : ({ isLoading: true } as any), 0)} >
+ );
return <>{data.items.map((item, i) => children({ ...item, isLoading: false } as any, i))}>;
};
diff --git a/front/packages/ui/src/index.ts b/front/packages/ui/src/index.ts
index 117a3655..fb01a8a7 100644
--- a/front/packages/ui/src/index.ts
+++ b/front/packages/ui/src/index.ts
@@ -20,3 +20,4 @@
export * from "./navbar";
export { BrowsePage } from "./browse";
+export { MovieDetails } from "./details";
diff --git a/front/packages/ui/src/navbar/index.tsx b/front/packages/ui/src/navbar/index.tsx
index 6749d709..3443caf9 100644
--- a/front/packages/ui/src/navbar/index.tsx
+++ b/front/packages/ui/src/navbar/index.tsx
@@ -96,7 +96,7 @@ export const Navbar = (props: Stylable) => {
{library.name}
) : (
-
+
)
}
diff --git a/front/yarn.lock b/front/yarn.lock
index 7d6bb5e6..09120266 100644
--- a/front/yarn.lock
+++ b/front/yarn.lock
@@ -9682,7 +9682,7 @@ __metadata:
react-native-screens: ~3.18.0
react-native-svg: 13.4.0
typescript: ^4.6.3
- yoshiki: 0.2.9
+ yoshiki: 0.2.11
languageName: unknown
linkType: soft
@@ -13319,7 +13319,7 @@ __metadata:
superjson: ^1.11.0
typescript: ^4.9.3
webpack: ^5.75.0
- yoshiki: 0.2.9
+ yoshiki: 0.2.11
zod: ^3.19.1
languageName: unknown
linkType: soft
@@ -13644,9 +13644,9 @@ __metadata:
languageName: node
linkType: hard
-"yoshiki@npm:0.2.9":
- version: 0.2.9
- resolution: "yoshiki@npm:0.2.9"
+"yoshiki@npm:0.2.11":
+ version: 0.2.11
+ resolution: "yoshiki@npm:0.2.11"
dependencies:
"@types/node": 18.x.x
"@types/react": 18.x.x
@@ -13661,7 +13661,7 @@ __metadata:
optional: true
react-native-web:
optional: true
- checksum: 41ff5ff7e4cd99b2bc7453749a1f17ceb63bc9e1123285bc62a12315cac1fb087b58366db50e08b275e7dd0b1ce862df4c3acae51872f8e3aa8765ee9b61d4bf
+ checksum: 5a2bbb62b2270d3456f114cfbb24a84ad6b8a94b147687929ccffe2d179560ef40b46df1d4054eda91310d295a9a674bbb201765deb86dc96a2133bfd702235a
languageName: node
linkType: hard