feat: unhide action, date-range filter, more sort options

- Hidden view shows an Unhide action (eye icon) instead of Hide
- Upload-date filter: From/To date range (inclusive); feed shows only videos
  published in that window (backend published_after / published_before)
- New sort options: Name (A-Z) and Channel subscribers, alongside date/views/
  duration/shuffle
- Native controls follow the theme via color-scheme (dark date picker)
This commit is contained in:
npeter83 2026-06-11 04:00:17 +02:00
parent ecbecbb9f4
commit f73cbdb490
5 changed files with 79 additions and 6 deletions

View file

@ -1,4 +1,4 @@
from datetime import datetime, timezone
from datetime import date, datetime, timedelta, timezone
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import and_, false, func, or_, select
@ -50,6 +50,8 @@ def get_feed(
min_duration: int | None = None,
max_duration: int | None = None,
max_age_days: int | None = None,
published_after: date | None = None,
published_before: date | None = None,
show_normal: bool = True,
include_shorts: bool = False,
include_live: bool = False,
@ -119,6 +121,17 @@ def get_feed(
query = query.where(
Video.published_at >= datetime.fromtimestamp(cutoff, tz=timezone.utc)
)
if published_after is not None:
start = datetime.combine(
published_after, datetime.min.time(), tzinfo=timezone.utc
)
query = query.where(Video.published_at >= start)
if published_before is not None:
# Inclusive of the end day.
end = datetime.combine(
published_before, datetime.min.time(), tzinfo=timezone.utc
) + timedelta(days=1)
query = query.where(Video.published_at < end)
if q:
# Title (and channel name) only — searching descriptions produced noisy matches.
like = f"%{q}%"
@ -168,6 +181,8 @@ def get_feed(
"views": Video.view_count.desc().nulls_last(),
"duration_desc": Video.duration_seconds.desc().nulls_last(),
"duration_asc": Video.duration_seconds.asc().nulls_last(),
"title": func.lower(Video.title).asc().nulls_last(),
"subscribers": Channel.subscriber_count.desc().nulls_last(),
"shuffle": func.md5(func.concat(Video.id, str(seed))),
}
query = query.order_by(sorts.get(sort, sorts["newest"]))