New ytsage/utils/ytsage_library_manager.py: sagetube_library.db
(separate from the upstream download-history DB) with WAL from day one,
holding subscriptions, cached feed_items, watch_history with resume
positions, and the persisted play_queue. Watch history and queue tables
are wired up by the next commit.
FeedPage:
- Local mode: FeedRefreshWorker refreshes each subscribed channel
sequentially (feed.per_channel_items, default 15) and the grid fills
incrementally per channel; results are cached so the feed is
populated instantly on startup.
- Account mode: fetches youtube.com/feed/subscriptions with the user's
browser cookies - the real logged-in feed; the option is enabled only
while cookies are active and errors surface as a status banner.
- Sidebar lists subscriptions (double-click opens the channel in
Browse; context menu unsubscribes). Browse's Subscribe button now
toggles subscription state through the Feed page.
Verified live: subscribe -> refresh -> 15 videos cached in SQLite and
rendered as cards.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The single-page downloader layout becomes the Downloads tab of a
SmoothTabWidget with Watch / Search / Feed / Browse / Downloads pages.
The init_ui edit is deliberately small (the old central widget is now
self.download_page); all new behavior lives in new modules:
- ytsage_gui_router.py: AppRouter signal hub (playVideo, queueVideo,
downloadVideo, openChannel, openPlaylist). A card's Download button
deep-links into the Downloads tab with the URL prefilled and analysis
started automatically.
- ytsage_gui_cards.py: VideoCard (thumbnail with disk cache under
APP_THUMBNAILS_DIR, title/channel/duration, Play/Queue/Download
actions, double-click to play) and VideoCardGrid (responsive grid,
Load more pagination).
- ytsage_gui_watch.py: WatchPage hosting the mpv PlayerPanel and a
drag-reorderable play queue with auto-advance on end of file.
- ytsage_gui_search.py: SearchPage running YtdlpClient.search off the
GUI thread with Load more pagination.
- Browse and Feed pages are placeholders, implemented next.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>