Implement channel and playlist browsing

BrowsePage accepts pasted or routed channel/playlist URLs:
- Channels get Videos / Shorts / Live sub-tabs mapped to the channel's
  /videos, /shorts and /streams listings, lazily fetched 24 at a time
  with -I range pagination; channel title and id resolve from a cheap
  -I 1:1 metadata fetch. Subscribe emits subscribeRequested for the
  Feed page to wire up.
- Playlists get a single grid with Play all (bulk-enqueues into the
  Watch queue) and a Download button that deep-links the playlist into
  the Downloads tab.

Workers are parented to their pages and fetch errors surface as status
text instead of crashing (verified against a channel with no videos
tab). fetch_flat_info gains an items="1:1" limiter so metadata probes
no longer enumerate whole channels.

Verified live: kurzgesagt channel (24 cards, title+id resolved) and a
17-video playlist with Play-all queueing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jaroslav Beneš
2026-07-25 01:53:44 +02:00
parent 16be4b4afa
commit 8e935c6116
4 changed files with 270 additions and 14 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ class SearchPage(QWidget):
self.status_label.setText(_("search.searching"))
self.search_btn.setEnabled(False)
query, offset = self._query, self._offset
self._worker = YtdlpWorker(lambda c: c.search(query, n=PAGE_SIZE, offset=offset))
self._worker = YtdlpWorker(lambda c: c.search(query, n=PAGE_SIZE, offset=offset), parent=self)
self._worker.result.connect(lambda entries: self._on_results(entries, append))
self._worker.error.connect(self._on_error)
self._worker.finished.connect(self._on_finished)