feat(player): a video's related videos, on demand beside it
The player shows what YouTube lists beside the video, without what the user has watched or hidden. Wide, a Related tab beside the description; stacked, a button beside the info opens them in a drawer. A row plays in the same player (Back returns) and the list stays the opened video's. A switch picks on-topic or Hungarian-trending lists, kept on the account. Each related row says whether the user follows its channel; the row is the video card's narrow form with its whole menu. VideoMenu moves to features/video, where the player can reach it.
This commit is contained in:
@@ -35,6 +35,21 @@ export function isResettable(v: Pick<Video, "status" | "position_seconds">): boo
|
||||
return v.status !== "new" || v.position_seconds > 0;
|
||||
}
|
||||
|
||||
/** A video's related videos, in the locale YouTube fills the list in: on the video's topic, or with
|
||||
* what trends in Hungary (the server's `RELATED_REGIONS`). */
|
||||
export type RelatedRegion = "topical" | "hu";
|
||||
|
||||
/** A row of a related list: a feed row that also says whether the user follows its channel. */
|
||||
export interface RelatedVideo extends Video {
|
||||
followed: boolean;
|
||||
}
|
||||
|
||||
export interface RelatedResponse {
|
||||
items: RelatedVideo[];
|
||||
has_more: boolean;
|
||||
next_cursor: string | null;
|
||||
}
|
||||
|
||||
export interface VideoDetail {
|
||||
id: string;
|
||||
description: string | null;
|
||||
@@ -235,6 +250,21 @@ export const feedApi = {
|
||||
if (limit) p.set("limit", String(limit));
|
||||
return req(`/api/search/youtube?${p.toString()}`, {}, { quiet: true });
|
||||
},
|
||||
// The videos YouTube shows beside this one, without what the user has watched or hidden. `quiet`
|
||||
// for the same reason as the search: the list renders its refusal (the day's cap, YouTube) inline.
|
||||
related: (
|
||||
videoId: string,
|
||||
region: RelatedRegion,
|
||||
cursor: string | null,
|
||||
): Promise<RelatedResponse> => {
|
||||
const p = new URLSearchParams({ region });
|
||||
if (cursor) p.set("cursor", cursor);
|
||||
return req(
|
||||
`/api/search/related/${encodeURIComponent(videoId)}?${p.toString()}`,
|
||||
{},
|
||||
{ quiet: true },
|
||||
);
|
||||
},
|
||||
// Discard a set of live-search results "as if never added" (drops your search-finds + deletes
|
||||
// the now-orphaned, un-kept videos). Returns how many videos were removed.
|
||||
clearSearch: (videoIds: string[]): Promise<{ removed: number }> =>
|
||||
|
||||
Reference in New Issue
Block a user