Commit Graph

131 Commits

Author SHA1 Message Date
sudacode 23d790d8f2 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-06 21:48:00 -07:00
sudacode b528440d48 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-06 21:48:00 -07:00
sudacode c1e6e44025 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-06 21:48:00 -07:00
sudacode 07a97fd64c 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-06 21:48:00 -07:00
sudacode ca5fc341cb 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-06 21:48:00 -07:00
sudacode ee08512988 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-06 21:48:00 -07:00
sudacode dbdf578c68 perf(tokenizer): single-pass Yomitan scan with cross-line caching and prefetch fixes (#185) 2026-08-06 21:44:09 -07:00
sudacode 441ecf3c04 feat(overlay): add in-app changelog modal (#187) 2026-08-05 22:19:13 -07:00
sudacode fe4dacc1e7 fix(overlay): show plain subtitle line immediately on tokenization cache miss (#184) 2026-08-04 01:55:52 -07:00
sudacode b08cd0db35 fix(streaming): keep subtitle tokenization prefetch warm for full episodes (#183) 2026-08-03 21:22:18 -07:00
sudacode bffb1c5982 fix(logging): surface subtitle processing debug/warn logs (#182) 2026-08-03 20:44:39 -07:00
sudacode 5b8848518a feat(subsync): add reference and target subtitle track picker (#181) 2026-08-03 01:00:14 -07:00
sudacode 6607c333bc fix(overlay): strip spinner frame from subsync overlay card
- Add overlayBody override to ConfiguredStatusNotificationOptions so overlay/OSD/desktop can diverge
- Extract getSubsyncStatusNotificationOptions() to strip the ASCII spinner frame from the overlay card (OSD keeps it since it renders the raw spinner)
- Add tests for spinner stripping and subsync result notifications
2026-07-31 18:03:26 -07:00
sudacode b204d4dd6e feat(anki): add configurable word card type for Kiku/Lapis (#175) 2026-07-31 17:17:29 -07:00
sudacode 89ed675935 fix(overlay): keep Yomitan popup interactive on macOS/Windows (#177) 2026-07-30 19:47:08 -07:00
sudacode 0d7084c8aa fix(anilist): resolve later seasons via sequel relations, not title guessing (#173) 2026-07-28 22:56:26 -07:00
sudacode 987b325edb Anki maturity-based known-word highlighting (#172) 2026-07-27 23:58:02 -07:00
sudacode 2398f5c030 refactor(main): eliminate local pass-through wrappers in main.ts (#168) 2026-07-15 03:22:03 -07:00
sudacode 2e2ee3f028 refactor(tsukihime): swap Animetosho backend for TsukiHime API (#165) 2026-07-13 22:03:35 -07:00
sudacode 49b926e08c Sync Stats & History window, headless --sync-cli, and Windows remote support (#160) 2026-07-13 18:56:51 -07:00
sudacode 6fe1e0fee4 refactor(stats): drop dead IPC handlers, unify stats types over HTTP (#164) 2026-07-13 12:09:56 -07:00
sudacode 14070acceb fix(overlay): defer autoplay release for untokenized startup priming
- Autoplay-ready gate now ignores untokenized subtitle payloads while tokenization warmup is pending, so playback doesn't resume before the first tokenized cue
- Wire isTokenizationReady dep through main.ts and update gate/wiring tests accordingly
- Drop stale release/release-notes.md, add changelog entry under changes/
2026-07-12 02:11:10 -07:00
sudacode 7d81342f0f fix(app): keep AppImage mount alive until Chromium children finish shutdown
Background AppImage launches executed directly from a FUSE mount owned by a
short-lived helper's AppImage runtime. On quit, the runtime unmounted the
squashfs while utility children (network service) were still mid-shutdown,
SIGBUSing them and triggering KDE Service Crash notifications on every video
close. Detach a POSIX-sh supervisor instead: mount via --appimage-mount, run
AppRun from the mount, and release the holder only once no process still
executes from the mount. Falls back to the old direct launch on any failure
or with SUBMINER_NO_APPIMAGE_MOUNT_KEEPALIVE=1.
2026-07-12 02:09:42 -07:00
sudacode 4b7f750919 feat(animetosho): add English/Japanese subtitle download integration (#159) 2026-07-12 00:48:12 -07:00
sudacode 6ab3d823a4 feat(shortcuts): make clipboard-video-append shortcut configurable (#158) 2026-07-11 23:36:44 -07:00
sudacode 7b1a005a65 feat(anki): mirror mpv software volume into generated sentence audio (#155) 2026-07-10 00:44:23 -07:00
sudacode db4139ba0b fix(tokenizer): block kanji reading collisions and name/generic length t
- Add allowReadingOnlyMatch:false to kanji token known-word lookups so 渓谷/けいこく no longer matches a mined 警告/けいこく card via reading-only index
- Greedy name pre-pass yields when a strictly longer generic word starts at the same position (空 no longer splits 空気; ties still go to the name)
2026-07-09 01:03:58 -07:00
sudacode 61f39d1e09 fix(overlay): resolve unspaced Japanese name splits and scan recovery (#146) 2026-07-07 02:33:46 -07:00
sudacode ad1d240f20 refactor(tests): centralize lane definitions and add per-file isolation (#143) 2026-07-07 01:51:05 -07:00
sudacode 0a58c20ad7 fix(stats): start stats server on background app launch (#144) 2026-07-07 00:16:57 -07:00
sudacode 38ddb29aa0 feat(anki): reading-aware known-word matching (cache v3) (#142) 2026-07-07 00:13:10 -07:00
sudacode a042b04357 fix(overlay): prevent field grouping modal from freezing overlay on Hyprland (#138) 2026-07-06 22:13:14 -07:00
sudacode 4b10e85053 chore(release): prepare v0.17.2 2026-06-28 23:03:18 -07:00
sudacode c942a2cf2d fFix(youtube): recover source URL for background media cache on direct mpv open (#132) 2026-06-28 22:46:11 -07:00
sudacode f65afa6046 feat(youtube): notify on manual picker open and show success after track load (#133) 2026-06-28 22:43:16 -07:00
sudacode 36f94151b8 fix(logs): use local date for log filenames and expand export redaction (#131) 2026-06-27 21:08:11 -07:00
sudacode 5326ad32f5 feat(youtube): add mediaCache mode and safer stream media extraction (#130) 2026-06-27 19:20:18 -07:00
sudacode 70da3ee8bd Fix Windows Anki startup and overlay regressions (#128) 2026-06-14 20:51:56 -07:00
sudacode a117c5759c fix(linux): auto-install managed plugin copy; include in asset updates (#127) 2026-06-14 17:25:28 -07:00
sudacode 33e767458f refactor(main): split main.ts into focused runtime modules (#123) 2026-06-12 17:35:46 -07:00
sudacode 0a384a22c9 Replace subtitle delay actions with native mpv keybindings (#120) 2026-06-12 00:03:06 -07:00
sudacode 131b23efa9 chore(release): prepare v0.16.0 2026-06-10 23:05:37 -07:00
sudacode 7be1843c41 feat(notifications): add overlay notifications with position config (#110) 2026-06-10 22:46:52 -07:00
sudacode 2007e28be8 feat(aniskip): move intro detection from mpv plugin to app runtime (#117) 2026-06-09 23:55:43 -07:00
sudacode 311f1e8ee5 feat(stats): speed up session maintenance and improve stats UI (#111) 2026-06-08 02:20:52 -07:00
Autumn (Bee) af67c53dd6 [codex] Restart Jellyfin remote session after setup login (#112) 2026-06-06 11:52:16 -07:00
sudacode 76f99e6518 fix(overlay): correct Hyprland fullscreen overlay alignment on Linux (#107) 2026-06-01 02:12:16 -07:00
sudacode f1e260e996 fix(overlay): fix macOS overlay interactivity and focus after autoplay (#106) 2026-06-01 01:34:27 -07:00
sudacode e6a004ab8b Fix Windows mpv shortcut attachment to background app (#105) 2026-05-31 21:46:00 -07:00
sudacode b510c54875 fix(overlay): restore mpv focus and pointer state on macOS (#104) 2026-05-31 21:25:04 -07:00