From 2bf4b93b50fce7c76bef406c3e086dc16f0bda5e Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sat, 8 Jun 2024 18:19:08 +0930 Subject: [PATCH 01/12] Add media type filter --- front/packages/ui/src/browse/header.tsx | 171 ++++++++++++++++-------- front/packages/ui/src/browse/index.tsx | 16 ++- front/packages/ui/src/browse/types.ts | 27 ++++ front/translations/en.json | 8 ++ 4 files changed, 165 insertions(+), 57 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index ba75cabd..52ee29e6 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -34,12 +34,14 @@ import ArrowUpward from "@material-symbols/svg-400/rounded/arrow_upward.svg"; import GridView from "@material-symbols/svg-400/rounded/grid_view.svg"; import Sort from "@material-symbols/svg-400/rounded/sort.svg"; import Style from "@material-symbols/svg-400/rounded/style.svg"; +import FilterList from "@material-symbols/svg-400/rounded/filter_list.svg"; import ViewList from "@material-symbols/svg-400/rounded/view_list.svg"; -import { forwardRef } from "react"; +import {type ComponentType, forwardRef} from "react"; import { useTranslation } from "react-i18next"; import { type PressableProps, View } from "react-native"; import { useYoshiki } from "yoshiki/native"; -import { Layout, SearchSort, SortOrd } from "./types"; +import {AllMediaTypes, Layout, SearchSort, SortOrd} from "./types"; +import type {SvgProps} from "react-native-svg"; const SortTrigger = forwardRef(function SortTrigger( { sortKey, ...props }, @@ -60,11 +62,38 @@ const SortTrigger = forwardRef(funct ); }); +const MediaTypeTrigger = forwardRef(function MediaTypeTrigger( + { mediaType, ...props }, + ref, +) { + const { css } = useYoshiki(); + const { t } = useTranslation(); + const labelKey = mediaType ? `browse.mediatypekey.${mediaType.key}` : "browse.mediatypelabel"; + return ( + + +

{t(labelKey as any)}

+
+ ); +}); + +export interface MediaType { + key: string; + icon: ComponentType; +} + export const BrowseSettings = ({ availableSorts, sortKey, sortOrd, setSort, + availableMediaTypes, + mediaType, + setMediaType, layout, setLayout, }: { @@ -72,6 +101,9 @@ export const BrowseSettings = ({ sortKey: string; sortOrd: SortOrd; setSort: (sort: string, ord: SortOrd) => void; + availableMediaTypes: MediaType[]; + mediaType?: MediaType; + setMediaType: (mediaType?: MediaType) => void; layout: Layout; setLayout: (layout: Layout) => void; }) => { @@ -81,58 +113,91 @@ export const BrowseSettings = ({ // TODO: implement filters in the front. return ( - - {filters.length !== 0 && ( - - - {filters.map((x) => ( - - ))} + <> + + + + {availableSorts.map((x) => ( + + setSort(x, sortKey === x && sortOrd === SortOrd.Asc ? SortOrd.Desc : SortOrd.Asc) + } + /> + ))} + +
+ setLayout(Layout.Grid)} + color={layout === Layout.Grid ? theme.accent : undefined} + {...tooltip(t("browse.switchToGrid"))} + {...css({ padding: ts(0.5), marginY: "auto" })} + /> + setLayout(Layout.List)} + color={layout === Layout.List ? theme.accent : undefined} + {...tooltip(t("browse.switchToList"))} + {...css({ padding: ts(0.5), marginY: "auto" })} + /> +
+ + + {availableMediaTypes.map((x) => ( + { + if (mediaType === x || x === AllMediaTypes) { + setMediaType(undefined) + } else { + setMediaType(x) + } + }} + /> + ))} + - )} - - - {availableSorts.map((x) => ( - - setSort(x, sortKey === x && sortOrd === SortOrd.Asc ? SortOrd.Desc : SortOrd.Asc) - } - /> - ))} - -
- setLayout(Layout.Grid)} - color={layout === Layout.Grid ? theme.accent : undefined} - {...tooltip(t("browse.switchToGrid"))} - {...css({ padding: ts(0.5), marginY: "auto" })} - /> - setLayout(Layout.List)} - color={layout === Layout.List ? theme.accent : undefined} - {...tooltip(t("browse.switchToList"))} - {...css({ padding: ts(0.5), marginY: "auto" })} - />
-
+ + {filters.length !== 0 && ( + + {/**/} + {filters.map((x) => ( +
+ +
+ ))} +
+ )} +
+ ); }; diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index be1be7c9..5c5736b7 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -32,9 +32,9 @@ import { DefaultLayout } from "../layout"; import { ItemGrid } from "./grid"; import { BrowseSettings } from "./header"; import { ItemList } from "./list"; -import { Layout, SortBy, SortOrd } from "./types"; +import {Layout, MediaTypes, SortBy, SortOrd} from "./types"; -const { useParam } = createParam<{ sortBy?: string }>(); +const { useParam } = createParam<{ sortBy?: string, mediaType?: string }>(); export const itemMap = ( item: LibraryItem, @@ -52,27 +52,30 @@ export const itemMap = ( item.kind === "show" ? item.watchStatus?.unseenEpisodesCount ?? item.episodesCount! : null, }); -const query = (sortKey?: SortBy, sortOrd?: SortOrd): QueryIdentifier => ({ +const query = (sortKey?: SortBy, sortOrd?: SortOrd, mediaTypeKey?: string): QueryIdentifier => ({ parser: LibraryItemP, path: ["items"], infinite: true, params: { sortBy: sortKey ? `${sortKey}:${sortOrd ?? "asc"}` : "name:asc", + filter: mediaTypeKey && mediaTypeKey !== "none" ? `kind eq ${mediaTypeKey}` : undefined, fields: ["watchStatus", "episodesCount"], }, }); export const BrowsePage: QueryPage = () => { const [sort, setSort] = useParam("sortBy"); + const [mediaTypeKey, setMediaTypeKey] = useParam("mediaType"); const sortKey = (sort?.split(":")[0] as SortBy) || SortBy.Name; const sortOrd = (sort?.split(":")[1] as SortOrd) || SortOrd.Asc; + const mediaType = mediaTypeKey !== undefined ? MediaTypes.find(t => t.key === mediaTypeKey) : undefined; const [layout, setLayout] = useState(Layout.Grid); const LayoutComponent = layout === Layout.Grid ? ItemGrid : ItemList; return ( { setSort={(key, ord) => { setSort(`${key}:${ord}`); }} + mediaType={mediaType} + availableMediaTypes={MediaTypes} + setMediaType={(mediaType) => { + setMediaTypeKey(mediaType?.key); + }} layout={layout} setLayout={setLayout} /> diff --git a/front/packages/ui/src/browse/types.ts b/front/packages/ui/src/browse/types.ts index f44181e0..8153b26f 100644 --- a/front/packages/ui/src/browse/types.ts +++ b/front/packages/ui/src/browse/types.ts @@ -18,6 +18,12 @@ * along with Kyoo. If not, see . */ +import {MediaType} from "./header"; +import Collection from "@material-symbols/svg-400/rounded/collections_bookmark.svg"; +import TV from "@material-symbols/svg-400/rounded/tv.svg"; +import Movie from "@material-symbols/svg-400/rounded/movie.svg"; +import All from "@material-symbols/svg-400/rounded/view_headline.svg"; + export enum SortBy { Name = "name", StartAir = "startAir", @@ -42,3 +48,24 @@ export enum Layout { Grid, List, } + +export const AllMediaTypes: MediaType = { + key: "all", + icon: All +} + +export const MediaTypes: MediaType[] = [ + AllMediaTypes, + { + key: "movie", + icon: Movie + }, + { + key: "show", + icon: TV, + }, + { + key: "collection", + icon: Collection + } +]; diff --git a/front/translations/en.json b/front/translations/en.json index 059f58f0..38004535 100644 --- a/front/translations/en.json +++ b/front/translations/en.json @@ -43,6 +43,14 @@ "season": "Season {{number}}" }, "browse": { + "mediatypekey": { + "all": "All", + "movie": "Movies", + "show": "Series", + "collection": "Collection" + }, + "mediatype-tt": "Media Type", + "mediatypelabel": "Media Type", "sortby": "Sort by {{key}}", "sortby-tt": "Sort by", "sortkey": { From b8db1fb151c7f6b674a1ba52fc77699c814e08d2 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 10:38:57 +0930 Subject: [PATCH 02/12] Remove Chip filter list as it's not required right now --- front/packages/ui/src/browse/header.tsx | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index 52ee29e6..5deaf780 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -109,8 +109,6 @@ export const BrowseSettings = ({ }) => { const { css, theme } = useYoshiki(); const { t } = useTranslation(); - const filters: string[] = []; - // TODO: implement filters in the front. return ( <> @@ -178,26 +176,6 @@ export const BrowseSettings = ({
- - {filters.length !== 0 && ( - - {/**/} - {filters.map((x) => ( -
- -
- ))} -
- )} -
); }; From 20963c021b8ea685d1d78cf2708bc8399403cfbb Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 10:40:00 +0930 Subject: [PATCH 03/12] Tidy up based on review comments --- front/packages/ui/src/browse/header.tsx | 28 ++++----------- front/packages/ui/src/browse/index.tsx | 47 +++++++++++++++---------- front/packages/ui/src/browse/types.ts | 27 ++++++++++---- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index 5deaf780..daf21e3e 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -19,7 +19,6 @@ */ import { - Chip, HR, Icon, IconButton, @@ -33,15 +32,13 @@ import ArrowDownward from "@material-symbols/svg-400/rounded/arrow_downward.svg" import ArrowUpward from "@material-symbols/svg-400/rounded/arrow_upward.svg"; import GridView from "@material-symbols/svg-400/rounded/grid_view.svg"; import Sort from "@material-symbols/svg-400/rounded/sort.svg"; -import Style from "@material-symbols/svg-400/rounded/style.svg"; import FilterList from "@material-symbols/svg-400/rounded/filter_list.svg"; import ViewList from "@material-symbols/svg-400/rounded/view_list.svg"; -import {type ComponentType, forwardRef} from "react"; +import {forwardRef} from "react"; import { useTranslation } from "react-i18next"; import { type PressableProps, View } from "react-native"; import { useYoshiki } from "yoshiki/native"; -import {AllMediaTypes, Layout, SearchSort, SortOrd} from "./types"; -import type {SvgProps} from "react-native-svg"; +import {Layout, MediaType, MediaTypeAll, SearchSort, SortOrd} from "./types"; const SortTrigger = forwardRef(function SortTrigger( { sortKey, ...props }, @@ -62,13 +59,13 @@ const SortTrigger = forwardRef(funct ); }); -const MediaTypeTrigger = forwardRef(function MediaTypeTrigger( +const MediaTypeTrigger = forwardRef(function MediaTypeTrigger( { mediaType, ...props }, ref, ) { const { css } = useYoshiki(); const { t } = useTranslation(); - const labelKey = mediaType ? `browse.mediatypekey.${mediaType.key}` : "browse.mediatypelabel"; + const labelKey = mediaType !== MediaTypeAll ? `browse.mediatypekey.${mediaType.key}` : "browse.mediatypelabel"; return ( ; -} - export const BrowseSettings = ({ availableSorts, sortKey, @@ -102,8 +94,8 @@ export const BrowseSettings = ({ sortOrd: SortOrd; setSort: (sort: string, ord: SortOrd) => void; availableMediaTypes: MediaType[]; - mediaType?: MediaType; - setMediaType: (mediaType?: MediaType) => void; + mediaType: MediaType; + setMediaType: (mediaType: MediaType) => void; layout: Layout; setLayout: (layout: Layout) => void; }) => { @@ -164,13 +156,7 @@ export const BrowseSettings = ({ label={t(`browse.mediatypekey.${x.key}` as any)} selected={mediaType === x} icon={x.icon} - onSelect={() => { - if (mediaType === x || x === AllMediaTypes) { - setMediaType(undefined) - } else { - setMediaType(x) - } - }} + onSelect={() => setMediaType(x)} /> ))} diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index 5c5736b7..2ad96c77 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -32,7 +32,7 @@ import { DefaultLayout } from "../layout"; import { ItemGrid } from "./grid"; import { BrowseSettings } from "./header"; import { ItemList } from "./list"; -import {Layout, MediaTypes, SortBy, SortOrd} from "./types"; +import {MediaTypeAll, Layout, MediaTypes, SortBy, SortOrd, MediaTypeKey, MediaType} from "./types"; const { useParam } = createParam<{ sortBy?: string, mediaType?: string }>(); @@ -52,30 +52,38 @@ export const itemMap = ( item.kind === "show" ? item.watchStatus?.unseenEpisodesCount ?? item.episodesCount! : null, }); -const query = (sortKey?: SortBy, sortOrd?: SortOrd, mediaTypeKey?: string): QueryIdentifier => ({ - parser: LibraryItemP, - path: ["items"], - infinite: true, - params: { - sortBy: sortKey ? `${sortKey}:${sortOrd ?? "asc"}` : "name:asc", - filter: mediaTypeKey && mediaTypeKey !== "none" ? `kind eq ${mediaTypeKey}` : undefined, - fields: ["watchStatus", "episodesCount"], - }, -}); +const query = (mediaType: MediaType, sortKey?: SortBy, sortOrd?: SortOrd): QueryIdentifier => { + const filter = mediaType !== MediaTypeAll ? `kind eq ${mediaType.key}` : undefined; + return ({ + parser: LibraryItemP, + path: ["items"], + infinite: true, + params: { + sortBy: sortKey ? `${sortKey}:${sortOrd ?? "asc"}` : "name:asc", + filter, + fields: ["watchStatus", "episodesCount"], + }, + }); +} + +const getMediaTypeFromParam = (mediaTypeParam?: string): MediaType => { + const mediaTypeKey = mediaTypeParam as MediaTypeKey || MediaTypeKey.All; + return MediaTypes.find(t => t.key === mediaTypeKey) ?? MediaTypeAll; +} export const BrowsePage: QueryPage = () => { const [sort, setSort] = useParam("sortBy"); - const [mediaTypeKey, setMediaTypeKey] = useParam("mediaType"); + const [mediaTypeParam, setMediaTypeKey] = useParam("mediaType"); const sortKey = (sort?.split(":")[0] as SortBy) || SortBy.Name; const sortOrd = (sort?.split(":")[1] as SortOrd) || SortOrd.Asc; - const mediaType = mediaTypeKey !== undefined ? MediaTypes.find(t => t.key === mediaTypeKey) : undefined; const [layout, setLayout] = useState(Layout.Grid); + const mediaType = getMediaTypeFromParam(mediaTypeParam); const LayoutComponent = layout === Layout.Grid ? ItemGrid : ItemList; return ( { mediaType={mediaType} availableMediaTypes={MediaTypes} setMediaType={(mediaType) => { - setMediaTypeKey(mediaType?.key); + setMediaTypeKey(mediaType.key); }} layout={layout} setLayout={setLayout} @@ -102,6 +110,9 @@ export const BrowsePage: QueryPage = () => { BrowsePage.getLayout = DefaultLayout; -BrowsePage.getFetchUrls = ({ sortBy }) => [ - query(sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd), -]; +BrowsePage.getFetchUrls = ({ mediaType, sortBy }) => { + const mediaTypeObj = getMediaTypeFromParam(mediaType); + return[ + query(mediaTypeObj, sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd), + ]; +} diff --git a/front/packages/ui/src/browse/types.ts b/front/packages/ui/src/browse/types.ts index 8153b26f..b53de6e7 100644 --- a/front/packages/ui/src/browse/types.ts +++ b/front/packages/ui/src/browse/types.ts @@ -18,11 +18,12 @@ * along with Kyoo. If not, see . */ -import {MediaType} from "./header"; import Collection from "@material-symbols/svg-400/rounded/collections_bookmark.svg"; import TV from "@material-symbols/svg-400/rounded/tv.svg"; import Movie from "@material-symbols/svg-400/rounded/movie.svg"; import All from "@material-symbols/svg-400/rounded/view_headline.svg"; +import type {ComponentType} from "react"; +import type {SvgProps} from "react-native-svg"; export enum SortBy { Name = "name", @@ -49,23 +50,35 @@ export enum Layout { List, } -export const AllMediaTypes: MediaType = { - key: "all", +export enum MediaTypeKey{ + All = "all", + Movie = "movie", + Show = "show", + Collection = "collection", +} + +export interface MediaType { + key: MediaTypeKey; + icon: ComponentType; +} + +export const MediaTypeAll: MediaType = { + key: MediaTypeKey.All, icon: All } export const MediaTypes: MediaType[] = [ - AllMediaTypes, + MediaTypeAll, { - key: "movie", + key: MediaTypeKey.Movie, icon: Movie }, { - key: "show", + key: MediaTypeKey.Show, icon: TV, }, { - key: "collection", + key: MediaTypeKey.Collection, icon: Collection } ]; From 4810db554e74b1d629caef7f1f39ebba1148dae7 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 10:42:45 +0930 Subject: [PATCH 04/12] Fix formatting --- front/packages/ui/src/browse/header.tsx | 51 ++++++++++--------------- front/packages/ui/src/browse/index.tsx | 36 ++++++++++------- front/packages/ui/src/browse/types.ts | 16 ++++---- 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index daf21e3e..e16a34f7 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -18,27 +18,18 @@ * along with Kyoo. If not, see . */ -import { - HR, - Icon, - IconButton, - Menu, - P, - PressableFeedback, - tooltip, - ts, -} from "@kyoo/primitives"; +import { HR, Icon, IconButton, Menu, P, PressableFeedback, tooltip, ts } from "@kyoo/primitives"; import ArrowDownward from "@material-symbols/svg-400/rounded/arrow_downward.svg"; import ArrowUpward from "@material-symbols/svg-400/rounded/arrow_upward.svg"; import GridView from "@material-symbols/svg-400/rounded/grid_view.svg"; import Sort from "@material-symbols/svg-400/rounded/sort.svg"; import FilterList from "@material-symbols/svg-400/rounded/filter_list.svg"; import ViewList from "@material-symbols/svg-400/rounded/view_list.svg"; -import {forwardRef} from "react"; +import { forwardRef } from "react"; import { useTranslation } from "react-i18next"; import { type PressableProps, View } from "react-native"; import { useYoshiki } from "yoshiki/native"; -import {Layout, MediaType, MediaTypeAll, SearchSort, SortOrd} from "./types"; +import { Layout, MediaType, MediaTypeAll, SearchSort, SortOrd } from "./types"; const SortTrigger = forwardRef(function SortTrigger( { sortKey, ...props }, @@ -59,24 +50,24 @@ const SortTrigger = forwardRef(funct ); }); -const MediaTypeTrigger = forwardRef(function MediaTypeTrigger( - { mediaType, ...props }, - ref, -) { - const { css } = useYoshiki(); - const { t } = useTranslation(); - const labelKey = mediaType !== MediaTypeAll ? `browse.mediatypekey.${mediaType.key}` : "browse.mediatypelabel"; - return ( - - -

{t(labelKey as any)}

-
- ); -}); +const MediaTypeTrigger = forwardRef( + function MediaTypeTrigger({ mediaType, ...props }, ref) { + const { css } = useYoshiki(); + const { t } = useTranslation(); + const labelKey = + mediaType !== MediaTypeAll ? `browse.mediatypekey.${mediaType.key}` : "browse.mediatypelabel"; + return ( + + +

{t(labelKey as any)}

+
+ ); + }, +); export const BrowseSettings = ({ availableSorts, diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index 2ad96c77..fb25436a 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -32,9 +32,17 @@ import { DefaultLayout } from "../layout"; import { ItemGrid } from "./grid"; import { BrowseSettings } from "./header"; import { ItemList } from "./list"; -import {MediaTypeAll, Layout, MediaTypes, SortBy, SortOrd, MediaTypeKey, MediaType} from "./types"; +import { + MediaTypeAll, + Layout, + MediaTypes, + SortBy, + SortOrd, + MediaTypeKey, + MediaType, +} from "./types"; -const { useParam } = createParam<{ sortBy?: string, mediaType?: string }>(); +const { useParam } = createParam<{ sortBy?: string; mediaType?: string }>(); export const itemMap = ( item: LibraryItem, @@ -52,9 +60,13 @@ export const itemMap = ( item.kind === "show" ? item.watchStatus?.unseenEpisodesCount ?? item.episodesCount! : null, }); -const query = (mediaType: MediaType, sortKey?: SortBy, sortOrd?: SortOrd): QueryIdentifier => { +const query = ( + mediaType: MediaType, + sortKey?: SortBy, + sortOrd?: SortOrd, +): QueryIdentifier => { const filter = mediaType !== MediaTypeAll ? `kind eq ${mediaType.key}` : undefined; - return ({ + return { parser: LibraryItemP, path: ["items"], infinite: true, @@ -63,13 +75,13 @@ const query = (mediaType: MediaType, sortKey?: SortBy, sortOrd?: SortOrd): Query filter, fields: ["watchStatus", "episodesCount"], }, - }); -} + }; +}; const getMediaTypeFromParam = (mediaTypeParam?: string): MediaType => { - const mediaTypeKey = mediaTypeParam as MediaTypeKey || MediaTypeKey.All; - return MediaTypes.find(t => t.key === mediaTypeKey) ?? MediaTypeAll; -} + const mediaTypeKey = (mediaTypeParam as MediaTypeKey) || MediaTypeKey.All; + return MediaTypes.find((t) => t.key === mediaTypeKey) ?? MediaTypeAll; +}; export const BrowsePage: QueryPage = () => { const [sort, setSort] = useParam("sortBy"); @@ -112,7 +124,5 @@ BrowsePage.getLayout = DefaultLayout; BrowsePage.getFetchUrls = ({ mediaType, sortBy }) => { const mediaTypeObj = getMediaTypeFromParam(mediaType); - return[ - query(mediaTypeObj, sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd), - ]; -} + return [query(mediaTypeObj, sortBy?.split("-")[0] as SortBy, sortBy?.split("-")[1] as SortOrd)]; +}; diff --git a/front/packages/ui/src/browse/types.ts b/front/packages/ui/src/browse/types.ts index b53de6e7..186bea4a 100644 --- a/front/packages/ui/src/browse/types.ts +++ b/front/packages/ui/src/browse/types.ts @@ -22,8 +22,8 @@ import Collection from "@material-symbols/svg-400/rounded/collections_bookmark.s import TV from "@material-symbols/svg-400/rounded/tv.svg"; import Movie from "@material-symbols/svg-400/rounded/movie.svg"; import All from "@material-symbols/svg-400/rounded/view_headline.svg"; -import type {ComponentType} from "react"; -import type {SvgProps} from "react-native-svg"; +import type { ComponentType } from "react"; +import type { SvgProps } from "react-native-svg"; export enum SortBy { Name = "name", @@ -50,7 +50,7 @@ export enum Layout { List, } -export enum MediaTypeKey{ +export enum MediaTypeKey { All = "all", Movie = "movie", Show = "show", @@ -64,14 +64,14 @@ export interface MediaType { export const MediaTypeAll: MediaType = { key: MediaTypeKey.All, - icon: All -} + icon: All, +}; export const MediaTypes: MediaType[] = [ MediaTypeAll, { key: MediaTypeKey.Movie, - icon: Movie + icon: Movie, }, { key: MediaTypeKey.Show, @@ -79,6 +79,6 @@ export const MediaTypes: MediaType[] = [ }, { key: MediaTypeKey.Collection, - icon: Collection - } + icon: Collection, + }, ]; From 243768e01913e1b2230f25c284fc090af0dd57fa Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 10:46:10 +0930 Subject: [PATCH 05/12] Fixes from linter --- front/packages/ui/src/browse/header.tsx | 2 +- front/packages/ui/src/browse/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index e16a34f7..2fcb9ab1 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -29,7 +29,7 @@ import { forwardRef } from "react"; import { useTranslation } from "react-i18next"; import { type PressableProps, View } from "react-native"; import { useYoshiki } from "yoshiki/native"; -import { Layout, MediaType, MediaTypeAll, SearchSort, SortOrd } from "./types"; +import { Layout, type MediaType, MediaTypeAll, SearchSort, SortOrd } from "./types"; const SortTrigger = forwardRef(function SortTrigger( { sortKey, ...props }, diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index fb25436a..74b3674f 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -39,7 +39,7 @@ import { SortBy, SortOrd, MediaTypeKey, - MediaType, + type MediaType, } from "./types"; const { useParam } = createParam<{ sortBy?: string; mediaType?: string }>(); From 654faae847064b3b6ce574884c552b078da99092 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 11:25:36 +0930 Subject: [PATCH 06/12] Fix typo --- front/packages/ui/src/browse/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index 74b3674f..a6db6f06 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -85,7 +85,7 @@ const getMediaTypeFromParam = (mediaTypeParam?: string): MediaType => { export const BrowsePage: QueryPage = () => { const [sort, setSort] = useParam("sortBy"); - const [mediaTypeParam, setMediaTypeKey] = useParam("mediaType"); + const [mediaTypeParam, setMediaTypeParam] = useParam("mediaType"); const sortKey = (sort?.split(":")[0] as SortBy) || SortBy.Name; const sortOrd = (sort?.split(":")[1] as SortOrd) || SortOrd.Asc; const [layout, setLayout] = useState(Layout.Grid); @@ -108,7 +108,7 @@ export const BrowsePage: QueryPage = () => { mediaType={mediaType} availableMediaTypes={MediaTypes} setMediaType={(mediaType) => { - setMediaTypeKey(mediaType.key); + setMediaTypeParam(mediaType.key); }} layout={layout} setLayout={setLayout} From 881188c689d11c790ba86d15ef064d5faa1628b5 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 13:00:23 +0930 Subject: [PATCH 07/12] Fix icon when no media type selected --- front/packages/ui/src/browse/header.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index 2fcb9ab1..797878c0 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -56,13 +56,14 @@ const MediaTypeTrigger = forwardRef - +

{t(labelKey as any)}

); From 0b3f70e48ec0b862da1cc17ee002742baa03cf26 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 14:14:07 +0930 Subject: [PATCH 08/12] Fix search page --- front/packages/ui/src/browse/index.tsx | 9 ++++++--- front/packages/ui/src/search/index.tsx | 27 +++++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index a6db6f06..f66d3ac3 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -60,25 +60,28 @@ export const itemMap = ( item.kind === "show" ? item.watchStatus?.unseenEpisodesCount ?? item.episodesCount! : null, }); +export const createFilterString = (mediaType: MediaType): string | undefined => { + return mediaType !== MediaTypeAll ? `kind eq ${mediaType.key}` : undefined; +} + const query = ( mediaType: MediaType, sortKey?: SortBy, sortOrd?: SortOrd, ): QueryIdentifier => { - const filter = mediaType !== MediaTypeAll ? `kind eq ${mediaType.key}` : undefined; return { parser: LibraryItemP, path: ["items"], infinite: true, params: { sortBy: sortKey ? `${sortKey}:${sortOrd ?? "asc"}` : "name:asc", - filter, + filter: createFilterString(mediaType), fields: ["watchStatus", "episodesCount"], }, }; }; -const getMediaTypeFromParam = (mediaTypeParam?: string): MediaType => { +export const getMediaTypeFromParam = (mediaTypeParam?: string): MediaType => { const mediaTypeKey = (mediaTypeParam as MediaTypeKey) || MediaTypeKey.All; return MediaTypes.find((t) => t.key === mediaTypeKey) ?? MediaTypeAll; }; diff --git a/front/packages/ui/src/search/index.tsx b/front/packages/ui/src/search/index.tsx index 89ba727e..f67b3223 100644 --- a/front/packages/ui/src/search/index.tsx +++ b/front/packages/ui/src/search/index.tsx @@ -23,17 +23,18 @@ import { usePageStyle } from "@kyoo/primitives"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { createParam } from "solito"; -import { itemMap } from "../browse"; +import {createFilterString, getMediaTypeFromParam, itemMap} from "../browse"; import { ItemGrid } from "../browse/grid"; import { BrowseSettings } from "../browse/header"; import { ItemList } from "../browse/list"; -import { Layout, SearchSort, SortOrd } from "../browse/types"; +import {Layout, type MediaType, MediaTypes, SearchSort, SortOrd} from "../browse/types"; import { InfiniteFetch } from "../fetch-infinite"; import { DefaultLayout } from "../layout"; -const { useParam } = createParam<{ sortBy?: string }>(); +const { useParam } = createParam<{ sortBy?: string, mediaType?: string }>(); const query = ( + mediaType: MediaType, query?: string, sortKey?: SearchSort, sortOrd?: SortOrd, @@ -43,6 +44,7 @@ const query = ( infinite: true, params: { q: query, + filter: createFilterString(mediaType), sortBy: sortKey && sortKey !== SearchSort.Relevance ? `${sortKey}:${sortOrd ?? "asc"}` : undefined, }, @@ -52,15 +54,18 @@ export const SearchPage: QueryPage<{ q?: string }> = ({ q }) => { const pageStyle = usePageStyle(); const { t } = useTranslation(); const [sort, setSort] = useParam("sortBy"); + const [mediaTypeParam, setMediaTypeParam] = useParam("mediaType"); const sortKey = (sort?.split(":")[0] as SearchSort) || SearchSort.Relevance; const sortOrd = (sort?.split(":")[1] as SortOrd) || SortOrd.Asc; const [layout, setLayout] = useState(Layout.Grid); + const mediaType = getMediaTypeFromParam(mediaTypeParam); + console.log("search: mediaType", mediaType); const LayoutComponent = layout === Layout.Grid ? ItemGrid : ItemList; return ( = ({ q }) => { setSort={(key, ord) => { setSort(`${key}:${ord}`); }} + mediaType={mediaType} + availableMediaTypes={MediaTypes} + setMediaType={(mediaType) => { + setMediaTypeParam(mediaType.key); + }} layout={layout} setLayout={setLayout} /> @@ -84,6 +94,9 @@ export const SearchPage: QueryPage<{ q?: string }> = ({ q }) => { }; SearchPage.getLayout = DefaultLayout; -SearchPage.getFetchUrls = ({ q, sortBy }) => [ - query(q, sortBy?.split("-")[0] as SearchSort, sortBy?.split("-")[1] as SortOrd), -]; +SearchPage.getFetchUrls = ({ q, sortBy, mediaType }) => { + const mediaTypeObj = getMediaTypeFromParam(mediaType); + return [ + query(mediaTypeObj, q, sortBy?.split("-")[0] as SearchSort, sortBy?.split("-")[1] as SortOrd), + ]; +} From eafd5f593d2ba984ad792ce77728b9e4788614e1 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Sun, 9 Jun 2024 22:08:20 +0930 Subject: [PATCH 09/12] fix formatting --- front/packages/ui/src/browse/index.tsx | 2 +- front/packages/ui/src/search/index.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index f66d3ac3..d3cb214e 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -62,7 +62,7 @@ export const itemMap = ( export const createFilterString = (mediaType: MediaType): string | undefined => { return mediaType !== MediaTypeAll ? `kind eq ${mediaType.key}` : undefined; -} +}; const query = ( mediaType: MediaType, diff --git a/front/packages/ui/src/search/index.tsx b/front/packages/ui/src/search/index.tsx index f67b3223..6d6eba22 100644 --- a/front/packages/ui/src/search/index.tsx +++ b/front/packages/ui/src/search/index.tsx @@ -23,15 +23,15 @@ import { usePageStyle } from "@kyoo/primitives"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { createParam } from "solito"; -import {createFilterString, getMediaTypeFromParam, itemMap} from "../browse"; +import { createFilterString, getMediaTypeFromParam, itemMap } from "../browse"; import { ItemGrid } from "../browse/grid"; import { BrowseSettings } from "../browse/header"; import { ItemList } from "../browse/list"; -import {Layout, type MediaType, MediaTypes, SearchSort, SortOrd} from "../browse/types"; +import { Layout, type MediaType, MediaTypes, SearchSort, SortOrd } from "../browse/types"; import { InfiniteFetch } from "../fetch-infinite"; import { DefaultLayout } from "../layout"; -const { useParam } = createParam<{ sortBy?: string, mediaType?: string }>(); +const { useParam } = createParam<{ sortBy?: string; mediaType?: string }>(); const query = ( mediaType: MediaType, @@ -99,4 +99,4 @@ SearchPage.getFetchUrls = ({ q, sortBy, mediaType }) => { return [ query(mediaTypeObj, q, sortBy?.split("-")[0] as SearchSort, sortBy?.split("-")[1] as SortOrd), ]; -} +}; From f5faf06f812abb761d1ba59e945f199dfb7221b8 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Mon, 10 Jun 2024 10:03:06 +0930 Subject: [PATCH 10/12] remove debug log line --- front/packages/ui/src/search/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/front/packages/ui/src/search/index.tsx b/front/packages/ui/src/search/index.tsx index 6d6eba22..fd1283cc 100644 --- a/front/packages/ui/src/search/index.tsx +++ b/front/packages/ui/src/search/index.tsx @@ -60,7 +60,6 @@ export const SearchPage: QueryPage<{ q?: string }> = ({ q }) => { const [layout, setLayout] = useState(Layout.Grid); const mediaType = getMediaTypeFromParam(mediaTypeParam); - console.log("search: mediaType", mediaType); const LayoutComponent = layout === Layout.Grid ? ItemGrid : ItemList; return ( From 6f5513f11c7dcd597c687d477403119dd4fdb1fd Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Mon, 10 Jun 2024 10:03:20 +0930 Subject: [PATCH 11/12] remove unnecessary empty tags --- front/packages/ui/src/browse/header.tsx | 116 ++++++++++++------------ 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index 797878c0..1af26e9a 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -95,65 +95,63 @@ export const BrowseSettings = ({ const { t } = useTranslation(); return ( - <> - - - - {availableSorts.map((x) => ( - - setSort(x, sortKey === x && sortOrd === SortOrd.Asc ? SortOrd.Desc : SortOrd.Asc) - } - /> - ))} - -
- setLayout(Layout.Grid)} - color={layout === Layout.Grid ? theme.accent : undefined} - {...tooltip(t("browse.switchToGrid"))} - {...css({ padding: ts(0.5), marginY: "auto" })} - /> - setLayout(Layout.List)} - color={layout === Layout.List ? theme.accent : undefined} - {...tooltip(t("browse.switchToList"))} - {...css({ padding: ts(0.5), marginY: "auto" })} - /> -
- - - {availableMediaTypes.map((x) => ( - setMediaType(x)} - /> - ))} - - + + + + {availableSorts.map((x) => ( + + setSort(x, sortKey === x && sortOrd === SortOrd.Asc ? SortOrd.Desc : SortOrd.Asc) + } + /> + ))} + +
+ setLayout(Layout.Grid)} + color={layout === Layout.Grid ? theme.accent : undefined} + {...tooltip(t("browse.switchToGrid"))} + {...css({ padding: ts(0.5), marginY: "auto" })} + /> + setLayout(Layout.List)} + color={layout === Layout.List ? theme.accent : undefined} + {...tooltip(t("browse.switchToList"))} + {...css({ padding: ts(0.5), marginY: "auto" })} + />
- + + + {availableMediaTypes.map((x) => ( + setMediaType(x)} + /> + ))} + + +
); }; From dce3c5f5764414fdcad6fe9335786a47029473f3 Mon Sep 17 00:00:00 2001 From: Scott Merchant Date: Mon, 10 Jun 2024 10:12:19 +0930 Subject: [PATCH 12/12] fix import ordering --- front/packages/ui/src/browse/header.tsx | 2 +- front/packages/ui/src/browse/index.tsx | 6 +++--- front/packages/ui/src/browse/types.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/front/packages/ui/src/browse/header.tsx b/front/packages/ui/src/browse/header.tsx index 1af26e9a..e37a2e89 100644 --- a/front/packages/ui/src/browse/header.tsx +++ b/front/packages/ui/src/browse/header.tsx @@ -21,9 +21,9 @@ import { HR, Icon, IconButton, Menu, P, PressableFeedback, tooltip, ts } from "@kyoo/primitives"; import ArrowDownward from "@material-symbols/svg-400/rounded/arrow_downward.svg"; import ArrowUpward from "@material-symbols/svg-400/rounded/arrow_upward.svg"; +import FilterList from "@material-symbols/svg-400/rounded/filter_list.svg"; import GridView from "@material-symbols/svg-400/rounded/grid_view.svg"; import Sort from "@material-symbols/svg-400/rounded/sort.svg"; -import FilterList from "@material-symbols/svg-400/rounded/filter_list.svg"; import ViewList from "@material-symbols/svg-400/rounded/view_list.svg"; import { forwardRef } from "react"; import { useTranslation } from "react-i18next"; diff --git a/front/packages/ui/src/browse/index.tsx b/front/packages/ui/src/browse/index.tsx index d3cb214e..8cc69bf4 100644 --- a/front/packages/ui/src/browse/index.tsx +++ b/front/packages/ui/src/browse/index.tsx @@ -33,13 +33,13 @@ import { ItemGrid } from "./grid"; import { BrowseSettings } from "./header"; import { ItemList } from "./list"; import { - MediaTypeAll, Layout, + type MediaType, + MediaTypeAll, + MediaTypeKey, MediaTypes, SortBy, SortOrd, - MediaTypeKey, - type MediaType, } from "./types"; const { useParam } = createParam<{ sortBy?: string; mediaType?: string }>(); diff --git a/front/packages/ui/src/browse/types.ts b/front/packages/ui/src/browse/types.ts index 186bea4a..c914ab26 100644 --- a/front/packages/ui/src/browse/types.ts +++ b/front/packages/ui/src/browse/types.ts @@ -19,8 +19,8 @@ */ import Collection from "@material-symbols/svg-400/rounded/collections_bookmark.svg"; -import TV from "@material-symbols/svg-400/rounded/tv.svg"; import Movie from "@material-symbols/svg-400/rounded/movie.svg"; +import TV from "@material-symbols/svg-400/rounded/tv.svg"; import All from "@material-symbols/svg-400/rounded/view_headline.svg"; import type { ComponentType } from "react"; import type { SvgProps } from "react-native-svg";