feat: add saved-video collections and category views

This commit is contained in:
2026-10-11 20:47:24 +02:00
parent 6eed1cdd9e
commit b65834e9d4
6 changed files with 680 additions and 138 deletions
+18 -2
View File
@@ -74,6 +74,9 @@ These are the default bindings. Overrides in `[keys]` replace an action's bindin
| `W` | Browse watch later for the current category, or the combined collection elsewhere |
| `f` | In watch later, cycle All → Unwatched → Watched |
| `D` | In watch later, confirm removal of all videos matching the current list/filter |
| `v` | Save the selected video to saved videos (also works in previews) |
| `V` | Browse saved videos for the current category, or the combined collection elsewhere |
| `x` | Remove only the selected saved video (also works in previews) |
| Tab / Shift-Tab | Switch between visible views |
| `r` | Reload configuration and refresh the current view |
| `?` | Open / close the scrollable keybinding reference |
@@ -162,7 +165,7 @@ Category entries accept `@handles`, HTTPS YouTube channel URLs, or canonical `UC
Video tables color channel names **cyan** when the creator belongs to at least one category. Untagged registrations keep the default text color; selected rows retain their black-on-cyan highlight. Membership is matched by channel ID or handle, not the displayed name, and updates after saving tags or reloading config.
- **Search** and **Feed** are permanent tabs. Feed combines all `[channels]` registrations, including untagged channels, plus channels entered directly in categories, without duplicates.
- Browsing an unpinned category, channel, or watch-later list uses one shared temporary tab; choosing another replaces it. Pinned categories keep their own tabs, marked with a dimmed `p`.
- Browsing an unpinned category, channel, watch-later list, or saved-video list uses one shared temporary tab; choosing another replaces it. Pinned categories keep their own tabs, marked with a dimmed `p`.
- Removing a channel from a category does **not** unsubscribe it from Feed. To unsubscribe, remove its `[channels]` mappings and category references, then press `r`.
- Temporary tabs do not survive restarting; saved categories and pins do. Hidden views retain loaded rows, selection, and pagination during the session.
@@ -174,7 +177,7 @@ Watch later is **one collection**, deduplicated by YouTube video ID. Category li
Browse a category with `c`, then use `W` for its watch-later list. From Search, Feed, or a channel view, `W` opens the combined collection. Watch-later views use saved title, creator, and publication metadata without fetching video lists, so they also work offline. Their filters are independent and retained during the session; each pane's border title shows the active All, Unwatched, or Watched filter.
Saved video titles are **magenta** in all video tables; categorized channel names remain cyan. A `✓` marks watched videos, including outside watch-later views. The selected row retains its usual highlight.
Watch-later-only titles are **magenta** in all video tables; categorized channel names remain cyan. A `✓` marks watched videos, including outside watch-later views. The selected row retains its usual highlight.
### Watched status
@@ -189,6 +192,7 @@ Terebi reports acknowledged playback positions. A video becomes watched when an
Files are siblings of `config.toml`:
- `watch-later.toml`: versioned saved-video metadata.
- `saved-videos.toml`: independent versioned saved-video metadata.
- `watch-state.toml`: versioned global watched video IDs.
- `playback-sessions/`: private per-launch progress streams and their expected video identities.
@@ -196,6 +200,18 @@ State writes are atomic and owner-only. Invalid state files or detected external
Progress sessions survive Tubular exit so later player reports can be recovered on the next launch. They are retained because the GUI may still be writing; up to 4,096 sessions are monitored. If that limit is reached, close the corresponding players, remove their inactive session directories, and restart Tubular. Never remove an active player's reporting directory.
## Saved videos
Saved videos is a separate collection from watch later, deduplicated by YouTube video ID. It uses the same offline title, creator, and publication metadata and follows **current channel category memberships**, not categories stored on individual videos.
Browse a category with `c`, then use `V` for its saved-video list. From Search, Feed, or a channel view, `V` opens the combined collection. Switching between a category's saved videos and watch later with `V` / `W` retains that category. Both lists share the existing temporary-tab and back/forward history behavior.
`x` removes **only the selected video** from saved videos, whether in a list or a preview. Removing it never changes watch-later membership or global watched status. There is no watched filter or bulk removal for saved videos.
Saved titles are **green**, taking precedence over watch-later magenta when a video belongs to both collections. Removing it from saved videos restores magenta if it remains in watch later. Channel styling, selected-row highlighting, and watched markers are unchanged.
The collection is persisted independently in `saved-videos.toml` beside `config.toml`, using the same atomic, owner-only writes and validation as watch later. Saving repeatedly does not add duplicates. Configure the actions with `video.saved.save`, `view.saved.browse`, and `video.saved.remove`; the live hints and `?` reference reflect overrides.
## Configurable keybindings
Print a complete default configuration, including every action and its default bindings: