fix(ui): portal tooltips, opaque glass, settings rail+stable height, notif test, channel help

- Tooltip: render in a portal with fixed positioning + edge-flip so hints are never
  clipped by overflow/stacking ancestors (fixes mispositioned/hidden bubbles app-wide).
- Glass: raise opacity so overlay menus/panels stay readable over content.
- SettingsPanel: vertical tab rail (no wrapping/jumping), content grid-stacked so the
  panel sizes to the tallest tab (stable height) and floats to its content height.
- Notifications: the test toast is now a normal auto-dismissing toast (with countdown
  bar) that also plays the sound via a new force-sound flag.
- Channel manager: explain priority/tags/hide and what 'Sync subscriptions' does;
  add a 'Channel priority' feed sort so priority is actually meaningful.
This commit is contained in:
npeter83 2026-06-11 21:30:25 +02:00
parent 6486c3d1a9
commit 7a189fd163
7 changed files with 160 additions and 79 deletions

View file

@ -208,6 +208,8 @@ SORTS = {
"duration_asc": Video.duration_seconds.asc().nulls_last(),
"title": func.lower(Video.title).asc().nulls_last(),
"subscribers": Channel.subscriber_count.desc().nulls_last(),
# Your per-channel priority (set in the channel manager), newest first within a tier.
"priority": Subscription.priority.desc(),
}
@ -222,10 +224,15 @@ def get_feed(
db: Session = Depends(get_db),
) -> dict:
query, _status = _filtered_query(db, user, **params)
order = SORTS.get(sort)
if order is None and sort == "shuffle":
order = func.md5(func.concat(Video.id, str(seed)))
query = query.order_by(order if order is not None else SORTS["newest"])
if sort == "priority":
query = query.order_by(
Subscription.priority.desc(), Video.published_at.desc().nulls_last()
)
else:
order = SORTS.get(sort)
if order is None and sort == "shuffle":
order = func.md5(func.concat(Video.id, str(seed)))
query = query.order_by(order if order is not None else SORTS["newest"])
rows = db.execute(query.offset(offset).limit(limit + 1)).all()
has_more = len(rows) > limit