Commit Graph
25 Commits
Author SHA1 Message Date
sudacode 89479f7045 feat(anime): set default source from Extensions tab
- Add default controls for installed sources and All sources
- Expose source metadata for extension rows
2026-09-02 23:50:11 -07:00
sudacode 18beac13f4 feat(anime): add version-aware extension updates
- Compare installed APK version codes before offering updates
- Add update status labels and an Update all action
2026-09-02 19:10:03 -07:00
sudacode 2bcb6c7e98 feat(anime): support shared bridge installs and updates
- Prefer configured or package-managed bridge bundles before downloading
- Select compatible upstream releases and offer managed-bundle updates
- Document bridge configuration and package dependencies
2026-09-01 23:14:16 -07:00
sudacode 1d1575f414 fix(anime): preserve HLS playlist rewriting and fetch timeouts
- Force identity encoding for upstream playlist responses
- Keep inactivity timeouts active while streaming response bodies
2026-08-16 14:20:08 -07:00
sudacode f6993ae507 fix(anime): harden stream proxy and session lifecycle
- Reject non-origin-form proxy targets
- Release stale anime browser sessions when senders move
2026-08-16 01:46:16 -07:00
sudacode 4300517da7 fix(anime): harden browser playback and modal lifecycle
- Abort upstream fetches when clients disconnect
- Validate embedded modal readiness before opening
- Centralize browser IPC and window lifecycle
2026-08-16 01:21:07 -07:00
sudacode 877f350353 fix(anime): keep browser state in sync and alias HLS segments
- Toggle the player Anime Browser without losing its state
- Share active playback state and support rotating fake segment extensions
2026-08-15 23:35:37 -07:00
sudacode cc43d3007a fix(anime): alias disguised HLS segments for ffmpeg
- Expose local `.ts` aliases for `.image` MPEG-TS segments
- Cover proxy rewriting and upstream alias removal with tests
2026-08-15 21:44:51 -07:00
sudacode 333ee5eea4 fix(anime): clean up discarded queued subtitles in background
- Let queued episode discard return before subtitle preparation finishes
- Remove the redundant queued subtitle loading command
2026-08-15 21:44:51 -07:00
sudacode 935e4c145f feat(anime): append queued episodes to mpv playlist
- Resolve queued streams immediately and cache subtitles in the background
- Attach prepared tracks as mpv advances through the playlist
2026-08-15 21:44:51 -07:00
sudacode 51fc9034f7 fix(subsync): decode file:// tracks mpv reports for dropped subtitles
- Sync a subtitle dropped onto mpv without hitting "Protocol file: not supported"; decode file:// external-filename/path back to a real path for target, reference, and video
- Stream strip proxy: destroy the connection instead of retrying/502 once a response is handed off, and cap buffered playlist bodies
- Bridge installer: cap downloaded bundle size to guard against a lying/missing content-length
- Anime browser playback: bump generation on dispose so a stale in-flight playEpisode cleans up its own subtitle cache
- Fix a flaky sidecar-process test by binding to an OS-assigned port instead of pre-allocating one
2026-08-15 21:44:51 -07:00
sudacode 8aff2ae505 fix(anime): guard playback races and harden install/extract tests
- Tag subtitle cache writes with a generation counter so overlapping playEpisode calls can't clobber the shared cache dir, and don't fail playback when track setup errors
- Ignore stale episode clicks in the detail panel via a LatestRequest guard on playback
- Extract a resetGrid helper in animeui to dedupe grid-clearing logic
- Assert reader cancellation and extracted-file writes actually happen in installer/subsync tests
2026-08-15 21:44:51 -07:00
sudacode 289c74da35 fix(anime): scope preferences, paginate sources, harden installs
- Preference store keys entries by extension package + bridge source id; legacy unscoped entries are discarded once instead of being handed to whichever extension asks first
- Source picker's "Load more" appends the next page without duplicating streamed results
- Repository index fetches and subtitle/APK downloads now time out and are size-bounded instead of hanging or growing unbounded
- APK installs are staged to a temp file and renamed into place
- Stream metadata lookup matches the requested path, not only the currently playing one
- Reworked animeui into browse-state/detail-panel/panels.css modules
- Reverted premature CHANGELOG unreleased entries; refreshed anime-browser docs
2026-08-15 21:44:51 -07:00
sudacode c94830531c fix(anime): thread episode metadata through stream playback and fix seas
- Split anime browser stream titles into series/season/episode fields (episode-metadata.ts) instead of one joined string, so stats grouping, the mpv title, and the Jimaku/TsukiHime modals all get real values instead of a filename-derived "m3u8"
- Fix AniList season resolver to walk through split-cour sequels and specials without counting them as a season, and to surface rate-limit/network failures instead of falling through to a wrong air-order guess
- Add a Season field to the TsukiHime modal and include later seasons in its search query
- Rewrite WebVTT subtitle tracks as SRT before handing them to alass, since alass has no VTT support and streams serve VTT
- Update CHANGELOG and troubleshooting docs
2026-08-15 21:44:51 -07:00
sudacode feb8d5a55c fix(anime): cap outcome polling and upstream stalls by wall clock
- watchPlaybackOutcome now tracks a real deadline so slow property reads eat the timeout budget instead of extending it, and a zero probe interval still terminates
- stream strip proxy aborts upstream GETs that go silent for 15s instead of hanging mpv on that segment forever
- anime browser runtime drops a stream proxy that finishes starting after its bridge already died, instead of leaking a listener pointed at nothing
2026-08-15 21:44:51 -07:00
sudacode d1d128b3f2 feat(anime): cache stream subtitles to disk for the alass reference
- Download a stream's subtitle tracks to a temp dir and load them into mpv as files instead of streaming from the source URL, so Subsync can use them as the alass reference (mirrors the Jellyfin subtitle preload)
- Detect format from content first, falling back to the URL extension
- A track that fails to download falls back to its URL so the episode still plays
- Remove the temp dir when the next episode loads or the runtime disposes
2026-08-15 21:44:51 -07:00
sudacode 2fbf27faff fix(anime): report a failed bridge kill instead of a generic timeout
- Track kill errors separately from exit/spawn so a signal failure (e.g. EPERM) surfaces its own message instead of a bare "did not exit after SIGKILL"
- Attach stop() failures as the cause on the readiness-timeout error so a surviving child's kill failure isn't dropped
- Skip stop() entirely when spawn itself failed, and stop polling once the ready deadline has passed
- Add stopTimeoutMs test hook and a test covering a kill that fails without the child exiting
2026-08-15 21:44:51 -07:00
sudacode 4739c3da78 fix(anime): restart the bridge on the next request after it dies
The reported 'APK crash' turned out not to exist: repeated full scans of
all installed extensions load cleanly. The real incident was the app's
quit sequence stopping the bridge (its /stop endpoint) while requests
were in flight - and it exposed that a bridge dying for any reason left
the anime browser failing every call with a raw 'fetch failed' until
the whole app was restarted.

SidecarHandle now reports the child's exit (including to late
subscribers), and the runtime detects a death it did not order: it
drops the dead handle, closes the strip proxy, tells the UI, and the
next request transparently starts a fresh bridge. requireBridge became
an async bridge() that starts on demand, which also covers first use.

Verified live: search -> SIGKILL the JVM -> search recovers.
2026-08-15 21:44:51 -07:00
sudacode ec66f59257 fix(anime): never forward Range to the bridge so 206 replies cannot skip the strip
ffmpeg opens every HLS segment with 'Range: bytes=0-'. The bridge
answers some of those 206 (depending on its cache state), and the proxy
only rewrites full 200 bodies, so the PNG disguise passed through
untouched and whether an episode played was a coin flip: first attempts
died with "no audio or video data played", the same URL played fine
once the bridge had the segments cached.

Reproduced end to end against a private bridge + mpv driven with the
app's exact commands; with Range dropped every segment is stripped and
playback runs.
2026-08-15 21:44:51 -07:00
sudacode ec9da6bed3 fix(anime): retry cold upstream fetches in the stream strip proxy
Right after an episode resolves, the bridge (or the host behind it) can
error on the very first segment fetches and be fine a moment later; mpv
sweeps the playlist of failing segments in ~2s and gives up with "no
audio or video data played" while a manual reload of the same URL plays.
Retry a failed GET once after 400ms and log upstream error statuses so
the next failure names the real cause in the app log.
2026-08-15 21:44:51 -07:00
sudacode 7643855e61 fix(anime): strip disguised HLS segments and report real playback errors
Some hosts prepend a fake image header (a real 1x1 PNG) to every HLS
segment; ffmpeg probes the segment as a picture and mpv drops back to
idle with no window while the browser claims the episode is playing.

- Route bridge-served m3u8 streams through a local strip proxy that
  scans each segment for the first genuine MPEG-TS packet run and drops
  the junk in front of it; playlists get absolute origins rewritten so
  segment requests come back through the proxy. Non-TS bodies pass
  through untouched.
- Only report ok from playEpisode once mpv configures a video output;
  an end-file with reason error surfaces mpv's own message (e.g. "no
  audio or video data played") in the browser status bar instead of
  "Playing". New end-file event plumbed through the mpv IPC client.
2026-08-15 21:44:51 -07:00
sudacode f8a8235b7d fix(anime): pin linux-x64 bridge checksum and fetch release by tag
- Add PINNED_BUNDLE_SHA256 entry for linux-x64-bundle.zip so Linux no longer refuses to start with "No pinned checksum"
- Fetch the bridge release by its pinned tag (releases/tags/<tag>) instead of listing newest releases, so an upstream publish can't swap in an unverified asset
- Update docs and changelog to describe the pin/tag behavior
2026-08-15 21:44:51 -07:00
sudacode c201520da3 fix(anime): honor the sidecar readiness deadline and confirm shutdown
The capabilities probe used a fixed 5s timeout, so a readiness budget
shorter than that could be overrun by one stalled request. Pass the
remaining deadline down instead.

stop() also resolved after the SIGKILL wait even when the child had not
exited, letting a restart race a process still holding the port. Throw
in that case, and keep a failed shutdown from masking the readiness
error at startup.
2026-08-15 21:44:51 -07:00
sudacode a612d44535 fix(anime): harden the extension bridge against untrusted repos and hangs
Addresses CodeRabbit review feedback on the Anime Browser:

- reject repository package/apk names that are not plain identifiers, and
  verify the install target resolves inside the extensions directory
- count mpv's %n% option escape in UTF-8 bytes, and escape backslashes in
  header values so a trailing one cannot eat the list separator
- key the bridge extension-id cache by APK content, so an in-place upgrade
  re-uploads instead of running the previous build
- bound every bridge, release-listing, and download request with a timeout
- enforce the APK size limit while streaming rather than after buffering
- read APK bytes on demand instead of holding a base64 copy per extension
  for the lifetime of the browser
- serialize preference mutations and write the file atomically
- handle the sidecar spawn error event, and wait for the child to exit in
  stop() before returning
- report a failed Anime Browser bootstrap instead of showing the starting
  banner forever
- keep the preferences panel's save confirmation and in-flight multi-select
  edits by re-rendering only on a structural schema change
2026-08-15 21:44:51 -07:00
sudacode ec48f90cd4 feat(anime): add anime browser powered by Aniyomi extensions
- Add `subminer anime` / `--anime` and a tray entry to open a browser that searches installed Aniyomi extension sources, shows cover art and episodes, and plays into mpv with overlay/mining attached
- Add an Extensions tab to add repos and install/update/remove sources, and per-source settings for sources needing config
- Support searching all sources at once with streaming, per-source results and status
- Prefer Japanese audio/subtitle tracks from the source and keep the primary subtitle slot reserved for Japanese
- Fix window/tray/Dock handling so the browser and mpv can be switched between without quitting the app or losing the Dock icon
- Add anime.repos, anime.extensionsDir, anime.preferredQuality config keys (no bundled repos or discovery)
2026-08-15 21:44:51 -07:00