Frontend for the channel-explore feature:
- ChannelPage: banner/avatar/stats header, Subscribe/unsubscribe, an "exploring" badge
while browsing an un-subscribed channel, Videos/About tabs. Reuses Feed scoped to the
channel (scope=all + source=all so the per-user ephemeral videos show). Auto-ingests
recent uploads on first visit (background, with a loading note) + "Load more from
YouTube" to page deeper; skipped for demo / already-subscribed channels.
- App: openChannel/closeChannel as a Back-aware sub-view (history.state._chan, mirrors the
YT-search _yt pattern); ChannelPage takes over the content column, nav rail stays.
- ChannelLink/cards/player: the channel name now opens our channel page (onChannelFilter →
onOpenChannel); the in-card "only this channel" filter button is dropped (the page
subsumes it). PlayerModal channel-name wiring follows in the next commit.
- api: channelDetail + exploreChannel; ChannelDetail/ExploreResult types.
- i18n EN/HU/DE: channel namespace, explore_cleanup scheduler labels, explore config group,
channels_explore quota label.
The search response now reports its source; in scrape mode (zero quota) the
results banner and Load-more button drop the 'uses quota' wording. Adds the
search_source toggle's labels/hints and updates the per-user-limit hint to note
the cost only applies to the api source. EN/HU/DE.
Surface live YouTube search in the existing feed, triggered explicitly so the
expensive API call is never per-keystroke.
- Header: the search box still filters the local catalog as you type; Enter or a
YouTube button escalates the term to a live search (hidden for the demo account).
- Feed: a dedicated infinite query renders results in the same VirtualFeed cards +
in-app player, under a banner with a back button and a quota note. No auto-paginate
(each page spends 100 units) — an explicit 'Load more (uses quota)' button instead;
quota/limit errors (incl. 429) shown inline. The empty local feed offers a
'Search YouTube for <q>' CTA.
- Library: a 'Search-discovered' toggle reveals search-ingested videos (hidden by
default); sent as exclude_search_discovered.
- Admin: search_daily_limit_per_user config field; new videos_search quota label.
- All new strings translated in HU/EN/DE.
New youtube_api_proxy setting (env fallback + admin Config UI, env YOUTUBE_API_PROXY):
when set, the YouTubeClient routes all its httpx traffic through that HTTP(S) proxy.
Lets a dynamic-IP host send API calls through a fixed-IP host (e.g. the server over
private tunnel) so an IP-restricted API key keeps working. Empty = direct.
- Build the Google OAuth client lazily from sysconfig (DB override, env fallback) and re-register
when the credentials change, so the install wizard / admin can set them without a restart.
- New 'google' config group (google_client_id/secret, encrypted) on the Configuration page; the
token-refresh reads the creds the same way.
- Public GET /auth/config exposes google_enabled; the login page hides 'Continue with Google'
when Google OAuth isn't configured (email+password still works).
New admin-only Users page (sidebar): Users & roles (list + promote/demote with
confirm; self/demo/last-admin guarded server-side), plus the Access requests
(Invite whitelist) and Demo whitelist+reset migrated out of Settings → Account
(same data/tables — UI relocated only). Settings → Account now holds personal
content only. ConfigPanel learns a boolean field type (toggle) for the new
allow_registration setting. api methods, new 'users' page/route/nav/header, and
EN/HU/DE strings (new users namespace + access group).
Register youtube_api_key in the sysconfig registry as a secret and resolve it from
the DB-override-or-env layer in YouTubeClient (self.db is in scope). Adds a YouTube
API group to the Configuration page (EN/HU/DE).
Google OAuth client id/secret stay env-only for now: the authlib client is
registered at module load (auth.py), and the token-refresh reads them too, so a
runtime DB override needs a lazy/re-registerable OAuth client — that belongs to the
install-wizard epic (first-boot OAuth config without restart). Admin-role-via-UI
moves to the auth-overhaul epic (user management lives there).
Add the four new groups to the page's group order and EN/HU/DE labels + field
hints for the 8 newly DB-overridable settings. The page is registry-driven, so
this is purely presentational (group order + i18n).
Per-field Save buttons were an unconventional, endpoint-driven choice. Replace
them with a single drafted Save/Discard bar (consistent with the Settings page):
edits are buffered and applied together on Save (each via the existing per-key
PATCH/DELETE), Discard reverts. Reset-to-default is a per-field affordance applied
on Save too — clearing a non-secret falls back to default; a secret (which can't
be cleared by emptying) gets a toggle that resets it on save. Backend unchanged.
New admin-only Configuration page that renders the system_config registry grouped
(Email/SMTP first), with per-field save/reset, write-only encrypted secret fields
(disabled with a hint when TOKEN_ENCRYPTION_KEY is unset), and a Send-test-email
button. New 'config' page + sidebar nav item + header title; api methods and
EN/HU/DE strings.