Commit graph

9 commits

Author SHA1 Message Date
npeter83
1d6d3d3063 feat(channels): status filter + header full-history link + stable priority
- header: per-user "N without full history" count (channels_deep_pending),
  clickable with a hint -> opens the channel manager filtered to those.
- channel manager: status filter chips (All / Needs full history / Fully synced
  / Hidden); the header link deep-links to "Needs full history".
- fix: priority up/down is now an optimistic in-place cache update (no refetch /
  re-sort), so the list no longer jumps to the top and loses your scroll position;
  the new order applies on the next page load.
2026-06-14 07:08:59 +02:00
npeter83
08776b17d0 fix(ui): robust avatars — no-referrer + graceful fallback
Channel/account avatars come from Google's image CDNs (yt3.ggpht.com,
lh3.googleusercontent.com). On a feed page dozens load at once; the CDN
rate-limits the referrer-bearing burst (429), so a random subset rendered the
browser's broken-image icon (the URLs themselves are valid — verified 200).

Add a shared <Avatar> that sets referrerPolicy="no-referrer" (which the CDNs
serve without throttling) and falls back to a neutral initial placeholder on
error instead of the broken-image icon. Use it for video-card, player, channel
manager, header and settings avatars.
2026-06-12 18:01:43 +02:00
npeter83
be3253415f fix(channels): reflect shared deep-queue state in the full-history chip
deep_requested is per-subscription, but deep backfill is channel-wide and shared:
once any subscriber requests full history, the whole back-catalog arrives for
everyone. The chip only looked at the current user's flag, so a second subscriber
saw a misleading 'get full history' on a channel already queued by someone else.
Add a channel-level deep_in_queue to /api/channels and show an informational
'full history queued' badge (vs the owner's cancelable button) in that case.
2026-06-12 02:29:10 +02:00
npeter83
f1009f06ed feat(channels): kick recent backfill immediately on 'full history' opt-in
When a user requests full history for a channel whose recent uploads aren't
fetched yet, run a one-channel recent backfill synchronously in the request so
the feed populates at once instead of waiting for the scheduler. Deep paging
still follows on the scheduler (recent-then-deep). The deep-toggle mutation now
also refreshes my-status and the feed.
2026-06-12 00:00:50 +02:00
npeter83
eb88d793f8 feat(m5b): optional YouTube write scope via incremental OAuth
Default login now requests read-only (youtube.readonly); write (unsubscribe,
later playlist export) is an explicit opt-in.

- auth.py: split READ_SCOPES / WRITE_SCOPES; new GET /auth/upgrade (incremental
  consent, prompt=consent); has_write_scope() helper
- /api/me exposes can_write
- youtube/client.py: delete_subscription (50 units, OAuth-only)
- DELETE /api/channels/{id}/subscription, gated on write scope (403 otherwise)
- UI: Settings - Account 'Playlist editing & YouTube export' enable button;
  per-channel 'Unsubscribe on YouTube' (with confirm) shown only when can_write

Browser-facing; develop/test locally until the public HTTPS login lands. Needs a
one-time Console step: add youtube.readonly to the OAuth consent screen scopes.
2026-06-11 23:27:11 +02:00
npeter83
5f60b3e9fe feat(m5d): demand-driven deep backfill + per-user ETA
Per-user opt-in to full-history (deep) backfill so a new user's unique
channels no longer trigger a big shared-quota burst.

- migration 0007: Subscription.deep_requested (default false); seed admins'
  existing subscriptions to preserve today's global-backfill behaviour
- run_deep_backfill is now demand-driven: only channels at least one user has
  requested are deep-backfilled; recent backfill stays unconditional (cheap)
- estimate_deep_backfill ETA helper (quota-bound) surfaced in /api/sync/my-status
- POST /api/sync/deep-all to opt all my channels in; PATCH channels accepts
  deep_requested
- UI: per-channel Full history toggle, Backfill everything action, deep
  progress + ETA in Channels header and Settings - Sync
2026-06-11 23:07:09 +02:00
npeter83
91fd008519 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.
2026-06-11 21:30:25 +02:00
npeter83
f8d2a11226 feat(ui): liquid-glass design system, settings polish, hints, notif fixes
- Add a theme-aware glass surface system (.glass/.glass-card + ambient backdrop,
  performance-mode opt-out) and apply it across panels, popovers, toasts, cards,
  sidebar widgets, channel rows, video cards and login.
- SettingsPanel: slide in/out animation, glass styling, wrapping pill tabs (no
  horizontal scrollbar) with a prominent active state.
- Notifications: auto-dismiss can be switched off (stays until closed); the test
  notification now also triggers the alert sound; resume a suspended AudioContext.
- Add an app-wide, toggleable hint/tooltip system (lib/hints + Tooltip) and wire
  hints across the settings and channel-manager surfaces; persisted per account.
2026-06-11 21:08:35 +02:00
npeter83
bf54b4b5a5 feat(m5a): channel manager, tabbed settings panel, per-user sync status
Backend: /api/channels (list + PATCH priority/hidden + attach/detach user tags),
user-tag CRUD on /api/tags, /api/sync/my-status (per-user channel sync counts).
Frontend: feed|channels page nav (URL-synced) from the account menu; a slide-in
tabbed Settings panel (Appearance, Notifications=6b sound+duration, Sync status +
actions + admin pause/resume, Account); a channel manager with priority, hide,
per-channel user tags, sync badges and 'view in feed'. Notifications now honor the
configurable sound + auto-dismiss settings.
2026-06-11 20:45:48 +02:00