mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-30 18:22:41 -04:00 
			
		
		
		
	Parse new fields in the front
This commit is contained in:
		
							parent
							
								
									5489f601d2
								
							
						
					
					
						commit
						f872deffb8
					
				
							
								
								
									
										75
									
								
								front/packages/models/src/resources/episode.base.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								front/packages/models/src/resources/episode.base.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | |||||||
|  | /* | ||||||
|  |  * 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 { zdate } from "../utils"; | ||||||
|  | import { withImages, imageFn } from "../traits"; | ||||||
|  | import { ResourceP } from "../traits/resource"; | ||||||
|  | 
 | ||||||
|  | export const BaseEpisodeP = withImages( | ||||||
|  | 	ResourceP.extend({ | ||||||
|  | 		/** | ||||||
|  | 		 * The season in witch this episode is in. | ||||||
|  | 		 */ | ||||||
|  | 		seasonNumber: z.number().nullable(), | ||||||
|  | 		/** | ||||||
|  | 		 * The number of this episode in it's season. | ||||||
|  | 		 */ | ||||||
|  | 		episodeNumber: z.number().nullable(), | ||||||
|  | 		/** | ||||||
|  | 		 * The absolute number of this episode. It's an episode number that is not reset to 1 after a new | ||||||
|  | 		 * season. | ||||||
|  | 		 */ | ||||||
|  | 		absoluteNumber: z.number().nullable(), | ||||||
|  | 		/** | ||||||
|  | 		 * The title of this episode. | ||||||
|  | 		 */ | ||||||
|  | 		name: z.string().nullable(), | ||||||
|  | 		/** | ||||||
|  | 		 * The overview of this episode. | ||||||
|  | 		 */ | ||||||
|  | 		overview: z.string().nullable(), | ||||||
|  | 		/** | ||||||
|  | 		 * How long is this movie? (in minutes). | ||||||
|  | 		 */ | ||||||
|  | 		runtime: z.number().int(), | ||||||
|  | 		/** | ||||||
|  | 		 * The release date of this episode. It can be null if unknown. | ||||||
|  | 		 */ | ||||||
|  | 		releaseDate: zdate().nullable(), | ||||||
|  | 		/** | ||||||
|  | 		 * The links to see a movie or an episode. | ||||||
|  | 		 */ | ||||||
|  | 		links: z.object({ | ||||||
|  | 			/** | ||||||
|  | 			 * The direct link to the unprocessed video (pristine quality). | ||||||
|  | 			 */ | ||||||
|  | 			direct: z.string().transform(imageFn), | ||||||
|  | 			/** | ||||||
|  | 			 * The link to an HLS master playlist containing all qualities available for this video. | ||||||
|  | 			 */ | ||||||
|  | 			hls: z.string().transform(imageFn), | ||||||
|  | 		}), | ||||||
|  | 	}), | ||||||
|  | 	"episodes", | ||||||
|  | ).transform((x) => ({ | ||||||
|  | 	...x, | ||||||
|  | 	href: `/watch/${x.slug}`, | ||||||
|  | })); | ||||||
| @ -19,64 +19,8 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import { z } from "zod"; | import { z } from "zod"; | ||||||
| import { zdate } from "../utils"; |  | ||||||
| import { withImages, imageFn } from "../traits"; |  | ||||||
| import { ResourceP } from "../traits/resource"; |  | ||||||
| import { ShowP } from "./show"; | import { ShowP } from "./show"; | ||||||
| 
 | import { BaseEpisodeP } from "./episode.base"; | ||||||
| export const BaseEpisodeP = withImages( |  | ||||||
| 	ResourceP.extend({ |  | ||||||
| 		/** |  | ||||||
| 		 * The season in witch this episode is in. |  | ||||||
| 		 */ |  | ||||||
| 		seasonNumber: z.number().nullable(), |  | ||||||
| 
 |  | ||||||
| 		/** |  | ||||||
| 		 * The number of this episode in it's season. |  | ||||||
| 		 */ |  | ||||||
| 		episodeNumber: z.number().nullable(), |  | ||||||
| 
 |  | ||||||
| 		/** |  | ||||||
| 		 * The absolute number of this episode. It's an episode number that is not reset to 1 after a new |  | ||||||
| 		 * season. |  | ||||||
| 		 */ |  | ||||||
| 		absoluteNumber: z.number().nullable(), |  | ||||||
| 
 |  | ||||||
| 		/** |  | ||||||
| 		 * The title of this episode. |  | ||||||
| 		 */ |  | ||||||
| 		name: z.string().nullable(), |  | ||||||
| 
 |  | ||||||
| 		/** |  | ||||||
| 		 * The overview of this episode. |  | ||||||
| 		 */ |  | ||||||
| 		overview: z.string().nullable(), |  | ||||||
| 
 |  | ||||||
| 		/** |  | ||||||
| 		 * The release date of this episode. It can be null if unknown. |  | ||||||
| 		 */ |  | ||||||
| 		releaseDate: zdate().nullable(), |  | ||||||
| 
 |  | ||||||
| 		/** |  | ||||||
| 		 * The links to see a movie or an episode. |  | ||||||
| 		 */ |  | ||||||
| 		links: z.object({ |  | ||||||
| 			/** |  | ||||||
| 			 * The direct link to the unprocessed video (pristine quality). |  | ||||||
| 			 */ |  | ||||||
| 			direct: z.string().transform(imageFn), |  | ||||||
| 
 |  | ||||||
| 			/** |  | ||||||
| 			 * The link to an HLS master playlist containing all qualities available for this video. |  | ||||||
| 			 */ |  | ||||||
| 			hls: z.string().transform(imageFn), |  | ||||||
| 		}), |  | ||||||
| 	}), |  | ||||||
| 	"episodes", |  | ||||||
| ).transform((x) => ({ |  | ||||||
| 	...x, |  | ||||||
| 	href: `/watch/${x.slug}`, |  | ||||||
| })); |  | ||||||
| 
 | 
 | ||||||
| export const EpisodeP = BaseEpisodeP.and( | export const EpisodeP = BaseEpisodeP.and( | ||||||
| 	z.object({ | 	z.object({ | ||||||
|  | |||||||
| @ -51,6 +51,14 @@ export const MovieP = withImages( | |||||||
| 		 * /** Is this movie not aired yet or finished? | 		 * /** Is this movie not aired yet or finished? | ||||||
| 		 */ | 		 */ | ||||||
| 		status: z.nativeEnum(Status), | 		status: z.nativeEnum(Status), | ||||||
|  | 		/** | ||||||
|  | 		 * How well this item is rated? (from 0 to 100). | ||||||
|  | 		 */ | ||||||
|  | 		rating: z.number().int().gte(0).lte(100), | ||||||
|  | 		/** | ||||||
|  | 		 * How long is this movie? (in minutes). | ||||||
|  | 		 */ | ||||||
|  | 		runtime: z.number().int(), | ||||||
| 		/** | 		/** | ||||||
| 		 * The date this movie aired. It can also be null if this is unknown. | 		 * The date this movie aired. It can also be null if this is unknown. | ||||||
| 		 */ | 		 */ | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ | |||||||
| 
 | 
 | ||||||
| import { z } from "zod"; | import { z } from "zod"; | ||||||
| import { MovieP } from "./movie"; | import { MovieP } from "./movie"; | ||||||
| import { BaseEpisodeP } from "./episode"; | import { BaseEpisodeP } from "./episode.base"; | ||||||
| import { ResourceP } from "../traits/resource"; | import { ResourceP } from "../traits/resource"; | ||||||
| import { withImages } from "../traits/images"; | import { withImages } from "../traits/images"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,6 +24,7 @@ import { withImages, ResourceP } from "../traits"; | |||||||
| import { Genre } from "./genre"; | import { Genre } from "./genre"; | ||||||
| import { SeasonP } from "./season"; | import { SeasonP } from "./season"; | ||||||
| import { StudioP } from "./studio"; | import { StudioP } from "./studio"; | ||||||
|  | import { BaseEpisodeP } from "./episode.base"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The enum containing show's status. |  * The enum containing show's status. | ||||||
| @ -61,6 +62,10 @@ export const ShowP = withImages( | |||||||
| 		 * Is this show airing, not aired yet or finished? | 		 * Is this show airing, not aired yet or finished? | ||||||
| 		 */ | 		 */ | ||||||
| 		status: z.nativeEnum(Status), | 		status: z.nativeEnum(Status), | ||||||
|  | 		/** | ||||||
|  | 		 * How well this item is rated? (from 0 to 100). | ||||||
|  | 		 */ | ||||||
|  | 		rating: z.number().int().gte(0).lte(100), | ||||||
| 		/** | 		/** | ||||||
| 		 * The date this show started airing. It can be null if this is unknown. | 		 * The date this show started airing. It can be null if this is unknown. | ||||||
| 		 */ | 		 */ | ||||||
| @ -85,6 +90,10 @@ export const ShowP = withImages( | |||||||
| 		 * The list of seasons of this show. | 		 * The list of seasons of this show. | ||||||
| 		 */ | 		 */ | ||||||
| 		seasons: z.array(SeasonP).optional(), | 		seasons: z.array(SeasonP).optional(), | ||||||
|  | 		/** | ||||||
|  | 		 * The first episode of this show | ||||||
|  | 		 */ | ||||||
|  | 		firstEpisode: BaseEpisodeP.optional().nullable(), | ||||||
| 	}), | 	}), | ||||||
| 	"shows", | 	"shows", | ||||||
| ) | ) | ||||||
| @ -100,7 +109,7 @@ export const ShowP = withImages( | |||||||
| 	}) | 	}) | ||||||
| 	.transform((x) => ({ | 	.transform((x) => ({ | ||||||
| 		href: `/show/${x.slug}`, | 		href: `/show/${x.slug}`, | ||||||
| 		playHref: `/watch/${x.slug}-s1e1`, | 		playHref: x.firstEpisode ? `/watch/${x.firstEpisode.slug}` : null, | ||||||
| 		...x, | 		...x, | ||||||
| 	})); | 	})); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -80,7 +80,7 @@ const TitleLine = ({ | |||||||
| 	...props | 	...props | ||||||
| }: { | }: { | ||||||
| 	isLoading: boolean; | 	isLoading: boolean; | ||||||
| 	playHref?: string; | 	playHref?: string | null; | ||||||
| 	name?: string; | 	name?: string; | ||||||
| 	tagline?: string | null; | 	tagline?: string | null; | ||||||
| 	date?: string | null; | 	date?: string | null; | ||||||
| @ -192,6 +192,7 @@ const TitleLine = ({ | |||||||
| 						</Skeleton> | 						</Skeleton> | ||||||
| 					)} | 					)} | ||||||
| 					<View {...css({ flexDirection: "row" })}> | 					<View {...css({ flexDirection: "row" })}> | ||||||
|  | 						{playHref !== null && ( | ||||||
| 							<IconFab | 							<IconFab | ||||||
| 								icon={PlayArrow} | 								icon={PlayArrow} | ||||||
| 								as={Link} | 								as={Link} | ||||||
| @ -203,6 +204,7 @@ const TitleLine = ({ | |||||||
| 								})} | 								})} | ||||||
| 								{...tooltip(t("show.play"))} | 								{...tooltip(t("show.play"))} | ||||||
| 							/> | 							/> | ||||||
|  | 						)} | ||||||
| 						{trailerUrl && ( | 						{trailerUrl && ( | ||||||
| 							<IconButton | 							<IconButton | ||||||
| 								icon={Theaters} | 								icon={Theaters} | ||||||
|  | |||||||
| @ -85,7 +85,7 @@ const query = (slug: string): QueryIdentifier<Show> => ({ | |||||||
| 	parser: ShowP, | 	parser: ShowP, | ||||||
| 	path: ["shows", slug], | 	path: ["shows", slug], | ||||||
| 	params: { | 	params: { | ||||||
| 		fields: ["studio"], | 		fields: ["studio", "firstEpisode"], | ||||||
| 	}, | 	}, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -52,7 +52,7 @@ export const Header = ({ | |||||||
| 	thumbnail: KyooImage | null; | 	thumbnail: KyooImage | null; | ||||||
| 	overview: string | null; | 	overview: string | null; | ||||||
| 	tagline: string | null; | 	tagline: string | null; | ||||||
| 	link: string; | 	link: string | null; | ||||||
| 	infoLink: string; | 	infoLink: string; | ||||||
| }>) => { | }>) => { | ||||||
| 	const { css } = useYoshiki(); | 	const { css } = useYoshiki(); | ||||||
| @ -70,6 +70,7 @@ export const Header = ({ | |||||||
| 			> | 			> | ||||||
| 				<H1>{name}</H1> | 				<H1>{name}</H1> | ||||||
| 				<View {...css({ flexDirection: "row" })}> | 				<View {...css({ flexDirection: "row" })}> | ||||||
|  | 					{link !== null && ( | ||||||
| 						<IconFab | 						<IconFab | ||||||
| 							icon={PlayArrow} | 							icon={PlayArrow} | ||||||
| 							aria-label={t("show.play")} | 							aria-label={t("show.play")} | ||||||
| @ -78,6 +79,7 @@ export const Header = ({ | |||||||
| 							{...tooltip(t("show.play"))} | 							{...tooltip(t("show.play"))} | ||||||
| 							{...css({ marginRight: ts(1) })} | 							{...css({ marginRight: ts(1) })} | ||||||
| 						/> | 						/> | ||||||
|  | 					)} | ||||||
| 					<IconButton | 					<IconButton | ||||||
| 						icon={Info} | 						icon={Info} | ||||||
| 						aria-label={t("home.info")} | 						aria-label={t("home.info")} | ||||||
| @ -96,4 +98,7 @@ export const Header = ({ | |||||||
| Header.query = (): QueryIdentifier<LibraryItem> => ({ | Header.query = (): QueryIdentifier<LibraryItem> => ({ | ||||||
| 	parser: LibraryItemP, | 	parser: LibraryItemP, | ||||||
| 	path: ["items", "random"], | 	path: ["items", "random"], | ||||||
|  | 	params: { | ||||||
|  | 		fields: "firstEpisode", | ||||||
|  | 	}, | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -66,7 +66,7 @@ export const ItemDetails = ({ | |||||||
| 	genres: Genre[] | null; | 	genres: Genre[] | null; | ||||||
| 	overview: string | null; | 	overview: string | null; | ||||||
| 	href: string; | 	href: string; | ||||||
| 	playHref: string; | 	playHref: string | null; | ||||||
| }>) => { | }>) => { | ||||||
| 	const { push } = useRouter(); | 	const { push } = useRouter(); | ||||||
| 	const { css } = useYoshiki("recommanded-card"); | 	const { css } = useYoshiki("recommanded-card"); | ||||||
| @ -136,6 +136,7 @@ export const ItemDetails = ({ | |||||||
| 					<ScrollView horizontal> | 					<ScrollView horizontal> | ||||||
| 						{genres?.map((x) => <Chip key={x} label={x} {...css({ mX: ts(0.5) })} />)} | 						{genres?.map((x) => <Chip key={x} label={x} {...css({ mX: ts(0.5) })} />)} | ||||||
| 					</ScrollView> | 					</ScrollView> | ||||||
|  | 					{playHref !== null && ( | ||||||
| 						<IconFab | 						<IconFab | ||||||
| 							icon={PlayArrow} | 							icon={PlayArrow} | ||||||
| 							size={20} | 							size={20} | ||||||
| @ -143,6 +144,7 @@ export const ItemDetails = ({ | |||||||
| 							onPress={() => push(playHref ?? "")} | 							onPress={() => push(playHref ?? "")} | ||||||
| 							{...css({ fover: { self: { transform: "scale(1.2)" as any, mX: ts(0.5) } } })} | 							{...css({ fover: { self: { transform: "scale(1.2)" as any, mX: ts(0.5) } } })} | ||||||
| 						/> | 						/> | ||||||
|  | 					)} | ||||||
| 				</View> | 				</View> | ||||||
| 			</View> | 			</View> | ||||||
| 		</Link> | 		</Link> | ||||||
| @ -197,5 +199,6 @@ Recommanded.query = (): QueryIdentifier<LibraryItem> => ({ | |||||||
| 	params: { | 	params: { | ||||||
| 		sortBy: "random", | 		sortBy: "random", | ||||||
| 		limit: 6, | 		limit: 6, | ||||||
|  | 		fields: "firstEpisode", | ||||||
| 	}, | 	}, | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user