}
+ {(isLoading || subtitle) && (
+ {isLoading || {subtitle}}
+ )}
+
+ );
+};
diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx
new file mode 100644
index 00000000..d2545cbf
--- /dev/null
+++ b/front/packages/ui/src/browse/index.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 { ComponentProps, useState } from "react";
+import {
+ QueryIdentifier,
+ QueryPage,
+ LibraryItem,
+ LibraryItemP,
+ ItemType,
+ getDisplayDate,
+} from "@kyoo/models";
+import { DefaultLayout } from "../layout";
+import { InfiniteFetch, WithLoading } from "../fetch";
+import { ItemGrid } from "./grid";
+import { SortBy, SortOrd, Layout } from "./types";
+
+const itemMap = (item: WithLoading): WithLoading> => {
+ if (item.isLoading) return item;
+
+ let href;
+ if (item?.type === ItemType.Movie) href = `/movie/${item.slug}`;
+ else if (item?.type === ItemType.Show) href = `/show/${item.slug}`;
+ else href = `/collection/${item.slug}`;
+
+ return {
+ isLoading: item.isLoading,
+ name: item.name,
+ subtitle: item.type !== ItemType.Collection ? getDisplayDate(item) : undefined,
+ href,
+ poster: item.poster,
+ };
+};
+
+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",
+ },
+});
+
+export const BrowsePage: QueryPage<{ slug?: string }> = ({ slug }) => {
+ const [sortKey, setSort] = useState(SortBy.Name);
+ const [sortOrd, setSortOrd] = useState(SortOrd.Asc);
+ const [layout, setLayout] = useState(Layout.Grid);
+
+ return (
+ <>
+ {/* */}
+
+ {(item, i) => }
+
+ >
+ );
+};
+
+BrowsePage.getLayout = DefaultLayout;
+
+BrowsePage.getFetchUrls = ({ slug, sortBy }) => [
+ query(slug, sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd),
+];
diff --git a/front/packages/ui/src/browse/list.tsx b/front/packages/ui/src/browse/list.tsx
new file mode 100644
index 00000000..bc34647f
--- /dev/null
+++ b/front/packages/ui/src/browse/list.tsx
@@ -0,0 +1,115 @@
+/*
+ * 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 .
+ */
+
+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 ?? }
+
+ )}
+
+
+
+ );
+};
diff --git a/front/packages/ui/src/browse/toto.tsx b/front/packages/ui/src/browse/toto.tsx
new file mode 100644
index 00000000..2a706490
--- /dev/null
+++ b/front/packages/ui/src/browse/toto.tsx
@@ -0,0 +1,188 @@
+/*
+ * 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 .
+ */
+
+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 (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ {sortAnchor && (
+ setSortAnchor(null)}
+ />
+ )}
+ >
+ );
+};
diff --git a/front/packages/ui/src/browse/types.ts b/front/packages/ui/src/browse/types.ts
new file mode 100644
index 00000000..0ceca512
--- /dev/null
+++ b/front/packages/ui/src/browse/types.ts
@@ -0,0 +1,35 @@
+/*
+ * 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 enum SortBy {
+ Name = "name",
+ StartAir = "startAir",
+ EndAir = "endAir",
+}
+
+export enum SortOrd {
+ Asc = "asc",
+ Desc = "desc",
+}
+
+export enum Layout {
+ Grid,
+ List,
+}
diff --git a/front/packages/ui/src/fetch.tsx b/front/packages/ui/src/fetch.tsx
index d4d7b437..925547ec 100644
--- a/front/packages/ui/src/fetch.tsx
+++ b/front/packages/ui/src/fetch.tsx
@@ -18,12 +18,14 @@
* along with Kyoo. If not, see .
*/
-import { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
+import { Page, QueryIdentifier, useFetch, KyooErrors, useInfiniteFetch } from "@kyoo/models";
import { P } from "@kyoo/primitives";
import { View } from "react-native";
import { useYoshiki } from "yoshiki/native";
-export type WithLoading = (Item & { isLoading: false }) | { isLoading: true };
+export type WithLoading =
+ | (Item & { isLoading: false })
+ | (Partial & { isLoading: true });
const isPage = (obj: unknown): obj is Page =>
(typeof obj === "object" && obj && "items" in obj) || false;
@@ -52,6 +54,29 @@ export const Fetch = ({
return <>{data.items.map((item, i) => children({ ...item, isLoading: false } as any, i))}>;
};
+export const InfiniteFetch = ({
+ query,
+ placeholderCount = 15,
+ children,
+}: {
+ query: QueryIdentifier;
+ placeholderCount?: number;
+ children: (
+ item: Data extends Page ? WithLoading : WithLoading,
+ i: number,
+ ) => JSX.Element | null;
+}): JSX.Element | null => {
+ if (!query.infinite) console.warn("A non infinite query was passed to an InfiniteFetch.");
+ const { items, error } = useInfiniteFetch(query);
+
+ if (error) return ;
+ if (!items)
+ return (
+ <>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))}>
+ );
+ return <>{items.map((item, i) => children({ ...item, isLoading: false } as any, i))}>;
+};
+
export const ErrorView = ({ error }: { error: KyooErrors }) => {
const { css } = useYoshiki();
@@ -60,7 +85,8 @@ export const ErrorView = ({ error }: { error: KyooErrors }) => {
{...css({
backgroundColor: (theme) => theme.colors.red,
flex: 1,
- alignItems: "center"
+ justifyContent: "center",
+ alignItems: "center",
})}
>
{error.errors.map((x, i) => (
diff --git a/front/packages/ui/src/index.ts b/front/packages/ui/src/index.ts
index 3ce76371..117a3655 100644
--- a/front/packages/ui/src/index.ts
+++ b/front/packages/ui/src/index.ts
@@ -19,3 +19,4 @@
*/
export * from "./navbar";
+export { BrowsePage } from "./browse";
diff --git a/front/packages/ui/src/layout.tsx b/front/packages/ui/src/layout.tsx
new file mode 100644
index 00000000..8f300e8e
--- /dev/null
+++ b/front/packages/ui/src/layout.tsx
@@ -0,0 +1,36 @@
+/*
+ * 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 { ReactElement } from "react";
+import { Navbar } from "./navbar";
+import { useYoshiki } from "yoshiki";
+
+export const DefaultLayout = (page: ReactElement) => {
+ const { css } = useYoshiki();
+
+ return (
+ <>
+
+ {page}
+ >
+ );
+};
+
+DefaultLayout.query = () => [Navbar.query()];