mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-04-06 17:21:58 -04:00
Handle watchstatus of entries without history entry
This commit is contained in:
parent
d3a929855a
commit
f126a0592e
3
api/drizzle/0030_external_hist.sql
Normal file
3
api/drizzle/0030_external_hist.sql
Normal file
@ -0,0 +1,3 @@
|
||||
ALTER TABLE "kyoo"."history" ADD COLUMN "external" boolean;--> statement-breakpoint
|
||||
UPDATE "kyoo"."history" SET "external" = false;--> statement-breakpoint
|
||||
ALTER TABLE "kyoo"."history" ALTER COLUMN "external" SET NOT NULL;--> statement-breakpoint
|
||||
2016
api/drizzle/meta/0030_snapshot.json
Normal file
2016
api/drizzle/meta/0030_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -211,6 +211,13 @@
|
||||
"when": 1774623568394,
|
||||
"tag": "0029_next_refresh",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"version": "7",
|
||||
"when": 1774974162419,
|
||||
"tag": "0030_external_hist",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ export const entryProgressQ = db
|
||||
entryPk: history.entryPk,
|
||||
playedDate: history.playedDate,
|
||||
videoId: videos.id,
|
||||
external: history.external,
|
||||
})
|
||||
.from(history)
|
||||
.leftJoin(videos, eq(history.videoPk, videos.pk))
|
||||
|
||||
@ -76,7 +76,7 @@ async function updateHistory(
|
||||
.select({ videoId: videos.id })
|
||||
.from(history)
|
||||
.for("update", { of: sql`history` as any })
|
||||
.leftJoin(videos, eq(videos.pk, history.videoPk))
|
||||
.innerJoin(videos, eq(videos.pk, history.videoPk))
|
||||
.where(
|
||||
and(
|
||||
eq(history.profilePk, userPk),
|
||||
@ -86,12 +86,16 @@ async function updateHistory(
|
||||
).map((x) => x.videoId);
|
||||
|
||||
const toUpdate = traverse(
|
||||
progress.filter((x) => existing.includes(x.videoId)),
|
||||
progress.filter((x) => x.videoId && existing.includes(x.videoId)),
|
||||
);
|
||||
const newEntries = traverse(
|
||||
progress
|
||||
.filter((x) => !existing.includes(x.videoId))
|
||||
.map((x) => ({ ...x, entryUseid: isUuid(x.entry) })),
|
||||
.filter((x) => !x.videoId || !existing.includes(x.videoId))
|
||||
.map((x) => ({
|
||||
...x,
|
||||
external: x.external ?? false,
|
||||
entryUseid: isUuid(x.entry),
|
||||
})),
|
||||
);
|
||||
|
||||
const updated =
|
||||
@ -140,6 +144,7 @@ async function updateHistory(
|
||||
playedDate: coalesce(sql`hist.played_date`, sql`now()`).as(
|
||||
"playedDate",
|
||||
),
|
||||
external: sql`hist.external`.as("external"),
|
||||
})
|
||||
.from(sql`unnest(
|
||||
${sqlarr(newEntries.entry)}::text[],
|
||||
@ -147,8 +152,9 @@ async function updateHistory(
|
||||
${sqlarr(newEntries.videoId)}::uuid[],
|
||||
${sqlarr(newEntries.time)}::integer[],
|
||||
${sqlarr(newEntries.percent)}::integer[],
|
||||
${sqlarr(newEntries.playedDate)}::timestamptz[]
|
||||
) as hist(entry, entry_use_id, video_id, ts, percent, played_date)`)
|
||||
${sqlarr(newEntries.playedDate)}::timestamptz[],
|
||||
${sqlarr(newEntries.external)}::boolean[]
|
||||
) as hist(entry, entry_use_id, video_id, ts, percent, played_date, external)`)
|
||||
.innerJoin(
|
||||
entries,
|
||||
sql`
|
||||
@ -244,7 +250,7 @@ async function updateWatchlist(
|
||||
seenCount: sql`
|
||||
case
|
||||
when ${entries.kind} = 'movie' then hist.percent
|
||||
when hist.percent >= 95 then 1
|
||||
when hist.percent >= 95 then 100
|
||||
else 0
|
||||
end
|
||||
`.as("seen_count"),
|
||||
@ -315,6 +321,7 @@ const historyProgressQ: typeof entryProgressQ = db
|
||||
entryPk: history.entryPk,
|
||||
playedDate: history.playedDate,
|
||||
videoId: videos.id,
|
||||
external: history.external,
|
||||
})
|
||||
.from(history)
|
||||
.leftJoin(videos, eq(history.videoPk, videos.pk))
|
||||
@ -360,6 +367,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(entryProgressQ.playedDate),
|
||||
eq(entryProgressQ.external, false),
|
||||
ne(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
@ -406,6 +414,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
sort,
|
||||
filter: and(
|
||||
isNotNull(entryProgressQ.playedDate),
|
||||
eq(entryProgressQ.external, false),
|
||||
ne(entries.kind, "extra"),
|
||||
filter,
|
||||
),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { check, index, integer, timestamp } from "drizzle-orm/pg-core";
|
||||
import { boolean, check, index, integer, timestamp } from "drizzle-orm/pg-core";
|
||||
import { entries } from "./entries";
|
||||
import { profiles } from "./profiles";
|
||||
import { schema } from "./utils";
|
||||
@ -23,6 +23,8 @@ export const history = schema.table(
|
||||
playedDate: timestamp({ withTimezone: true, precision: 3 })
|
||||
.notNull()
|
||||
.defaultNow(),
|
||||
// true if the user only marked the entry has seen and has not seen it on kyoo
|
||||
external: boolean().notNull(),
|
||||
},
|
||||
(t) => [
|
||||
index("history_play_date").on(t.playedDate.desc()),
|
||||
|
||||
@ -33,6 +33,18 @@ export const SeedHistory = t.Intersect([
|
||||
entry: t.String({
|
||||
description: "Id or slug of the entry/movie you watched",
|
||||
}),
|
||||
external: t.Optional(
|
||||
t.Boolean({
|
||||
description: comment`
|
||||
Set this to true if the user marked the entry as watched
|
||||
without actually watching it on kyoo.
|
||||
|
||||
If true, it will not add it to the history but still mark it as
|
||||
seen.
|
||||
`,
|
||||
default: false,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
]);
|
||||
export type SeedHistory = typeof SeedHistory.static;
|
||||
|
||||
@ -29,8 +29,25 @@ export const EntryContext = ({
|
||||
} & Partial<ComponentProps<typeof Menu>> &
|
||||
Partial<ComponentProps<typeof IconButton>>) => {
|
||||
// const downloader = useDownloader();
|
||||
const account = useAccount();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const markAsSeenMutation = useMutation({
|
||||
method: "POST",
|
||||
path: ["api", "profiles", "me", "history"],
|
||||
body: [
|
||||
{
|
||||
percent: 100,
|
||||
entry: slug,
|
||||
videoId: null,
|
||||
time: 0,
|
||||
playedDate: null,
|
||||
external: true,
|
||||
},
|
||||
],
|
||||
invalidate: null,
|
||||
});
|
||||
|
||||
return (
|
||||
<Menu
|
||||
Trigger={IconButton}
|
||||
@ -39,6 +56,13 @@ export const EntryContext = ({
|
||||
{...tooltip(t("misc.more"))}
|
||||
{...(props as any)}
|
||||
>
|
||||
{account && (
|
||||
<Menu.Item
|
||||
label={t("show.watchlistMark.completed")}
|
||||
icon={watchListIcon("completed")}
|
||||
onSelect={() => markAsSeenMutation.mutate()}
|
||||
/>
|
||||
)}
|
||||
{serieSlug && (
|
||||
<Menu.Item
|
||||
label={t("home.episodeMore.goToShow")}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user