feat(anime): queue episodes to play next across anime

- Episode rows gain Play/Queue actions (and matching context-menu items); queued rows show their place in line, with a queue count and Clear queue in the episode header
- Queue lives in the main process (`anime-browser-queue.ts`) so it survives the browser window closing and advances on mpv's end-file even when nobody is watching; streams resolve at play time so a signed URL cannot expire while queued
- Holds mpv's keep-open off while the queue waits and restores it once empty; queueing with nothing playing just plays immediately
- Adds anime-browser-queue and episode-queue unit tests, IPC channels/contracts, and doc updates
This commit is contained in:
2026-08-15 21:44:51 -07:00
parent 51fc9034f7
commit 3ca7dcd664
19 changed files with 838 additions and 7 deletions
@@ -11,7 +11,11 @@ import type { SubtitleCacheIo } from '../../anime-bridge/subtitle-cache';
import type { BundleBinaries } from '../../anime-bridge/sidecar-bundle';
import { startSidecar } from '../../anime-bridge/sidecar-process';
import { startStreamStripProxy } from '../../anime-bridge/stream-strip-proxy';
import type { AnimeBrowserBridgeState, AnimeBrowserSearchUpdate } from '../../types/anime-browser';
import type {
AnimeBrowserBridgeState,
AnimeBrowserQueueState,
AnimeBrowserSearchUpdate,
} from '../../types/anime-browser';
import type { InstallProgress } from './anime-bridge-installer';
export interface AnimeBrowserRuntimeDeps {
@@ -53,6 +57,8 @@ export interface AnimeBrowserRuntimeDeps {
/** Overrides the filesystem/network the subtitle cache uses. Tests only. */
subtitleCacheIo?: SubtitleCacheIo;
onBridgeState: (state: AnimeBrowserBridgeState) => void;
/** Pushes the play queue to the browser window, advances included. */
onQueueState?: (state: AnimeBrowserQueueState) => void;
/** Streams per-source progress while a search invoke is pending. */
onSearchUpdate?: (update: AnimeBrowserSearchUpdate) => void;
preferredQuality?: () => string | undefined;