mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-02-23 19:50:04 -05:00
Type error cleanups
This commit is contained in:
parent
e1d1eb3bef
commit
3bfadc673e
@ -1,7 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { View } from "react-native";
|
||||
import type { KImage, WatchStatusV } from "~/models";
|
||||
import type { KImage } from "~/models";
|
||||
import {
|
||||
Image,
|
||||
ImageBackground,
|
||||
@ -24,7 +24,6 @@ export const EntryBox = ({
|
||||
thumbnail,
|
||||
href,
|
||||
watchedPercent,
|
||||
watchedStatus,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
@ -35,8 +34,7 @@ export const EntryBox = ({
|
||||
description: string | null;
|
||||
href: string;
|
||||
thumbnail: KImage | null;
|
||||
watchedPercent: number | null;
|
||||
watchedStatus: WatchStatusV | null;
|
||||
watchedPercent: number;
|
||||
className?: string;
|
||||
}) => {
|
||||
const [moreOpened, setMoreOpened] = useState(false);
|
||||
@ -58,9 +56,7 @@ export const EntryBox = ({
|
||||
"ring-accent group-hover:ring-3 group-focus-visible:ring-3",
|
||||
)}
|
||||
>
|
||||
{(watchedPercent || watchedStatus === "completed") && (
|
||||
<ItemProgress watchPercent={watchedPercent ?? 100} />
|
||||
)}
|
||||
<ItemProgress watchPercent={watchedPercent} />
|
||||
<EntryContext
|
||||
slug={slug}
|
||||
serieSlug={serieSlug}
|
||||
|
||||
@ -18,8 +18,8 @@ export const itemMap = (
|
||||
item.kind !== "collection" ? (item.watchStatus?.status ?? null) : null,
|
||||
watchPercent:
|
||||
item.kind === "movie" ? (item.watchStatus?.percent ?? null) : null,
|
||||
unseenEpisodesCount: 0,
|
||||
// item.kind === "serie" ? (item.watchStatus?.unseenEpisodesCount ?? item.episodesCount!) : null,
|
||||
availableCount: item.kind === "serie" ? item.availableCount : null,
|
||||
seenCount: item.kind === "serie" ? item.watchStatus?.seenCount : null,
|
||||
});
|
||||
|
||||
export { ItemGrid, ItemList };
|
||||
|
||||
@ -16,6 +16,7 @@ import { ItemContext } from "./context-menus";
|
||||
import { ItemWatchStatus } from "./item-helpers";
|
||||
|
||||
export const ItemProgress = ({ watchPercent }: { watchPercent: number }) => {
|
||||
if (!watchPercent) return null;
|
||||
return (
|
||||
<>
|
||||
<View className="absolute bottom-0 h-1 w-full bg-slate-400" />
|
||||
@ -36,7 +37,8 @@ export const ItemGrid = ({
|
||||
poster,
|
||||
watchStatus,
|
||||
watchPercent,
|
||||
unseenEpisodesCount,
|
||||
availableCount,
|
||||
seenCount,
|
||||
horizontal = false,
|
||||
className,
|
||||
...props
|
||||
@ -49,8 +51,9 @@ export const ItemGrid = ({
|
||||
watchStatus: WatchStatusV | null;
|
||||
watchPercent: number | null;
|
||||
kind: "movie" | "serie" | "collection";
|
||||
unseenEpisodesCount: number | null;
|
||||
horizontal: boolean;
|
||||
availableCount?: number | null;
|
||||
seenCount?: number | null;
|
||||
horizontal?: boolean;
|
||||
className?: string;
|
||||
}) => {
|
||||
const [moreOpened, setMoreOpened] = useState(false);
|
||||
@ -77,7 +80,8 @@ export const ItemGrid = ({
|
||||
>
|
||||
<ItemWatchStatus
|
||||
watchStatus={watchStatus}
|
||||
unseenEpisodesCount={unseenEpisodesCount}
|
||||
availableCount={availableCount}
|
||||
seenCount={seenCount}
|
||||
/>
|
||||
{kind === "movie" && watchPercent && (
|
||||
<ItemProgress watchPercent={watchPercent} />
|
||||
|
||||
@ -1,51 +1,30 @@
|
||||
import Done from "@material-symbols/svg-400/rounded/check-fill.svg";
|
||||
import { View } from "react-native";
|
||||
import { max, rem, useYoshiki } from "yoshiki/native";
|
||||
import type { WatchStatusV } from "~/models";
|
||||
import { Icon, P, ts } from "~/primitives";
|
||||
import { Icon, P } from "~/primitives";
|
||||
|
||||
export const ItemWatchStatus = ({
|
||||
watchStatus,
|
||||
unseenEpisodesCount,
|
||||
availableCount,
|
||||
seenCount,
|
||||
...props
|
||||
}: {
|
||||
watchStatus?: WatchStatusV | null;
|
||||
unseenEpisodesCount?: number | null;
|
||||
availableCount?: number | null;
|
||||
seenCount?: number | null;
|
||||
}) => {
|
||||
const { css } = useYoshiki();
|
||||
|
||||
if (watchStatus !== "completed" && !unseenEpisodesCount) return null;
|
||||
if (watchStatus !== "completed" && !availableCount) return null;
|
||||
|
||||
return (
|
||||
<View
|
||||
{...css(
|
||||
{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 0,
|
||||
minWidth: max(rem(1), ts(3.5)),
|
||||
aspectRatio: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
m: ts(0.5),
|
||||
pX: ts(0.5),
|
||||
bg: (theme) => theme.darkOverlay,
|
||||
borderRadius: 999999,
|
||||
},
|
||||
props,
|
||||
)}
|
||||
className="absolute top-0 right-0 m-1 aspect-square min-w-8 items-center justify-center rounded-full bg-gray-800/70 p-1"
|
||||
{...props}
|
||||
>
|
||||
{watchStatus === "completed" ? (
|
||||
<Icon icon={Done} size={16} />
|
||||
<Icon icon={Done} />
|
||||
) : (
|
||||
<P
|
||||
{...css({
|
||||
marginVertical: 0,
|
||||
verticalAlign: "middle",
|
||||
textAlign: "center",
|
||||
})}
|
||||
>
|
||||
{unseenEpisodesCount}
|
||||
<P className="text-center">
|
||||
{seenCount ?? 0}/{availableCount}
|
||||
</P>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import { Platform, View } from "react-native";
|
||||
import { percent, px, rem, useYoshiki } from "yoshiki/native";
|
||||
import { View } from "react-native";
|
||||
import type { KImage, WatchStatusV } from "~/models";
|
||||
import {
|
||||
ContrastArea,
|
||||
GradientImageBackground,
|
||||
Heading,
|
||||
important,
|
||||
ImageBackground,
|
||||
Link,
|
||||
P,
|
||||
Poster,
|
||||
@ -15,6 +12,7 @@ import {
|
||||
ts,
|
||||
} from "~/primitives";
|
||||
import type { Layout } from "~/query";
|
||||
import { cn } from "~/utils";
|
||||
import { ItemContext } from "./context-menus";
|
||||
import { ItemWatchStatus } from "./item-helpers";
|
||||
|
||||
@ -27,7 +25,9 @@ export const ItemList = ({
|
||||
thumbnail,
|
||||
poster,
|
||||
watchStatus,
|
||||
unseenEpisodesCount,
|
||||
availableCount,
|
||||
seenCount,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
href: string;
|
||||
@ -38,159 +38,92 @@ export const ItemList = ({
|
||||
poster: KImage | null;
|
||||
thumbnail: KImage | null;
|
||||
watchStatus: WatchStatusV | null;
|
||||
unseenEpisodesCount: number | null;
|
||||
availableCount?: number | null;
|
||||
seenCount?: number | null;
|
||||
className?: string;
|
||||
}) => {
|
||||
const [moreOpened, setMoreOpened] = useState(false);
|
||||
|
||||
return (
|
||||
<ContrastArea>
|
||||
{({ css }) => (
|
||||
<Link
|
||||
href={moreOpened ? undefined : href}
|
||||
onLongPress={() => setMoreOpened(true)}
|
||||
{...css({
|
||||
child: {
|
||||
more: {
|
||||
opacity: 0,
|
||||
},
|
||||
},
|
||||
fover: {
|
||||
title: {
|
||||
textDecorationLine: "underline",
|
||||
},
|
||||
more: {
|
||||
opacity: 100,
|
||||
},
|
||||
},
|
||||
})}
|
||||
{...props}
|
||||
>
|
||||
<GradientImageBackground
|
||||
src={thumbnail}
|
||||
alt={name}
|
||||
quality="medium"
|
||||
layout={{ width: percent(100), height: ItemList.layout.size }}
|
||||
gradientStyle={{
|
||||
alignItems: "center",
|
||||
justifyContent: "space-evenly",
|
||||
flexDirection: "row",
|
||||
}}
|
||||
{...(css({
|
||||
borderRadius: px(10),
|
||||
overflow: "hidden",
|
||||
}) as any)}
|
||||
>
|
||||
<View
|
||||
{...css({
|
||||
width: { xs: "50%", lg: "30%" },
|
||||
})}
|
||||
>
|
||||
<View
|
||||
{...css({
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
})}
|
||||
>
|
||||
<Heading
|
||||
{...css([
|
||||
"title",
|
||||
{
|
||||
textAlign: "center",
|
||||
fontSize: rem(2),
|
||||
letterSpacing: rem(0.002),
|
||||
fontWeight: "900",
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
])}
|
||||
>
|
||||
{name}
|
||||
</Heading>
|
||||
{kind !== "collection" && (
|
||||
<ItemContext
|
||||
kind={kind}
|
||||
slug={slug}
|
||||
status={watchStatus}
|
||||
isOpen={moreOpened}
|
||||
setOpen={(v) => setMoreOpened(v)}
|
||||
{...css([
|
||||
{
|
||||
// I dont know why marginLeft gets overwritten by the margin: px(2) so we important
|
||||
marginLeft: important(ts(2)),
|
||||
bg: (theme) => theme.darkOverlay,
|
||||
},
|
||||
"more",
|
||||
Platform.OS === "web" &&
|
||||
moreOpened && { opacity: important(100) },
|
||||
])}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
{subtitle && (
|
||||
<P
|
||||
{...css({
|
||||
textAlign: "center",
|
||||
marginRight: ts(4),
|
||||
})}
|
||||
>
|
||||
{subtitle}
|
||||
</P>
|
||||
)}
|
||||
</View>
|
||||
<PosterBackground
|
||||
src={poster}
|
||||
alt=""
|
||||
quality="low"
|
||||
layout={{ height: percent(80) }}
|
||||
>
|
||||
<ItemWatchStatus
|
||||
watchStatus={watchStatus}
|
||||
unseenEpisodesCount={unseenEpisodesCount}
|
||||
/>
|
||||
</PosterBackground>
|
||||
</GradientImageBackground>
|
||||
</Link>
|
||||
<Link
|
||||
href={moreOpened ? undefined : href}
|
||||
onLongPress={() => setMoreOpened(true)}
|
||||
className={cn(
|
||||
"group h-80 w-full outline-0 ring-accent focus-within:ring-3 hover:ring-3",
|
||||
className,
|
||||
)}
|
||||
</ContrastArea>
|
||||
{...props}
|
||||
>
|
||||
<ImageBackground
|
||||
src={thumbnail}
|
||||
quality="medium"
|
||||
className="h-full w-full flex-row items-center justify-evenly overflow-hidden rounded"
|
||||
>
|
||||
<View className="absolute inset-0 bg-linear-to-b from-transparent to-slate-950/70" />
|
||||
<View className="w-1/2 lg:w-1/3">
|
||||
<View className="flex-row justify-center">
|
||||
<Heading
|
||||
className={cn(
|
||||
"text-center text-3xl uppercase",
|
||||
"group-focus-within:underline group-hover:underline",
|
||||
)}
|
||||
>
|
||||
{name}
|
||||
</Heading>
|
||||
{kind !== "collection" && (
|
||||
<ItemContext
|
||||
kind={kind}
|
||||
slug={slug}
|
||||
status={watchStatus}
|
||||
isOpen={moreOpened}
|
||||
setOpen={(v) => setMoreOpened(v)}
|
||||
className={cn(
|
||||
"ml-4",
|
||||
"bg-gray-800/70 hover:bg-gray-800 focus-visible:bg-gray-800",
|
||||
"native:hidden opacity-0 focus-visible:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100",
|
||||
moreOpened && "opacity-100",
|
||||
)}
|
||||
iconClassName="fill-slate-200 dark:fill-slate-200"
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
{subtitle && <P className="mr-8 text-center">{subtitle}</P>}
|
||||
</View>
|
||||
<PosterBackground
|
||||
src={poster}
|
||||
alt=""
|
||||
quality="low"
|
||||
className="h-4/5 ring-accent group-focus-within:ring-4 group-hover:ring-4"
|
||||
>
|
||||
<ItemWatchStatus
|
||||
watchStatus={watchStatus}
|
||||
availableCount={availableCount}
|
||||
seenCount={seenCount}
|
||||
/>
|
||||
</PosterBackground>
|
||||
</ImageBackground>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
ItemList.Loader = (props: object) => {
|
||||
const { css } = useYoshiki();
|
||||
|
||||
return (
|
||||
<View
|
||||
{...css(
|
||||
{
|
||||
alignItems: "center",
|
||||
justifyContent: "space-evenly",
|
||||
flexDirection: "row",
|
||||
height: ItemList.layout.size,
|
||||
borderRadius: px(10),
|
||||
overflow: "hidden",
|
||||
bg: (theme) => theme.dark.background,
|
||||
marginX: ItemList.layout.gap,
|
||||
},
|
||||
props,
|
||||
)}
|
||||
className="h-80 w-full flex-row items-center justify-evenly overflow-hidden rounded bg-slate-800"
|
||||
{...props}
|
||||
>
|
||||
<View
|
||||
{...css({
|
||||
width: { xs: "50%", lg: "30%" },
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
})}
|
||||
>
|
||||
<Skeleton {...css({ height: rem(2), alignSelf: "center" })} />
|
||||
<Skeleton {...css({ width: rem(5), alignSelf: "center" })} />
|
||||
<View className="w-1/2 justify-center lg:w-1/3">
|
||||
<Skeleton className="h-8" />
|
||||
<Skeleton className="w-2/5" />
|
||||
</View>
|
||||
<Poster.Loader layout={{ height: percent(80) }} />
|
||||
<Poster.Loader className="h-4/5" />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
ItemList.layout = {
|
||||
numColumns: 1,
|
||||
size: 300,
|
||||
size: 320,
|
||||
layout: "vertical",
|
||||
gap: ts(2),
|
||||
} satisfies Layout;
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import AccountCircle from "@material-symbols/svg-400/rounded/account_circle-fill.svg";
|
||||
import type { ComponentType } from "react";
|
||||
import { Image, View, type ViewProps, type ViewStyle } from "react-native";
|
||||
import { cn } from "~/utils";
|
||||
import { Skeleton } from "./skeleton";
|
||||
import { P } from "./text";
|
||||
import { Icon } from "./icons";
|
||||
|
||||
const stringToColor = (string: string) => {
|
||||
let hash = 0;
|
||||
@ -51,12 +53,20 @@ export const Avatar = <AsProps = ViewProps>({
|
||||
{placeholder[0]}
|
||||
</P>
|
||||
)}
|
||||
<Image
|
||||
resizeMode="cover"
|
||||
source={{ uri: src }}
|
||||
alt={alt}
|
||||
className="absolute inset-0"
|
||||
/>
|
||||
{src && (
|
||||
<Image
|
||||
resizeMode="cover"
|
||||
source={{ uri: src }}
|
||||
alt={alt}
|
||||
className="absolute inset-0"
|
||||
/>
|
||||
)}
|
||||
{!src && !placeholder && (
|
||||
<Icon
|
||||
icon={AccountCircle}
|
||||
className="fill-slate-200 dark:fill-slate-200"
|
||||
/>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ export const Button = <AsProps = PressableProps>({
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
"flex-row items-center justify-center overflow-hidden",
|
||||
"rounded-4xl border-3 border-accent p-1",
|
||||
"rounded-4xl border-3 border-accent p-1 outline-0",
|
||||
disabled && "border-slate-600",
|
||||
"group focus-within:bg-accent hover:bg-accent",
|
||||
className,
|
||||
|
||||
@ -124,8 +124,8 @@ export const IconFab = <AsProps = PressableProps>({
|
||||
<Icon
|
||||
icon={icon}
|
||||
className={cn(
|
||||
"fill-slate-300",
|
||||
(hover || focus) && "fill-slate-200",
|
||||
"fill-slate-300 dark:fill-slate-300",
|
||||
(hover || focus) && "fill-slate-200 dark:fill-slate-200",
|
||||
iconClassName,
|
||||
)}
|
||||
/>
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { ImageBackground as EImageBackground } from "expo-image";
|
||||
import { LinearGradient, type LinearGradientProps } from "expo-linear-gradient";
|
||||
import type { ComponentProps, ReactNode } from "react";
|
||||
import type { ImageStyle } from "react-native";
|
||||
import { Platform } from "react-native";
|
||||
import { withUniwind } from "uniwind";
|
||||
import { useYoshiki } from "yoshiki/native";
|
||||
import type { KImage } from "~/models";
|
||||
import { useToken } from "~/providers/account-context";
|
||||
import { cn } from "~/utils";
|
||||
@ -65,40 +63,3 @@ export const PosterBackground = ({
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const GradientImageBackground = ({
|
||||
gradient,
|
||||
gradientStyle,
|
||||
children,
|
||||
...props
|
||||
}: ComponentProps<typeof ImageBackground> & {
|
||||
gradient?: Partial<LinearGradientProps>;
|
||||
gradientStyle?: Parameters<ReturnType<typeof useYoshiki>["css"]>[0];
|
||||
}) => {
|
||||
const { css, theme } = useYoshiki();
|
||||
|
||||
return (
|
||||
<ImageBackground {...props}>
|
||||
<LinearGradient
|
||||
start={{ x: 0, y: 0.25 }}
|
||||
end={{ x: 0, y: 1 }}
|
||||
colors={["transparent", theme.darkOverlay]}
|
||||
{...css(
|
||||
[
|
||||
{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
},
|
||||
gradientStyle,
|
||||
],
|
||||
typeof gradient === "object" ? gradient : undefined,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</LinearGradient>
|
||||
</ImageBackground>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import ExpandMore from "@material-symbols/svg-400/rounded/keyboard_arrow_down-fill.svg";
|
||||
import { Button } from "./button";
|
||||
import { Icon } from "./icons";
|
||||
import { Menu } from "./menu";
|
||||
|
||||
export const Select = <Value extends string>({
|
||||
@ -16,11 +15,7 @@ export const Select = <Value extends string>({
|
||||
getLabel: (key: Value) => string;
|
||||
}) => {
|
||||
return (
|
||||
<Menu
|
||||
Trigger={Button}
|
||||
text={getLabel(value)}
|
||||
icon={<Icon icon={ExpandMore} />}
|
||||
>
|
||||
<Menu Trigger={Button} text={getLabel(value)} icon={ExpandMore}>
|
||||
{values.map((x) => (
|
||||
<Menu.Item
|
||||
key={x}
|
||||
|
||||
@ -7,13 +7,6 @@ import { Stack } from "expo-router";
|
||||
import { Fragment } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { View } from "react-native";
|
||||
import {
|
||||
percent,
|
||||
rem,
|
||||
type Stylable,
|
||||
type Theme,
|
||||
useYoshiki,
|
||||
} from "yoshiki/native";
|
||||
import { WatchListInfo } from "~/components/items/watchlist-info";
|
||||
import { Rating } from "~/components/rating";
|
||||
import {
|
||||
@ -44,7 +37,6 @@ import {
|
||||
Poster,
|
||||
Skeleton,
|
||||
tooltip,
|
||||
ts,
|
||||
UL,
|
||||
} from "~/primitives";
|
||||
import { useAccount } from "~/providers/account-context";
|
||||
@ -82,7 +74,6 @@ const ButtonList = ({
|
||||
icon={PlayArrow}
|
||||
as={Link}
|
||||
href={playHref}
|
||||
iconClassName="dark:fill-slate-200"
|
||||
{...tooltip(t("show.play"))}
|
||||
/>
|
||||
)}
|
||||
@ -273,7 +264,7 @@ const Description = ({
|
||||
genres: Genre[];
|
||||
studios: Studio[];
|
||||
externalIds: Metadata;
|
||||
} & Stylable) => {
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
|
||||
@ -7,11 +7,11 @@ import { min, percent, px, rem, vh } from "yoshiki/native";
|
||||
import { type KImage, Show } from "~/models";
|
||||
import {
|
||||
ContrastArea,
|
||||
GradientImageBackground,
|
||||
H1,
|
||||
H2,
|
||||
IconButton,
|
||||
IconFab,
|
||||
ImageBackground,
|
||||
Link,
|
||||
P,
|
||||
Skeleton,
|
||||
@ -19,6 +19,7 @@ import {
|
||||
ts,
|
||||
} from "~/primitives";
|
||||
import type { QueryIdentifier } from "~/query";
|
||||
import { cn } from "~/utils";
|
||||
|
||||
export const Header = ({
|
||||
name,
|
||||
@ -27,6 +28,7 @@ export const Header = ({
|
||||
tagline,
|
||||
link,
|
||||
infoLink,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
name: string;
|
||||
@ -35,86 +37,55 @@ export const Header = ({
|
||||
tagline: string | null;
|
||||
link: string | null;
|
||||
infoLink: string;
|
||||
className?: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ContrastArea mode="dark">
|
||||
{({ css }) => (
|
||||
<GradientImageBackground
|
||||
src={thumbnail}
|
||||
alt=""
|
||||
quality="high"
|
||||
layout={{
|
||||
width: percent(100),
|
||||
height: {
|
||||
xs: vh(40),
|
||||
sm: min(vh(60), px(750)),
|
||||
md: min(vh(60), px(680)),
|
||||
lg: vh(65),
|
||||
},
|
||||
}}
|
||||
{...(css(
|
||||
{
|
||||
minHeight: {
|
||||
xs: px(350),
|
||||
sm: px(300),
|
||||
md: px(400),
|
||||
lg: px(600),
|
||||
},
|
||||
},
|
||||
props,
|
||||
) as any)}
|
||||
>
|
||||
<View
|
||||
{...css({
|
||||
width: { md: percent(70) },
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
margin: ts(2),
|
||||
})}
|
||||
>
|
||||
<H1
|
||||
numberOfLines={4}
|
||||
{...css({ fontSize: { xs: rem(2), sm: rem(3) } })}
|
||||
>
|
||||
{name}
|
||||
</H1>
|
||||
<View {...css({ flexDirection: "row", alignItems: "center" })}>
|
||||
{link !== null && (
|
||||
<IconFab
|
||||
icon={PlayArrow}
|
||||
aria-label={t("show.play")}
|
||||
as={Link}
|
||||
href={link ?? "#"}
|
||||
{...tooltip(t("show.play"))}
|
||||
{...css({ marginRight: ts(1) })}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
icon={Info}
|
||||
as={Link}
|
||||
aria-label={t("home.info")}
|
||||
href={infoLink ?? "#"}
|
||||
{...tooltip(t("home.info"))}
|
||||
{...css({ marginRight: ts(2) })}
|
||||
/>
|
||||
{tagline && (
|
||||
<H2 {...css({ display: { xs: "none", sm: "flex" } })}>
|
||||
{tagline}
|
||||
</H2>
|
||||
)}
|
||||
</View>
|
||||
<P
|
||||
numberOfLines={4}
|
||||
{...css({ display: { xs: "none", md: "flex" } })}
|
||||
>
|
||||
{description}
|
||||
</P>
|
||||
</View>
|
||||
</GradientImageBackground>
|
||||
<ImageBackground
|
||||
src={thumbnail}
|
||||
alt=""
|
||||
quality="high"
|
||||
className={cn(
|
||||
"h-[40vh] w-full sm:h-[60vh] sm:min-h-[750px] md:min-h-[680px] lg:h-[65vh]",
|
||||
className,
|
||||
)}
|
||||
</ContrastArea>
|
||||
{...props}
|
||||
>
|
||||
<View className="absolute inset-0 bg-linear-to-b from-transparent to-slate-950/70" />
|
||||
<View className="absolute bottom-0 m-4 md:w-3/5">
|
||||
<H1 numberOfLines={4} className="text-3xl text-slate-200 sm:text-5xl">
|
||||
{name}
|
||||
</H1>
|
||||
<View className="my-2 flex-row items-center">
|
||||
{link !== null && (
|
||||
<IconFab
|
||||
icon={PlayArrow}
|
||||
aria-label={t("show.play")}
|
||||
as={Link}
|
||||
href={link}
|
||||
className="mr-2"
|
||||
{...tooltip(t("show.play"))}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
icon={Info}
|
||||
as={Link}
|
||||
aria-label={t("home.info")}
|
||||
href={infoLink}
|
||||
className="mr-2"
|
||||
iconClassName="fill-slate-400"
|
||||
{...tooltip(t("home.info"))}
|
||||
/>
|
||||
{tagline && (
|
||||
<H2 className="text-slate-200 max-sm:hidden">{tagline}</H2>
|
||||
)}
|
||||
</View>
|
||||
<P numberOfLines={4} className="text-slate-400 max-sm:hidden">
|
||||
{description}
|
||||
</P>
|
||||
</View>
|
||||
</ImageBackground>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -35,7 +35,8 @@ export const ItemDetails = ({
|
||||
href,
|
||||
playHref,
|
||||
watchStatus,
|
||||
unseenEpisodesCount,
|
||||
availableCount,
|
||||
seenCount,
|
||||
...props
|
||||
}: {
|
||||
slug: string;
|
||||
@ -49,7 +50,8 @@ export const ItemDetails = ({
|
||||
href: string;
|
||||
playHref: string | null;
|
||||
watchStatus: WatchStatusV | null;
|
||||
unseenEpisodesCount: number | null;
|
||||
availableCount?: number | null;
|
||||
seenCount?: number | null;
|
||||
}) => {
|
||||
const [moreOpened, setMoreOpened] = useState(false);
|
||||
const { css } = useYoshiki("recommended-card");
|
||||
@ -120,7 +122,8 @@ export const ItemDetails = ({
|
||||
</View>
|
||||
<ItemWatchStatus
|
||||
watchStatus={watchStatus}
|
||||
unseenEpisodesCount={unseenEpisodesCount}
|
||||
availableCount={availableCount}
|
||||
seenCount={seenCount}
|
||||
/>
|
||||
</PosterBackground>
|
||||
<View
|
||||
|
||||
@ -57,7 +57,7 @@ export const WatchlistList = () => {
|
||||
description={entry.name}
|
||||
thumbnail={entry.thumbnail ?? item.thumbnail}
|
||||
href={entry.href ?? "#"}
|
||||
watchedPercent={entry.watchStatus?.percent || null}
|
||||
watchedPercent={entry.progress.percent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -237,7 +237,6 @@ const ChangePopup = ({
|
||||
</View>
|
||||
<Input
|
||||
autoComplete={autoComplete}
|
||||
variant="big"
|
||||
value={value}
|
||||
onChangeText={(v) => setValue(v)}
|
||||
/>
|
||||
@ -299,7 +298,6 @@ const ChangePasswordPopup = ({
|
||||
{hasPassword && (
|
||||
<PasswordInput
|
||||
autoComplete="current-password"
|
||||
variant="big"
|
||||
value={oldValue}
|
||||
onChangeText={(v) => setOldValue(v)}
|
||||
placeholder={t("settings.account.password.oldPassword")}
|
||||
@ -307,7 +305,6 @@ const ChangePasswordPopup = ({
|
||||
)}
|
||||
<PasswordInput
|
||||
autoComplete="new-password"
|
||||
variant="big"
|
||||
value={newValue}
|
||||
onChangeText={(v) => setNewValue(v)}
|
||||
placeholder={t("settings.account.password.newPassword")}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user