Per-video state flags + smart folders + comments capture (Tartube parity 1.3/1.4)
Three Tartube-parity items shipped together since they touch the same
schema and rendering paths.
Per-video state flags
- New `video_flags` SQLite table with `bookmark`/`favourite`/`waiting`/
`archive` columns (one row per video that has at least one flag set).
- `Database::set_video_flag` validates the flag name against an
allow-list before interpolating into the SQL — column names can't be
parameterised in SQLite, but the allow-list keeps it injection-free.
- `Database::get_video_flags` bulk-loads into a new
`VideoFlagsBundle { bookmark, favourite, waiting, archive: HashSet<String> }`
so subsequent reads are O(1) in-memory hits.
- `WebState.flags` (Mutex<VideoFlagsBundle>) + `App.flags`
(VideoFlagsBundle, GUI is single-threaded) populated at startup.
- `POST /api/videos/:id/flags/:flag` toggles a flag; the in-memory
bundle is mirrored immediately so the next /api/library reflects the
change without a rescan. Library ETag is bumped.
- `VideoInfo` JSON gains `bookmark` / `favourite` / `waiting` /
`archive` boolean fields.
- `archive` is wired through everywhere but no UI gate yet — it's
reserved for the future auto-delete feature.
Smart folders
- Both UIs gain "★ Favourites", "🔖 Bookmarks", "⏳ Waiting" sidebar
entries between Continue Watching and Channels. Each is hidden when
its set is empty, so a fresh install isn't polluted with zero-count
rows.
- Desktop: new `SidebarView::Favourites / Bookmarks / Waiting`
variants. `compute_cards` filters the library by the matching
`self.flags.<set>` HashSet and returns the resulting cards using the
same rendering path as the other views.
- Web: `showFavourites/Bookmarks/Waiting` flags + smart-folder branch
in `currentVideos()`. Refactored the view-mode selectors through a
new `resetViewSelectors()` helper so adding three more booleans
didn't quadruple every `setX` function.
Per-card flag toggles
- Web: each video card grows three new action buttons (☆/★ favourite,
🔖 bookmark, ⏳ waiting) next to the existing watched toggle.
Optimistic UI — flip in-memory immediately, undo on server error.
- Desktop: same three buttons next to Watched in the card row, deferred
through a `toggle_flag_card: Option<&'static str>` to keep the
borrow checker happy. New `App::toggle_video_flag` helper persists
the flip to SQLite and invalidates the card cache.
Comments capture
- `DownloadOptions` gains `fetch_comments: bool`. When set, the
downloader emits `--write-comments` so yt-dlp embeds the full
comment tree into info.json.
- New `GET /api/comments/:id` reads the array out of info.json and
returns a slimmed-down version (id, author, text, likes, parent,
time) — strips the multi-MB extras yt-dlp can otherwise inline.
- Web player modal grows a 💬 button that opens a separate modal
with a threaded viewer: replies indented by parent id, "N comments"
header, helpful message when nothing's captured pointing at the
channel-options toggle.
- Channel-options dialog in both UIs gains a "Fetch comments"
checkbox + hint about the slowdown.
Tartube spec checklist
- Three more boxes ticked: per-video state flags, smart folders,
comments capture. Score now: 5 ahead, 5 behind, 1 tied + matching
on 4 parity items. (Half done.)
55 unit tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9335e0faa8
commit
8281246420
6 changed files with 437 additions and 15 deletions
|
|
@ -580,13 +580,22 @@ the following are all true.
|
|||
Editor surfaces in both UIs.*
|
||||
- [ ] **Folder hierarchy** with N-level nesting, drag-to-reparent, and
|
||||
per-folder default options.
|
||||
- [ ] **Smart folders** for Bookmarks / Favourites / Waiting / New /
|
||||
Live / Missing, on top of our existing Recent + Continue
|
||||
Watching.
|
||||
- [ ] **Per-video state flags** persisted (extending the SQLite
|
||||
schema): `bookmark`, `favourite`, `archive`, `waiting`,
|
||||
`block`, plus a `missing` derived flag from the maintenance
|
||||
scan.
|
||||
- [x] **Smart folders** for Bookmarks / Favourites / Waiting on top of
|
||||
Recent + Continue Watching. *v1 shipped 2026-05-25: each smart
|
||||
folder appears in the sidebar only when at least one video carries
|
||||
the matching flag, so a fresh install isn't polluted with empty
|
||||
rows. Driven by the in-memory flag bundle so no SQL per render.*
|
||||
- [x] **Per-video state flags** persisted in a new `video_flags`
|
||||
SQLite table with columns `bookmark`, `favourite`, `waiting`,
|
||||
`archive`. Loaded as four `HashSet<String>` at startup, mutated
|
||||
via `POST /api/videos/:id/flags/:flag` (web) or the per-card
|
||||
action buttons (desktop). `archive` is wired through but UI is
|
||||
deferred until we actually have auto-deletion to gate.
|
||||
- [x] **Comments capture** via the new `fetch_comments` field in
|
||||
DownloadOptions. Adds `--write-comments` to the yt-dlp command
|
||||
when set. New `GET /api/comments/:id` reads the comments array
|
||||
out of info.json and the web player modal's 💬 button renders a
|
||||
threaded viewer.
|
||||
- [ ] **Profiles** — saved named groups of channels with a "Download
|
||||
this profile" action.
|
||||
- [ ] **Tidy + Refresh** unified into a single bidirectional sync
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue