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)
This commit is contained in:
sudacode committed 2026-07-31 17:21:12 -07:00
1 parent b204d4dd6e
commit e64ff1a0ee
117 files changed
+7565 -529

No files matched your search

@@ -4,6 +4,7 @@ import { getDefaultMpvSocketPath } from '../../shared/mpv-socket-path';
export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
ResolvedConfig,
| 'ankiConnect'
| 'anime'
| 'jimaku'
| 'tsukihime'
| 'anilist'
@@ -95,6 +96,13 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
wordCardKind: 'word-and-sentence',
},
},
anime: {
// Empty by default: SubMiner ships no extension repositories and performs
// no discovery. Sources exist only once the user adds a repo or an APK.
extensionsDir: '',
repos: [],
preferredQuality: '',
},
jimaku: {
apiBaseUrl: 'https://jimaku.cc',
apiKey: '',
@@ -566,6 +566,27 @@ export function buildIntegrationConfigOptionRegistry(
defaultValue: defaultConfig.mpv.aniskipButtonKey,
description: 'mpv key used to skip the detected intro while the skip prompt is visible.',
},
{
path: 'anime.extensionsDir',
kind: 'string',
defaultValue: defaultConfig.anime.extensionsDir,
description:
'Directory holding Aniyomi extension .apk files. Empty uses <userData>/anime-extensions.',
},
{
path: 'anime.repos',
kind: 'array',
defaultValue: defaultConfig.anime.repos,
description:
'Extension repository index URLs (any https .json index, e.g. https://.../index.min.json). Empty by default; SubMiner ships no repositories.',
},
{
path: 'anime.preferredQuality',
kind: 'string',
defaultValue: defaultConfig.anime.preferredQuality,
description:
'Preferred stream quality label, matched as a substring (for example: 1080). Empty uses the source order.',
},
{
path: 'jellyfin.enabled',
kind: 'boolean',
@@ -141,6 +141,15 @@ const INTEGRATION_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [
],
key: 'ankiConnect',
},
{
title: 'Anime Browser',
description: [
'Anime browser sources. SubMiner ships no extension repositories and bundles no sources;',
'add a repository index URL here (or drop .apk files in the extensions directory) to have any.',
],
notes: ['Hot-reload: anime changes apply the next time the anime browser opens.'],
key: 'anime',
},
{
title: 'Jimaku',
description: ['Jimaku API configuration and defaults.'],