mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-30 10:12:36 -04:00 
			
		
		
		
	Create watchlist on the homepage
This commit is contained in:
		
							parent
							
								
									4cf9609153
								
							
						
					
					
						commit
						c87001d91e
					
				| @ -30,4 +30,5 @@ export * from "./episode"; | |||||||
| export * from "./season"; | export * from "./season"; | ||||||
| export * from "./watch-info"; | export * from "./watch-info"; | ||||||
| export * from "./watch-status"; | export * from "./watch-status"; | ||||||
|  | export * from "./watchlist"; | ||||||
| export * from "./user"; | export * from "./user"; | ||||||
|  | |||||||
							
								
								
									
										47
									
								
								front/packages/models/src/resources/watchlist.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								front/packages/models/src/resources/watchlist.ts
									
									
									
									
									
										Normal file
									
								
							| @ -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 <https://www.gnu.org/licenses/>.
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | import { z } from "zod"; | ||||||
|  | import { MovieP } from "./movie"; | ||||||
|  | import { ShowP } from "./show"; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * The type of item, ether a show, a movie or an episode. | ||||||
|  |  */ | ||||||
|  | export enum WatchlistKind { | ||||||
|  | 	Show = "Show", | ||||||
|  | 	Movie = "Movie", | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const WatchlistP = z.union([ | ||||||
|  | 	/* | ||||||
|  | 	 * Either a show | ||||||
|  | 	 */ | ||||||
|  | 	ShowP.and(z.object({ kind: z.literal(WatchlistKind.Show) })), | ||||||
|  | 	/* | ||||||
|  | 	 * Or a Movie | ||||||
|  | 	 */ | ||||||
|  | 	MovieP.and(z.object({ kind: z.literal(WatchlistKind.Movie) })), | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A item in the user's watchlist. | ||||||
|  |  */ | ||||||
|  | export type Watchlist = z.infer<typeof WatchlistP>; | ||||||
| @ -105,7 +105,7 @@ export const EpisodeBox = ({ | |||||||
| 				src={thumbnail} | 				src={thumbnail} | ||||||
| 				quality="low" | 				quality="low" | ||||||
| 				alt="" | 				alt="" | ||||||
| 				graditent={false} | 				gradient={false} | ||||||
| 				hideLoad={false} | 				hideLoad={false} | ||||||
| 				forcedLoading={isLoading} | 				forcedLoading={isLoading} | ||||||
| 				layout={{ width: percent(100), aspectRatio: 16 / 9 }} | 				layout={{ width: percent(100), aspectRatio: 16 / 9 }} | ||||||
|  | |||||||
| @ -28,6 +28,7 @@ import { Recommanded } from "./recommanded"; | |||||||
| import { VerticalRecommanded } from "./vertical"; | import { VerticalRecommanded } from "./vertical"; | ||||||
| import { NewsList } from "./news"; | import { NewsList } from "./news"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
|  | import { WatchlistList } from "./watchlist"; | ||||||
| 
 | 
 | ||||||
| export const HomePage: QueryPage<{}, Genre> = ({ randomItems }) => { | export const HomePage: QueryPage<{}, Genre> = ({ randomItems }) => { | ||||||
| 	const [isClient, setClient] = useState(false); | 	const [isClient, setClient] = useState(false); | ||||||
| @ -48,6 +49,7 @@ export const HomePage: QueryPage<{}, Genre> = ({ randomItems }) => { | |||||||
| 					/> | 					/> | ||||||
| 				)} | 				)} | ||||||
| 			</Fetch> | 			</Fetch> | ||||||
|  | 			<WatchlistList /> | ||||||
| 			<NewsList /> | 			<NewsList /> | ||||||
| 			{randomItems | 			{randomItems | ||||||
| 				.filter((_, i) => i < 2) | 				.filter((_, i) => i < 2) | ||||||
| @ -72,6 +74,7 @@ HomePage.getLayout = { Layout: DefaultLayout, props: { transparent: true } }; | |||||||
| 
 | 
 | ||||||
| HomePage.getFetchUrls = (_, randomItems) => [ | HomePage.getFetchUrls = (_, randomItems) => [ | ||||||
| 	Header.query(), | 	Header.query(), | ||||||
|  | 	WatchlistList.query(), | ||||||
| 	NewsList.query(), | 	NewsList.query(), | ||||||
| 	...randomItems.filter((_, i) => i < 6).map((x) => GenreGrid.query(x)), | 	...randomItems.filter((_, i) => i < 6).map((x) => GenreGrid.query(x)), | ||||||
| 	Recommanded.query(), | 	Recommanded.query(), | ||||||
|  | |||||||
							
								
								
									
										92
									
								
								front/packages/ui/src/home/watchlist.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								front/packages/ui/src/home/watchlist.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  | /* | ||||||
|  |  * 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 <https://www.gnu.org/licenses/>.
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | import { | ||||||
|  | 	QueryIdentifier, | ||||||
|  | 	Watchlist, | ||||||
|  | 	WatchlistKind, | ||||||
|  | 	WatchlistP, | ||||||
|  | 	getDisplayDate, | ||||||
|  | } from "@kyoo/models"; | ||||||
|  | import { useYoshiki } from "yoshiki/native"; | ||||||
|  | import { ItemGrid } from "../browse/grid"; | ||||||
|  | import { InfiniteFetch } from "../fetch-infinite"; | ||||||
|  | import { useTranslation } from "react-i18next"; | ||||||
|  | import { Header } from "./genre"; | ||||||
|  | import { EpisodeBox, episodeDisplayNumber } from "../details/episode"; | ||||||
|  | 
 | ||||||
|  | export const WatchlistList = () => { | ||||||
|  | 	const { t } = useTranslation(); | ||||||
|  | 	const { css } = useYoshiki(); | ||||||
|  | 
 | ||||||
|  | 	return ( | ||||||
|  | 		<> | ||||||
|  | 			<Header title={t("home.watchlist")} /> | ||||||
|  | 			<InfiniteFetch | ||||||
|  | 				query={WatchlistList.query()} | ||||||
|  | 				layout={{ ...ItemGrid.layout, layout: "horizontal" }} | ||||||
|  | 				getItemType={(x, i) => | ||||||
|  | 					(x.kind === WatchlistKind.Show && x.watchStatus?.nextEpisode) || (x.isLoading && i % 2) | ||||||
|  | 						? "episode" | ||||||
|  | 						: "item" | ||||||
|  | 				} | ||||||
|  | 				empty={t("home.none")} | ||||||
|  | 			> | ||||||
|  | 				{(x, i) => { | ||||||
|  | 					const episode = x.kind === WatchlistKind.Show ? x.watchStatus?.nextEpisode : null; | ||||||
|  | 					return (x.kind === WatchlistKind.Show && x.watchStatus?.nextEpisode) || | ||||||
|  | 						(x.isLoading && i % 2) ? ( | ||||||
|  | 						<EpisodeBox | ||||||
|  | 							isLoading={x.isLoading as any} | ||||||
|  | 							name={episode ? `${x.name} ${episodeDisplayNumber(episode)}` : undefined} | ||||||
|  | 							overview={episode?.name} | ||||||
|  | 							thumbnail={episode?.thumbnail ?? x.thumbnail} | ||||||
|  | 							href={episode?.href} | ||||||
|  | 							watchedPercent={x.watchStatus?.watchedPercent || null} | ||||||
|  | 							watchedStatus={x.watchStatus?.status || null} | ||||||
|  | 							// TODO: support this on mobile too
 | ||||||
|  | 							// @ts-expect-error This is a web only property
 | ||||||
|  | 							{...css({ gridColumnEnd: "span 2" })} | ||||||
|  | 						/> | ||||||
|  | 					) : ( | ||||||
|  | 						<ItemGrid | ||||||
|  | 							isLoading={x.isLoading as any} | ||||||
|  | 							href={x.href} | ||||||
|  | 							name={x.name!} | ||||||
|  | 							subtitle={!x.isLoading ? getDisplayDate(x) : undefined} | ||||||
|  | 							poster={x.poster} | ||||||
|  | 						/> | ||||||
|  | 					); | ||||||
|  | 				}} | ||||||
|  | 			</InfiniteFetch> | ||||||
|  | 		</> | ||||||
|  | 	); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | WatchlistList.query = (): QueryIdentifier<Watchlist> => ({ | ||||||
|  | 	parser: WatchlistP, | ||||||
|  | 	infinite: true, | ||||||
|  | 	path: ["watchlist"], | ||||||
|  | 	params: { | ||||||
|  | 		// Limit the inital numbers of items
 | ||||||
|  | 		limit: 10, | ||||||
|  | 		fields: ["watchStatus"], | ||||||
|  | 	}, | ||||||
|  | }); | ||||||
| @ -2,6 +2,7 @@ | |||||||
| 	"home": { | 	"home": { | ||||||
| 		"recommanded": "Recommanded", | 		"recommanded": "Recommanded", | ||||||
| 		"news": "News", | 		"news": "News", | ||||||
|  | 		"watchlist": "Continue watching", | ||||||
| 		"info": "See more", | 		"info": "See more", | ||||||
| 		"none": "No episodes" | 		"none": "No episodes" | ||||||
| 	}, | 	}, | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 	"home": { | 	"home": { | ||||||
| 		"recommanded": "Recommandé", | 		"recommanded": "Recommandé", | ||||||
| 		"news": "Nouveautés", | 		"news": "Nouveautés", | ||||||
|  | 		"watchlist": "Continuer de regarder", | ||||||
| 		"info": "Voir plus", | 		"info": "Voir plus", | ||||||
| 		"none": "Aucun episode" | 		"none": "Aucun episode" | ||||||
| 	}, | 	}, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user