mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-03 05:34:23 -04:00
Add play button on the recommanded card
This commit is contained in:
parent
e4562648ba
commit
872639dab9
@ -21,16 +21,21 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { ImagesP, ResourceP } from "../traits";
|
import { ImagesP, ResourceP } from "../traits";
|
||||||
|
|
||||||
export const CollectionP = ResourceP.merge(ImagesP).extend({
|
export const CollectionP = ResourceP.merge(ImagesP)
|
||||||
/**
|
.extend({
|
||||||
* The title of this collection.
|
/**
|
||||||
*/
|
* The title of this collection.
|
||||||
name: z.string(),
|
*/
|
||||||
/**
|
name: z.string(),
|
||||||
* The summary of this show.
|
/**
|
||||||
*/
|
* The summary of this show.
|
||||||
overview: z.string().nullable(),
|
*/
|
||||||
});
|
overview: z.string().nullable(),
|
||||||
|
})
|
||||||
|
.transform((x) => ({
|
||||||
|
...x,
|
||||||
|
href: `/collection/${x.slug}`,
|
||||||
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class representing collections of show or movies.
|
* A class representing collections of show or movies.
|
||||||
|
@ -36,24 +36,15 @@ export const LibraryItemP = z.union([
|
|||||||
/*
|
/*
|
||||||
* Either a Show
|
* Either a Show
|
||||||
*/
|
*/
|
||||||
ShowP.and(z.object({ kind: z.literal(ItemKind.Show) })).transform((x) => ({
|
ShowP.and(z.object({ kind: z.literal(ItemKind.Show) })),
|
||||||
...x,
|
|
||||||
href: `/show/${x.slug}`,
|
|
||||||
})),
|
|
||||||
/*
|
/*
|
||||||
* Or a Movie
|
* Or a Movie
|
||||||
*/
|
*/
|
||||||
MovieP.and(z.object({ kind: z.literal(ItemKind.Movie) })).transform((x) => ({
|
MovieP.and(z.object({ kind: z.literal(ItemKind.Movie) })),
|
||||||
...x,
|
|
||||||
href: `/movie/${x.slug}`,
|
|
||||||
})),
|
|
||||||
/*
|
/*
|
||||||
* Or a Collection
|
* Or a Collection
|
||||||
*/
|
*/
|
||||||
CollectionP.and(z.object({ kind: z.literal(ItemKind.Collection) })).transform((x) => ({
|
CollectionP.and(z.object({ kind: z.literal(ItemKind.Collection) })),
|
||||||
...x,
|
|
||||||
href: `/collection/${x.slug}`,
|
|
||||||
})),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +92,12 @@ export const MovieP = ResourceP.merge(ImagesP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
});
|
})
|
||||||
|
.transform((x) => ({
|
||||||
|
...x,
|
||||||
|
href: `/movie/${x.slug}`,
|
||||||
|
playHref: `/movie/${x.slug}/watch`,
|
||||||
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Movie type
|
* A Movie type
|
||||||
|
@ -95,7 +95,13 @@ export const ShowP = ResourceP.merge(ImagesP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
});
|
})
|
||||||
|
.transform((x) => ({
|
||||||
|
href: `/show/${x.slug}`,
|
||||||
|
playHref: `/watch/${x.slug}-s1e1`,
|
||||||
|
...x,
|
||||||
|
}))
|
||||||
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tv serie or an anime.
|
* A tv serie or an anime.
|
||||||
|
@ -86,9 +86,9 @@ export const Link = ({
|
|||||||
target,
|
target,
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: { href: string; target?: string; replace?: boolean } & PressableProps) => {
|
}: { href?: string; target?: string; replace?: boolean } & PressableProps) => {
|
||||||
const linkProps = useLink({
|
const linkProps = useLink({
|
||||||
href,
|
href: href ?? "#",
|
||||||
replace,
|
replace,
|
||||||
experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false },
|
experimental: { nativeBehavior: "stack-replace", isNestedNavigator: false },
|
||||||
});
|
});
|
||||||
|
@ -69,7 +69,7 @@ import Theaters from "@material-symbols/svg-400/rounded/theaters-fill.svg";
|
|||||||
|
|
||||||
const TitleLine = ({
|
const TitleLine = ({
|
||||||
isLoading,
|
isLoading,
|
||||||
slug,
|
playHref,
|
||||||
name,
|
name,
|
||||||
tagline,
|
tagline,
|
||||||
date,
|
date,
|
||||||
@ -80,7 +80,7 @@ const TitleLine = ({
|
|||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
slug: string;
|
playHref?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
tagline?: string | null;
|
tagline?: string | null;
|
||||||
date?: string | null;
|
date?: string | null;
|
||||||
@ -195,7 +195,7 @@ const TitleLine = ({
|
|||||||
<IconFab
|
<IconFab
|
||||||
icon={PlayArrow}
|
icon={PlayArrow}
|
||||||
as={Link}
|
as={Link}
|
||||||
href={type === "show" ? `/watch/${slug}` : `/movie/${slug}/watch`}
|
href={playHref}
|
||||||
color={{ xs: theme.user.colors.black, md: theme.colors.black }}
|
color={{ xs: theme.user.colors.black, md: theme.colors.black }}
|
||||||
{...css({
|
{...css({
|
||||||
bg: theme.user.accent,
|
bg: theme.user.accent,
|
||||||
@ -346,11 +346,9 @@ const Description = ({
|
|||||||
export const Header = ({
|
export const Header = ({
|
||||||
query,
|
query,
|
||||||
type,
|
type,
|
||||||
slug,
|
|
||||||
}: {
|
}: {
|
||||||
query: QueryIdentifier<Show | Movie>;
|
query: QueryIdentifier<Show | Movie>;
|
||||||
type: "movie" | "show";
|
type: "movie" | "show";
|
||||||
slug: string;
|
|
||||||
}) => {
|
}) => {
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
@ -376,7 +374,7 @@ export const Header = ({
|
|||||||
<TitleLine
|
<TitleLine
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
type={type}
|
type={type}
|
||||||
slug={slug}
|
playHref={data?.playHref}
|
||||||
name={data?.name}
|
name={data?.name}
|
||||||
tagline={data?.tagline}
|
tagline={data?.tagline}
|
||||||
date={data ? getDisplayDate(data as any) : undefined}
|
date={data ? getDisplayDate(data as any) : undefined}
|
||||||
|
@ -68,8 +68,7 @@ const ShowHeader = forwardRef<View, ViewProps & { slug: string }>(function ShowH
|
|||||||
props,
|
props,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* TODO: Remove the slug quickfix for the play button */}
|
<Header type="show" query={query(slug)} />
|
||||||
<Header slug={`${slug}-s1e1`} type="show" query={query(slug)} />
|
|
||||||
{/* <Staff slug={slug} /> */}
|
{/* <Staff slug={slug} /> */}
|
||||||
<SvgWave
|
<SvgWave
|
||||||
fill={theme.variant.background}
|
fill={theme.variant.background}
|
||||||
|
@ -37,19 +37,23 @@ export const HomePage: QueryPage<{}, Genre> = ({ randomItems }) => {
|
|||||||
tagline={"tagline" in x ? x.tagline : null}
|
tagline={"tagline" in x ? x.tagline : null}
|
||||||
overview={x.overview}
|
overview={x.overview}
|
||||||
thumbnail={x.thumbnail}
|
thumbnail={x.thumbnail}
|
||||||
link={x.kind === ItemKind.Show ? `/watch/${x.slug}-s1e1` : `/movie/${x.slug}/watch`}
|
link={x.kind !== ItemKind.Collection && !x.isLoading ? x.playHref : undefined}
|
||||||
infoLink={x.href}
|
infoLink={x.href}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Fetch>
|
</Fetch>
|
||||||
{/* <News /> */}
|
{/* <News /> */}
|
||||||
{randomItems.filter((_, i) => i < 2).map((x) =>
|
{randomItems
|
||||||
<GenreGrid key={x} genre={x} />,
|
.filter((_, i) => i < 2)
|
||||||
)}
|
.map((x) => (
|
||||||
|
<GenreGrid key={x} genre={x} />
|
||||||
|
))}
|
||||||
<Recommanded />
|
<Recommanded />
|
||||||
{randomItems.filter((_, i) => i >= 2).map((x) =>
|
{randomItems
|
||||||
<GenreGrid key={x} genre={x} />,
|
.filter((_, i) => i >= 2)
|
||||||
)}
|
.map((x) => (
|
||||||
|
<GenreGrid key={x} genre={x} />
|
||||||
|
))}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -29,12 +29,25 @@ import {
|
|||||||
QueryIdentifier,
|
QueryIdentifier,
|
||||||
getDisplayDate,
|
getDisplayDate,
|
||||||
} from "@kyoo/models";
|
} from "@kyoo/models";
|
||||||
import { Chip, Container, H3, ImageBackground, P, Poster, SubP, alpha, ts } from "@kyoo/primitives";
|
import {
|
||||||
|
Chip,
|
||||||
|
Container,
|
||||||
|
H3,
|
||||||
|
IconFab,
|
||||||
|
ImageBackground,
|
||||||
|
Link,
|
||||||
|
P,
|
||||||
|
Poster,
|
||||||
|
SubP,
|
||||||
|
alpha,
|
||||||
|
ts,
|
||||||
|
} from "@kyoo/primitives";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ScrollView, View } from "react-native";
|
import { ScrollView, View } from "react-native";
|
||||||
import { percent, px, useYoshiki } from "yoshiki/native";
|
import { calc, percent, px, rem, useYoshiki } from "yoshiki/native";
|
||||||
import { Fetch, Layout, WithLoading } from "../fetch";
|
import { Fetch, Layout, WithLoading } from "../fetch";
|
||||||
import { InfiniteFetch } from "../fetch-infinite";
|
import { InfiniteFetch } from "../fetch-infinite";
|
||||||
|
import PlayArrow from "@material-symbols/svg-400/rounded/play_arrow-fill.svg";
|
||||||
|
|
||||||
export const ItemDetails = ({
|
export const ItemDetails = ({
|
||||||
isLoading,
|
isLoading,
|
||||||
@ -44,6 +57,7 @@ export const ItemDetails = ({
|
|||||||
overview,
|
overview,
|
||||||
poster,
|
poster,
|
||||||
genres,
|
genres,
|
||||||
|
playHref,
|
||||||
...props
|
...props
|
||||||
}: WithLoading<{
|
}: WithLoading<{
|
||||||
name: string;
|
name: string;
|
||||||
@ -52,6 +66,7 @@ export const ItemDetails = ({
|
|||||||
poster: KyooImage | null;
|
poster: KyooImage | null;
|
||||||
genres: Genre[] | null;
|
genres: Genre[] | null;
|
||||||
overview: string | null;
|
overview: string | null;
|
||||||
|
playHref: string;
|
||||||
}>) => {
|
}>) => {
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
@ -96,10 +111,24 @@ export const ItemDetails = ({
|
|||||||
<SubP {...css({ pX: ts(1) })}>{overview}</SubP>
|
<SubP {...css({ pX: ts(1) })}>{overview}</SubP>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)}
|
)}
|
||||||
<View {...css({ bg: (theme) => theme.themeOverlay, flexDirection: "row" })}>
|
<View
|
||||||
{genres?.map((x) => (
|
{...css({
|
||||||
<Chip key={x} label={x} {...css({ mX: ts(.5) })} />
|
bg: (theme) => theme.themeOverlay,
|
||||||
))}
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
minHeight: px(50),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<View {...css({ flexDirection: "row" })}>
|
||||||
|
{genres?.slice(0, 2).map((x) => <Chip key={x} label={x} {...css({ mX: ts(0.5) })} />)}
|
||||||
|
</View>
|
||||||
|
<IconFab
|
||||||
|
icon={PlayArrow}
|
||||||
|
size={20}
|
||||||
|
as={Link}
|
||||||
|
href={playHref ?? "#"}
|
||||||
|
{...css({ fover: { self: { transform: "scale(1.2)" as any, mX: ts(0.5) } } })}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@ -133,6 +162,7 @@ export const Recommanded = () => {
|
|||||||
x.kind !== ItemKind.Collection && !x.isLoading ? getDisplayDate(x) : undefined
|
x.kind !== ItemKind.Collection && !x.isLoading ? getDisplayDate(x) : undefined
|
||||||
}
|
}
|
||||||
genres={"genres" in x ? x.genres : null}
|
genres={"genres" in x ? x.genres : null}
|
||||||
|
playHref={x.kind !== ItemKind.Collection && !x.isLoading ? x.playHref : undefined}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</InfiniteFetch>
|
</InfiniteFetch>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user