mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-04-04 00:01:54 -04:00
Properly use nextup in the home
This commit is contained in:
parent
637505dde9
commit
cef7a64017
@ -135,7 +135,7 @@ const newsSort: Sort = {
|
||||
],
|
||||
};
|
||||
|
||||
const entryRelations = {
|
||||
export const entryRelations = {
|
||||
translations: () => {
|
||||
const { pk, language, ...trans } = getColumns(entryTranslations);
|
||||
return db
|
||||
|
||||
@ -6,6 +6,7 @@ import { entries } from "~/db/schema";
|
||||
import { watchlist } from "~/db/schema/watchlist";
|
||||
import { getColumns } from "~/db/utils";
|
||||
import { Entry } from "~/models/entry";
|
||||
import { Show } from "~/models/show";
|
||||
import {
|
||||
AcceptLanguage,
|
||||
createPage,
|
||||
@ -21,6 +22,7 @@ import { desc } from "~/models/utils/descriptions";
|
||||
import {
|
||||
entryFilters,
|
||||
entryProgressQ,
|
||||
entryRelations,
|
||||
entryVideosQ,
|
||||
getEntryTransQ,
|
||||
mapProgress,
|
||||
@ -71,7 +73,7 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
jwt: { sub, settings },
|
||||
}) => {
|
||||
const langs = processLanguages(languages);
|
||||
const transQ = getEntryTransQ(langs);
|
||||
@ -102,6 +104,11 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
||||
seasonNumber: sql<number>`${seasonNumber}`,
|
||||
episodeNumber: sql<number>`${episodeNumber}`,
|
||||
name: sql<string>`${transQ.name}`,
|
||||
|
||||
show: sql`${entryRelations.show({
|
||||
languages: langs,
|
||||
preferOriginal: settings.preferOriginal,
|
||||
})}`,
|
||||
})
|
||||
.from(entries)
|
||||
.innerJoin(watchlist, eq(watchlist.nextEntry, entries.pk))
|
||||
@ -134,7 +141,7 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
||||
"accept-language": AcceptLanguage({ autoFallback: true }),
|
||||
}),
|
||||
response: {
|
||||
200: Page(Entry),
|
||||
200: Page(t.Intersect([Entry, t.Object({ show: Show })])),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@ -8,9 +8,9 @@ import { HeaderBackground, useScrollNavbar } from "../navbar";
|
||||
import { GenreGrid } from "./genre";
|
||||
import { Header } from "./header";
|
||||
import { NewsList } from "./news";
|
||||
import { NextupList } from "./nextup";
|
||||
import { Recommended } from "./recommended";
|
||||
import { VerticalRecommended } from "./vertical";
|
||||
import { WatchlistList } from "./watchlist";
|
||||
|
||||
export const HomePage = () => {
|
||||
const genres = shuffle(Object.values(Genre.enum));
|
||||
@ -50,7 +50,7 @@ export const HomePage = () => {
|
||||
)}
|
||||
Loader={Header.Loader}
|
||||
/>
|
||||
<WatchlistList />
|
||||
<NextupList />
|
||||
<NewsList />
|
||||
{genres
|
||||
.filter((_, i) => i < 2)
|
||||
@ -64,10 +64,11 @@ export const HomePage = () => {
|
||||
<GenreGrid key={x} genre={x} />
|
||||
))}
|
||||
<VerticalRecommended />
|
||||
{/*
|
||||
TODO: Lazy load those items
|
||||
{randomItems.filter((_, i) => i >= 6).map((x) => <GenreGrid key={x} genre={x} />)}
|
||||
*/}
|
||||
{genres
|
||||
.filter((_, i) => i >= 6)
|
||||
.map((x) => (
|
||||
<GenreGrid key={x} genre={x} />
|
||||
))}
|
||||
</Animated.ScrollView>
|
||||
</>
|
||||
);
|
||||
@ -75,7 +76,7 @@ export const HomePage = () => {
|
||||
|
||||
HomePage.queries = (randomItems: Genre[]) => [
|
||||
Header.query(),
|
||||
WatchlistList.query(),
|
||||
NextupList.query(),
|
||||
NewsList.query(),
|
||||
...randomItems.filter((_, i) => i < 6).map((x) => GenreGrid.query(x)),
|
||||
Recommended.query(),
|
||||
|
||||
@ -15,20 +15,18 @@ export const NewsList = () => {
|
||||
query={NewsList.query()}
|
||||
layout={{ ...EntryBox.layout, layout: "horizontal" }}
|
||||
Empty={<EmptyView message={t("home.none")} />}
|
||||
Render={({ item }) => {
|
||||
return (
|
||||
<EntryBox
|
||||
kind={item.kind}
|
||||
slug={item.slug}
|
||||
serieSlug={item.show!.slug}
|
||||
name={`${item.show!.name} ${entryDisplayNumber(item)}`}
|
||||
description={item.name}
|
||||
thumbnail={item.thumbnail}
|
||||
href={item.href ?? "#"}
|
||||
watchedPercent={item.progress.percent}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
Render={({ item }) => (
|
||||
<EntryBox
|
||||
kind={item.kind}
|
||||
slug={item.slug}
|
||||
serieSlug={item.show!.slug}
|
||||
name={`${item.show!.name} ${entryDisplayNumber(item)}`}
|
||||
description={item.name}
|
||||
thumbnail={item.thumbnail ?? item.show!.thumbnail}
|
||||
href={item.href ?? "#"}
|
||||
watchedPercent={item.progress.percent}
|
||||
/>
|
||||
)}
|
||||
Loader={EntryBox.Loader}
|
||||
/>
|
||||
</>
|
||||
|
||||
66
front/src/ui/home/nextup.tsx
Normal file
66
front/src/ui/home/nextup.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { View } from "react-native";
|
||||
import { EntryBox, entryDisplayNumber } from "~/components/entries";
|
||||
import { ItemGrid } from "~/components/items";
|
||||
import { Entry } from "~/models";
|
||||
import { Button, Link, P } from "~/primitives";
|
||||
import { useAccount } from "~/providers/account-context";
|
||||
import { InfiniteFetch, type QueryIdentifier } from "~/query";
|
||||
import { EmptyView } from "~/ui/empty-view";
|
||||
import { Header } from "./genre";
|
||||
|
||||
export const NextupList = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
|
||||
if (!account) {
|
||||
return (
|
||||
<>
|
||||
<Header title={t("home.watchlist")} />
|
||||
<View className="items-center justify-center">
|
||||
<P>{t("home.watchlistLogin")}</P>
|
||||
<Button
|
||||
as={Link}
|
||||
href={"/login"}
|
||||
text={t("login.login")}
|
||||
className="m-4 min-w-md"
|
||||
/>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header title={t("home.watchlist")} />
|
||||
<InfiniteFetch
|
||||
query={NextupList.query()}
|
||||
layout={{ ...ItemGrid.layout, layout: "horizontal" }}
|
||||
Empty={<EmptyView message={t("home.none")} />}
|
||||
Render={({ item }) => (
|
||||
<EntryBox
|
||||
kind={item.kind}
|
||||
slug={item.slug}
|
||||
serieSlug={item.show!.slug}
|
||||
name={`${item.show!.name} ${entryDisplayNumber(item)}`}
|
||||
description={item.name}
|
||||
thumbnail={item.thumbnail ?? item.show!.thumbnail}
|
||||
href={item.href ?? "#"}
|
||||
watchedPercent={item.progress.percent}
|
||||
/>
|
||||
)}
|
||||
Loader={EntryBox.Loader}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
NextupList.query = (): QueryIdentifier<Entry> => ({
|
||||
parser: Entry,
|
||||
infinite: true,
|
||||
path: ["api", "profiles", "me", "nextup"],
|
||||
params: {
|
||||
limit: 10,
|
||||
with: ["nextEntry"],
|
||||
},
|
||||
});
|
||||
@ -1,80 +0,0 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { View } from "react-native";
|
||||
import { EntryBox, entryDisplayNumber } from "~/components/entries";
|
||||
import { ItemGrid, itemMap } from "~/components/items";
|
||||
import { Show } from "~/models";
|
||||
import { Button, Link, P } from "~/primitives";
|
||||
import { useAccount } from "~/providers/account-context";
|
||||
import { InfiniteFetch, type QueryIdentifier } from "~/query";
|
||||
import { EmptyView } from "~/ui/empty-view";
|
||||
import { Header } from "./genre";
|
||||
|
||||
export const WatchlistList = () => {
|
||||
const { t } = useTranslation();
|
||||
const account = useAccount();
|
||||
|
||||
if (!account) {
|
||||
return (
|
||||
<>
|
||||
<Header title={t("home.watchlist")} />
|
||||
<View className="items-center justify-center">
|
||||
<P>{t("home.watchlistLogin")}</P>
|
||||
<Button
|
||||
as={Link}
|
||||
href={"/login"}
|
||||
text={t("login.login")}
|
||||
className="m-4 min-w-md"
|
||||
/>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header title={t("home.watchlist")} />
|
||||
<InfiniteFetch
|
||||
query={WatchlistList.query()}
|
||||
layout={{ ...ItemGrid.layout, layout: "horizontal" }}
|
||||
getItemType={(x, i) =>
|
||||
(x?.kind === "serie" && x.nextEntry) || (!x && i % 2)
|
||||
? "episode"
|
||||
: "item"
|
||||
}
|
||||
getItemSizeMult={(_, __, kind) => (kind === "episode" ? 2 : 1)}
|
||||
Empty={<EmptyView message={t("home.none")} />}
|
||||
Render={({ item }) => {
|
||||
const entry = item.kind === "serie" ? item.nextEntry : null;
|
||||
if (entry) {
|
||||
return (
|
||||
<EntryBox
|
||||
kind={entry.kind}
|
||||
slug={entry.slug}
|
||||
serieSlug={item.slug}
|
||||
name={`${item.name} ${entryDisplayNumber(entry)}`}
|
||||
description={entry.name}
|
||||
thumbnail={entry.thumbnail ?? item.thumbnail}
|
||||
href={entry.href ?? "#"}
|
||||
watchedPercent={entry.progress.percent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <ItemGrid {...itemMap(item)} horizontal />;
|
||||
}}
|
||||
Loader={({ index }) =>
|
||||
index % 2 ? <EntryBox.Loader /> : <ItemGrid.Loader horizontal />
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
WatchlistList.query = (): QueryIdentifier<Show> => ({
|
||||
parser: Show,
|
||||
infinite: true,
|
||||
path: ["api", "profiles", "me", "watchlist"],
|
||||
params: {
|
||||
limit: 10,
|
||||
with: ["nextEntry"],
|
||||
},
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user