feat(search): live YouTube search UI
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.
This commit is contained in:
parent
9b1bdb6b42
commit
546be57963
16 changed files with 240 additions and 15 deletions
|
|
@ -19,6 +19,7 @@
|
|||
"smtp_password": { "label": "SMTP-Passwort", "hint": "App-Passwort. Verschlüsselt gespeichert; nur schreibbar — wird nie wieder angezeigt." },
|
||||
"quota_daily_budget": { "label": "Tägliches Kontingentbudget", "hint": "YouTube-Data-API-Einheiten pro Tag (kostenloses Limit 10.000). Standard 9000 lässt Puffer." },
|
||||
"backfill_quota_reserve": { "label": "Nachlade-Kontingentreserve", "hint": "Reservierte Einheiten, damit geplantes Nachladen interaktive Syncs / Anreicherung nie aushungert." },
|
||||
"search_daily_limit_per_user": { "label": "Live-Suche — Tageslimit pro Nutzer", "hint": "Maximale Live-YouTube-Suchen pro Nutzer und Tag. Jede Suche kostet 100 Einheiten, das gemeinsame Budget reicht also für insgesamt nur ~80-90/Tag. 0 = Live-Suche deaktiviert." },
|
||||
"backfill_recent_max_videos": { "label": "Aktuelles Nachladen — max. Videos", "hint": "Neueste Videos pro Kanal beim ersten Durchlauf." },
|
||||
"backfill_recent_max_days": { "label": "Aktuelles Nachladen — max. Alter (Tage)", "hint": "Wie weit der erste Durchlauf pro Kanal zurückreicht." },
|
||||
"shorts_probe_max_seconds": { "label": "Shorts-Prüfung — max. Dauer (s)", "hint": "Nur Videos bis zu dieser Länge werden als mögliche Shorts geprüft." },
|
||||
|
|
|
|||
|
|
@ -29,5 +29,17 @@
|
|||
"undo": "Rückgängig",
|
||||
"markedWatchedNamed": "Als angesehen markiert: „{{title}}”",
|
||||
"markedWatched": "Als angesehen markiert",
|
||||
"unwatch": "Nicht mehr als angesehen"
|
||||
"unwatch": "Nicht mehr als angesehen",
|
||||
"searchDiscovered": "Über Suche gefunden",
|
||||
"searchDiscoveredTip": "Auch Videos anzeigen, die nur über eine Live-YouTube-Suche in die Bibliothek kamen.",
|
||||
"yt": {
|
||||
"searchFor": "Auf YouTube suchen nach „{{query}}”",
|
||||
"resultsFor": "YouTube-Ergebnisse für „{{query}}”",
|
||||
"quotaNote": "Live-Ergebnisse — verbraucht gemeinsames API-Kontingent",
|
||||
"back": "Zurück zum Feed",
|
||||
"searching": "Suche auf YouTube…",
|
||||
"noResults": "Keine YouTube-Videos gefunden.",
|
||||
"error": "YouTube-Suche fehlgeschlagen.",
|
||||
"loadMore": "Mehr laden (verbraucht Kontingent)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"feed": "Feed",
|
||||
"searchPlaceholder": "Deine Abos durchsuchen…",
|
||||
"searchYoutube": "Auf YouTube suchen",
|
||||
"searchYoutubeTip": "Live auf YouTube nach diesem Begriff suchen (verbraucht gemeinsames API-Kontingent). Du kannst auch Enter drücken.",
|
||||
"channelManager": "Kanalverwaltung",
|
||||
"usageStats": "Nutzung & Statistik",
|
||||
"scheduler": "Planer",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"videos_backfill_full": "Vollständigen Verlauf laden",
|
||||
"videos_enrich": "Video-Anreicherung",
|
||||
"videos_lookup": "Video-Abfrage",
|
||||
"videos_search": "Live-Suche",
|
||||
"channels_discover": "Kanal-Entdeckung",
|
||||
"channels_subscribe": "Abonnieren",
|
||||
"channels_unsubscribe": "Abo beenden",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
"smtp_password": { "label": "SMTP password", "hint": "App password. Stored encrypted; write-only — it's never shown back." },
|
||||
"quota_daily_budget": { "label": "Daily quota budget", "hint": "Total YouTube Data API units to spend per day (free tier is 10,000). Default 9000 leaves headroom." },
|
||||
"backfill_quota_reserve": { "label": "Backfill quota reserve", "hint": "Units kept in reserve so scheduled backfill never starves interactive syncs / enrichment." },
|
||||
"search_daily_limit_per_user": { "label": "Live search — daily limit per user", "hint": "Max live YouTube searches per user per day. Each search costs 100 units, so the shared budget only affords ~80-90/day total. Set 0 to disable live search." },
|
||||
"backfill_recent_max_videos": { "label": "Recent backfill — max videos", "hint": "Newest videos fetched per channel on the first pass." },
|
||||
"backfill_recent_max_days": { "label": "Recent backfill — max age (days)", "hint": "How far back the first pass reaches per channel." },
|
||||
"shorts_probe_max_seconds": { "label": "Shorts probe — max duration (s)", "hint": "Only videos at or below this length are probed as possible Shorts." },
|
||||
|
|
|
|||
|
|
@ -29,5 +29,17 @@
|
|||
"undo": "Undo",
|
||||
"markedWatchedNamed": "Marked watched “{{title}}”",
|
||||
"markedWatched": "Marked watched",
|
||||
"unwatch": "Unwatch"
|
||||
"unwatch": "Unwatch",
|
||||
"searchDiscovered": "Search-discovered",
|
||||
"searchDiscoveredTip": "Also show videos that entered the library only through a live YouTube search.",
|
||||
"yt": {
|
||||
"searchFor": "Search YouTube for “{{query}}”",
|
||||
"resultsFor": "YouTube results for “{{query}}”",
|
||||
"quotaNote": "Live results — uses shared API quota",
|
||||
"back": "Back to feed",
|
||||
"searching": "Searching YouTube…",
|
||||
"noResults": "No YouTube videos found.",
|
||||
"error": "YouTube search failed.",
|
||||
"loadMore": "Load more (uses quota)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"feed": "Feed",
|
||||
"searchPlaceholder": "Search your subscriptions…",
|
||||
"searchYoutube": "Search YouTube",
|
||||
"searchYoutubeTip": "Search live on YouTube for this term (uses shared API quota). You can also press Enter.",
|
||||
"channelManager": "Channel manager",
|
||||
"usageStats": "Usage & stats",
|
||||
"scheduler": "Scheduler",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"videos_backfill_full": "Full-history backfill",
|
||||
"videos_enrich": "Video enrichment",
|
||||
"videos_lookup": "Video lookup",
|
||||
"videos_search": "Live search",
|
||||
"channels_discover": "Channel discovery",
|
||||
"channels_subscribe": "Subscribe",
|
||||
"channels_unsubscribe": "Unsubscribe",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
"smtp_password": { "label": "SMTP-jelszó", "hint": "Alkalmazásjelszó. Titkosítva tárolva; csak írható — soha nem jelenik meg újra." },
|
||||
"quota_daily_budget": { "label": "Napi kvótakeret", "hint": "Naponta elkölthető YouTube Data API-egységek (az ingyenes keret 10 000). Az alap 9000 tartalékot hagy." },
|
||||
"backfill_quota_reserve": { "label": "Letöltési kvótatartalék", "hint": "Tartalékban tartott egységek, hogy az ütemezett letöltés ne éheztesse ki az interaktív szinkront / gazdagítást." },
|
||||
"search_daily_limit_per_user": { "label": "Élő keresés — napi limit / felhasználó", "hint": "Maximális élő YouTube-keresés felhasználónként naponta. Egy keresés 100 egységbe kerül, így a közös büdzséből összesen csak ~80-90 fér bele naponta. 0 = élő keresés kikapcsolva." },
|
||||
"backfill_recent_max_videos": { "label": "Friss letöltés — max videó", "hint": "Csatornánként az első körben letöltött legújabb videók száma." },
|
||||
"backfill_recent_max_days": { "label": "Friss letöltés — max kor (nap)", "hint": "Az első kör csatornánként meddig nyúl vissza." },
|
||||
"shorts_probe_max_seconds": { "label": "Shorts-vizsgálat — max hossz (mp)", "hint": "Csak az ennél nem hosszabb videókat vizsgáljuk lehetséges Shortsként." },
|
||||
|
|
|
|||
|
|
@ -29,5 +29,17 @@
|
|||
"undo": "Visszavonás",
|
||||
"markedWatchedNamed": "Megnézettnek jelölve: „{{title}}”",
|
||||
"markedWatched": "Megnézettnek jelölve",
|
||||
"unwatch": "Megnézés visszavonása"
|
||||
"unwatch": "Megnézés visszavonása",
|
||||
"searchDiscovered": "Keresésből talált",
|
||||
"searchDiscoveredTip": "Mutasd azokat a videókat is, amelyek csak élő YouTube-keresésen át kerültek a könyvtárba.",
|
||||
"yt": {
|
||||
"searchFor": "Keresés a YouTube-on: „{{query}}”",
|
||||
"resultsFor": "YouTube találatok erre: „{{query}}”",
|
||||
"quotaNote": "Élő találatok — a közös API-kvótát fogyasztja",
|
||||
"back": "Vissza a hírfolyamhoz",
|
||||
"searching": "Keresés a YouTube-on…",
|
||||
"noResults": "Nincs YouTube-találat.",
|
||||
"error": "A YouTube-keresés nem sikerült.",
|
||||
"loadMore": "Továbbiak betöltése (kvótát fogyaszt)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"feed": "Hírfolyam",
|
||||
"searchPlaceholder": "Keresés a feliratkozásaid között…",
|
||||
"searchYoutube": "Keresés a YouTube-on",
|
||||
"searchYoutubeTip": "Élő keresés a YouTube-on erre a kifejezésre (a közös API-kvótát fogyasztja). Entert is nyomhatsz.",
|
||||
"channelManager": "Csatornakezelő",
|
||||
"usageStats": "Használat és statisztika",
|
||||
"scheduler": "Ütemező",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
"videos_backfill_full": "Teljes előzmény betöltése",
|
||||
"videos_enrich": "Videó-gazdagítás",
|
||||
"videos_lookup": "Videó-lekérdezés",
|
||||
"videos_search": "Élő keresés",
|
||||
"channels_discover": "Csatorna-felfedezés",
|
||||
"channels_subscribe": "Feliratkozás",
|
||||
"channels_unsubscribe": "Leiratkozás",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue