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:
@@ -158,6 +158,19 @@ def blocked_ids(db: Session, user: User) -> set[str]:
|
||||
)
|
||||
|
||||
|
||||
def followed_among(db: Session, user: User, channel_ids: set[str]) -> set[str]:
|
||||
"""Which of these channels the user subscribes to."""
|
||||
if not channel_ids:
|
||||
return set()
|
||||
return set(
|
||||
db.scalars(
|
||||
select(Subscription.channel_id).where(
|
||||
owned_by(Subscription.user_id, user), Subscription.channel_id.in_(channel_ids)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def blocked_channels(db: Session, user: User, lang: str) -> list[Channel]:
|
||||
return list(
|
||||
db.execute(
|
||||
|
||||
@@ -284,8 +284,11 @@ def related_videos(
|
||||
# (a cursor) is the same list.
|
||||
if cursor is None:
|
||||
quota.log_action(user.id, quota.QuotaAction.VIDEOS_RELATED)
|
||||
rows = reader_queries.feed_rows_by_ids(db, user, collected)
|
||||
# A related list mixes channels the user follows with ones they never met: each row says which.
|
||||
followed = queries.followed_among(db, user, {r["channel_id"] for r in rows})
|
||||
return {
|
||||
"items": reader_queries.feed_rows_by_ids(db, user, collected),
|
||||
"items": [{**r, "followed": r["channel_id"] in followed} for r in rows],
|
||||
"next_cursor": next_cursor,
|
||||
"has_more": bool(next_cursor),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user