From b5eb20e8fe972e1b505d2d98dff2dac7cfb01e66 Mon Sep 17 00:00:00 2001 From: sudacode Date: Mon, 13 Jul 2026 01:12:11 -0700 Subject: [PATCH] refactor(tsukihime): rename animetosho integration to tsukihime The animetosho backend was swapped for TsukiHime and never shipped in a release (the integration landed after v0.18.0), so no config migration or legacy aliases are needed. Renames the module, IPC channels, config key, session action, shortcut id, CLI flag, DOM ids, and CSS classes. "animetosho" is kept only where it names the upstream service: the imported-entry flag TsukiHime returns, the /tosho/ storage mirror path, and storage.animetosho.org, which that mirror currently redirects to. Also drops two stray NUL bytes that have sat inside the dedup-key template literals since the integration landed (#159). They were harmless (any separator groups correctly) but made grep treat the file as binary. --- src/animetosho/lang.test.ts | 45 -- src/cli/args.test.ts | 4 +- src/cli/args.ts | 16 +- src/config/definitions.ts | 4 +- src/config/definitions/defaults-core.ts | 2 +- .../definitions/defaults-integrations.ts | 4 +- src/config/definitions/options-core.ts | 4 +- .../definitions/options-integrations.ts | 8 +- src/config/definitions/shared.ts | 2 +- src/config/definitions/template-sections.ts | 3 +- src/config/resolve/core-domains.ts | 2 +- src/config/resolve/subtitle-domains.ts | 18 +- src/config/settings/registry.ts | 2 +- src/core/services/anki-jimaku-ipc.test.ts | 54 +- src/core/services/anki-jimaku-ipc.ts | 80 +-- src/core/services/anki-jimaku.test.ts | 28 +- src/core/services/anki-jimaku.ts | 74 +-- src/core/services/app-lifecycle.test.ts | 2 +- src/core/services/cli-command.test.ts | 2 +- src/core/services/cli-command.ts | 8 +- src/core/services/ipc-command.test.ts | 6 +- src/core/services/ipc-command.ts | 8 +- .../services/overlay-shortcut-handler.test.ts | 22 +- src/core/services/overlay-shortcut-handler.ts | 14 +- src/core/services/overlay-shortcut.test.ts | 8 +- src/core/services/overlay-shortcut.ts | 4 +- src/core/services/session-actions.test.ts | 2 +- src/core/services/session-actions.ts | 6 +- src/core/services/session-bindings.test.ts | 2 +- src/core/services/session-bindings.ts | 6 +- src/core/services/startup-bootstrap.test.ts | 2 +- src/core/utils/shortcut-config.ts | 4 +- src/main.ts | 14 +- src/main/dependencies.ts | 4 +- src/main/ipc-mpv-command.ts | 4 +- src/main/overlay-runtime.ts | 10 +- src/main/overlay-shortcuts-runtime.ts | 6 +- .../composers/ipc-runtime-composer.test.ts | 2 +- .../runtime/first-run-setup-service.test.ts | 2 +- src/main/runtime/first-run-setup-service.ts | 2 +- .../global-shortcuts-runtime-handlers.test.ts | 2 +- src/main/runtime/global-shortcuts.test.ts | 2 +- .../ipc-bridge-actions-main-deps.test.ts | 2 +- src/main/runtime/ipc-bridge-actions.test.ts | 2 +- .../runtime/ipc-mpv-command-main-deps.test.ts | 6 +- src/main/runtime/ipc-mpv-command-main-deps.ts | 2 +- ...verlay-shortcuts-runtime-main-deps.test.ts | 2 +- .../overlay-shortcuts-runtime-main-deps.ts | 2 +- .../{animetosho-open.ts => tsukihime-open.ts} | 16 +- src/preload.ts | 42 +- src/renderer/handlers/keyboard.test.ts | 4 +- src/renderer/handlers/keyboard.ts | 6 +- src/renderer/index.html | 26 +- src/renderer/modals/animetosho.ts | 489 ------------------ src/renderer/modals/session-help-sections.ts | 8 +- .../{animetosho.test.ts => tsukihime.test.ts} | 128 ++--- src/renderer/modals/tsukihime.ts | 489 ++++++++++++++++++ src/renderer/renderer.ts | 22 +- src/renderer/state.ts | 32 +- src/renderer/style.css | 14 +- src/renderer/utils/dom.ts | 48 +- src/shared/ipc/contracts.ts | 12 +- src/shared/ipc/validators.ts | 14 +- .../fetch-limits.test.ts | 18 +- src/tsukihime/lang.test.ts | 45 ++ src/{animetosho => tsukihime}/lang.ts | 18 +- src/{animetosho => tsukihime}/utils.test.ts | 118 ++--- src/{animetosho => tsukihime}/utils.ts | Bin 12017 -> 12082 bytes src/types/config.ts | 8 +- src/types/integrations.ts | 16 +- src/types/runtime.ts | 36 +- src/types/session-bindings.ts | 2 +- 72 files changed, 1060 insertions(+), 1061 deletions(-) delete mode 100644 src/animetosho/lang.test.ts rename src/main/runtime/{animetosho-open.ts => tsukihime-open.ts} (74%) delete mode 100644 src/renderer/modals/animetosho.ts rename src/renderer/modals/{animetosho.test.ts => tsukihime.test.ts} (76%) create mode 100644 src/renderer/modals/tsukihime.ts rename src/{animetosho => tsukihime}/fetch-limits.test.ts (82%) create mode 100644 src/tsukihime/lang.test.ts rename src/{animetosho => tsukihime}/lang.ts (67%) rename src/{animetosho => tsukihime}/utils.test.ts (61%) rename src/{animetosho => tsukihime}/utils.ts (87%) diff --git a/src/animetosho/lang.test.ts b/src/animetosho/lang.test.ts deleted file mode 100644 index 3dce1cab..00000000 --- a/src/animetosho/lang.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import assert from 'node:assert/strict'; -import test from 'node:test'; - -import { - animetoshoLangToFilenameSuffix, - animetoshoTrackMatchesLanguages, - describeAnimetoshoTabLanguages, - normalizeAnimetoshoLangCode, -} from './lang.js'; - -test('normalizeAnimetoshoLangCode collapses 2/3-letter and region variants', () => { - assert.equal(normalizeAnimetoshoLangCode('eng'), 'en'); - assert.equal(normalizeAnimetoshoLangCode('en'), 'en'); - assert.equal(normalizeAnimetoshoLangCode('en-US'), 'en'); - assert.equal(normalizeAnimetoshoLangCode('GER'), 'de'); - assert.equal(normalizeAnimetoshoLangCode('jpn'), 'ja'); - assert.equal(normalizeAnimetoshoLangCode('vie'), 'vie'); - assert.equal(normalizeAnimetoshoLangCode(''), ''); -}); - -test('animetoshoTrackMatchesLanguages matches across code forms', () => { - assert.equal(animetoshoTrackMatchesLanguages('eng', ['en']), true); - assert.equal(animetoshoTrackMatchesLanguages('eng', ['en', 'eng']), true); - assert.equal(animetoshoTrackMatchesLanguages('ger', ['de']), true); - assert.equal(animetoshoTrackMatchesLanguages('por', ['en']), false); - assert.equal(animetoshoTrackMatchesLanguages('spa', ['en', 'de']), false); -}); - -test('animetoshoTrackMatchesLanguages keeps unknown-language tracks visible', () => { - assert.equal(animetoshoTrackMatchesLanguages('', ['en']), true); - assert.equal(animetoshoTrackMatchesLanguages('und', ['en']), true); -}); - -test('describeAnimetoshoTabLanguages names common languages and dedupes', () => { - assert.equal(describeAnimetoshoTabLanguages(['en', 'eng']), 'English'); - assert.equal(describeAnimetoshoTabLanguages(['de']), 'German'); - assert.equal(describeAnimetoshoTabLanguages(['en', 'de']), 'English / German'); - assert.equal(describeAnimetoshoTabLanguages(['vie']), 'VIE'); - assert.equal(describeAnimetoshoTabLanguages([]), 'English'); -}); - -test('animetoshoLangToFilenameSuffix is re-exported from the pure module', () => { - assert.equal(animetoshoLangToFilenameSuffix('jpn'), 'ja'); - assert.equal(animetoshoLangToFilenameSuffix('eng'), 'en'); -}); diff --git a/src/cli/args.test.ts b/src/cli/args.test.ts index 556f0cf3..93f957ae 100644 --- a/src/cli/args.test.ts +++ b/src/cli/args.test.ts @@ -115,7 +115,7 @@ test('parseArgs captures session action forwarding flags', () => { '--toggle-stats-overlay', '--mark-watched', '--open-jimaku', - '--open-animetosho', + '--open-tsukihime', '--open-youtube-picker', '--open-playlist-browser', '--toggle-primary-subtitle-bar', @@ -133,7 +133,7 @@ test('parseArgs captures session action forwarding flags', () => { assert.equal(args.toggleStatsOverlay, true); assert.equal(args.markWatched, true); assert.equal(args.openJimaku, true); - assert.equal(args.openAnimetosho, true); + assert.equal(args.openTsukihime, true); assert.equal(args.openYoutubePicker, true); assert.equal(args.openPlaylistBrowser, true); assert.equal(args.togglePrimarySubtitleBar, true); diff --git a/src/cli/args.ts b/src/cli/args.ts index 25a50a01..b77e38eb 100644 --- a/src/cli/args.ts +++ b/src/cli/args.ts @@ -37,7 +37,7 @@ export interface CliArgs { openControllerSelect: boolean; openControllerDebug: boolean; openJimaku: boolean; - openAnimetosho: boolean; + openTsukihime: boolean; openYoutubePicker: boolean; openPlaylistBrowser: boolean; replayCurrentSubtitle: boolean; @@ -146,7 +146,7 @@ export function parseArgs(argv: string[]): CliArgs { openControllerSelect: false, openControllerDebug: false, openJimaku: false, - openAnimetosho: false, + openTsukihime: false, openYoutubePicker: false, openPlaylistBrowser: false, replayCurrentSubtitle: false, @@ -294,7 +294,7 @@ export function parseArgs(argv: string[]): CliArgs { else if (arg === '--open-controller-select') args.openControllerSelect = true; else if (arg === '--open-controller-debug') args.openControllerDebug = true; else if (arg === '--open-jimaku') args.openJimaku = true; - else if (arg === '--open-animetosho') args.openAnimetosho = true; + else if (arg === '--open-tsukihime') args.openTsukihime = true; else if (arg === '--open-youtube-picker') args.openYoutubePicker = true; else if (arg === '--open-playlist-browser') args.openPlaylistBrowser = true; else if (arg === '--replay-current-subtitle') args.replayCurrentSubtitle = true; @@ -567,7 +567,7 @@ export function hasExplicitCommand(args: CliArgs): boolean { args.openControllerSelect || args.openControllerDebug || args.openJimaku || - args.openAnimetosho || + args.openTsukihime || args.openYoutubePicker || args.openPlaylistBrowser || args.replayCurrentSubtitle || @@ -645,7 +645,7 @@ export function isStandaloneTexthookerCommand(args: CliArgs): boolean { !args.openControllerSelect && !args.openControllerDebug && !args.openJimaku && - !args.openAnimetosho && + !args.openTsukihime && !args.openYoutubePicker && !args.openPlaylistBrowser && !args.replayCurrentSubtitle && @@ -712,7 +712,7 @@ export function shouldStartApp(args: CliArgs): boolean { args.openControllerSelect || args.openControllerDebug || args.openJimaku || - args.openAnimetosho || + args.openTsukihime || args.openYoutubePicker || args.openPlaylistBrowser || args.replayCurrentSubtitle || @@ -773,7 +773,7 @@ export function shouldRunYomitanOnlyStartup(args: CliArgs): boolean { !args.openControllerSelect && !args.openControllerDebug && !args.openJimaku && - !args.openAnimetosho && + !args.openTsukihime && !args.openYoutubePicker && !args.openPlaylistBrowser && !args.replayCurrentSubtitle && @@ -839,7 +839,7 @@ export function commandNeedsOverlayRuntime(args: CliArgs): boolean { args.openControllerSelect || args.openControllerDebug || args.openJimaku || - args.openAnimetosho || + args.openTsukihime || args.openYoutubePicker || args.openPlaylistBrowser || args.replayCurrentSubtitle || diff --git a/src/config/definitions.ts b/src/config/definitions.ts index c8994d8b..0cdfc924 100644 --- a/src/config/definitions.ts +++ b/src/config/definitions.ts @@ -40,7 +40,7 @@ const { const { ankiConnect, jimaku, - animetosho, + tsukihime, anilist, mpv, yomitan, @@ -73,7 +73,7 @@ export const DEFAULT_CONFIG: ResolvedConfig = { subtitleSidebar, auto_start_overlay, jimaku, - animetosho, + tsukihime, anilist, mpv, yomitan, diff --git a/src/config/definitions/defaults-core.ts b/src/config/definitions/defaults-core.ts index b0e9f7f7..7d61e884 100644 --- a/src/config/definitions/defaults-core.ts +++ b/src/config/definitions/defaults-core.ts @@ -98,7 +98,7 @@ export const CORE_DEFAULT_CONFIG: Pick< openCharacterDictionaryManager: 'CommandOrControl+D', openRuntimeOptions: 'CommandOrControl+Shift+O', openJimaku: 'Ctrl+Shift+J', - openAnimetosho: 'Ctrl+Shift+T', + openTsukihime: 'Ctrl+Shift+T', openSessionHelp: 'CommandOrControl+Slash', openControllerSelect: 'Alt+C', openControllerDebug: 'Alt+Shift+C', diff --git a/src/config/definitions/defaults-integrations.ts b/src/config/definitions/defaults-integrations.ts index 9abe2374..bb18a955 100644 --- a/src/config/definitions/defaults-integrations.ts +++ b/src/config/definitions/defaults-integrations.ts @@ -5,7 +5,7 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick< ResolvedConfig, | 'ankiConnect' | 'jimaku' - | 'animetosho' + | 'tsukihime' | 'anilist' | 'mpv' | 'yomitan' @@ -97,7 +97,7 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick< languagePreference: 'ja', maxEntryResults: 10, }, - animetosho: { + tsukihime: { apiBaseUrl: 'https://api.tsukihime.org/v1', maxSearchResults: 10, }, diff --git a/src/config/definitions/options-core.ts b/src/config/definitions/options-core.ts index 057c4f18..f9e5a4d2 100644 --- a/src/config/definitions/options-core.ts +++ b/src/config/definitions/options-core.ts @@ -616,9 +616,9 @@ export function buildCoreConfigOptionRegistry( description: 'Accelerator that opens the Jimaku subtitle search modal.', }, { - path: 'shortcuts.openAnimetosho', + path: 'shortcuts.openTsukihime', kind: 'string', - defaultValue: defaultConfig.shortcuts.openAnimetosho, + defaultValue: defaultConfig.shortcuts.openTsukihime, description: 'Accelerator that opens the TsukiHime subtitle search modal (English/Japanese tabs).', }, diff --git a/src/config/definitions/options-integrations.ts b/src/config/definitions/options-integrations.ts index 39e99f8f..fbcbb91a 100644 --- a/src/config/definitions/options-integrations.ts +++ b/src/config/definitions/options-integrations.ts @@ -401,16 +401,16 @@ export function buildIntegrationConfigOptionRegistry( description: 'Maximum Jimaku search results returned.', }, { - path: 'animetosho.apiBaseUrl', + path: 'tsukihime.apiBaseUrl', kind: 'string', - defaultValue: defaultConfig.animetosho.apiBaseUrl, + defaultValue: defaultConfig.tsukihime.apiBaseUrl, description: 'Base URL of the TsukiHime API (Animetosho successor). No API key required.', }, { - path: 'animetosho.maxSearchResults', + path: 'tsukihime.maxSearchResults', kind: 'number', - defaultValue: defaultConfig.animetosho.maxSearchResults, + defaultValue: defaultConfig.tsukihime.maxSearchResults, description: 'Maximum TsukiHime search results returned.', }, { diff --git a/src/config/definitions/shared.ts b/src/config/definitions/shared.ts index bd045447..eb2a1073 100644 --- a/src/config/definitions/shared.ts +++ b/src/config/definitions/shared.ts @@ -53,7 +53,7 @@ export const SPECIAL_COMMANDS = { SUBSYNC_TRIGGER: '__subsync-trigger', RUNTIME_OPTIONS_OPEN: '__runtime-options-open', JIMAKU_OPEN: '__jimaku-open', - ANIMETOSHO_OPEN: '__animetosho-open', + TSUKIHIME_OPEN: '__tsukihime-open', RUNTIME_OPTION_CYCLE_PREFIX: '__runtime-option-cycle:', REPLAY_SUBTITLE: '__replay-subtitle', PLAY_NEXT_SUBTITLE: '__play-next-subtitle', diff --git a/src/config/definitions/template-sections.ts b/src/config/definitions/template-sections.ts index 521c7305..110fec7f 100644 --- a/src/config/definitions/template-sections.ts +++ b/src/config/definitions/template-sections.ts @@ -151,10 +151,9 @@ const INTEGRATION_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [ title: 'TsukiHime', description: [ 'TsukiHime subtitle search configuration (English and Japanese). No API key required.', - 'TsukiHime is the successor to Animetosho; the config key keeps the legacy name.', ], notes: ['Hot-reload: TsukiHime changes apply to the next TsukiHime request.'], - key: 'animetosho', + key: 'tsukihime', }, { title: 'YouTube Playback Settings', diff --git a/src/config/resolve/core-domains.ts b/src/config/resolve/core-domains.ts index ff1f4436..9fa093d5 100644 --- a/src/config/resolve/core-domains.ts +++ b/src/config/resolve/core-domains.ts @@ -236,7 +236,7 @@ export function applyCoreDomainConfig(context: ResolveContext): void { 'openCharacterDictionaryManager', 'openRuntimeOptions', 'openJimaku', - 'openAnimetosho', + 'openTsukihime', 'openSessionHelp', 'openControllerSelect', 'openControllerDebug', diff --git a/src/config/resolve/subtitle-domains.ts b/src/config/resolve/subtitle-domains.ts index 2f45a33e..6cf2c137 100644 --- a/src/config/resolve/subtitle-domains.ts +++ b/src/config/resolve/subtitle-domains.ts @@ -80,18 +80,18 @@ export function applySubtitleDomainConfig(context: ResolveContext): void { } } - if (isObject(src.animetosho)) { - const apiBaseUrl = asString(src.animetosho.apiBaseUrl); - if (apiBaseUrl !== undefined) resolved.animetosho.apiBaseUrl = apiBaseUrl; + if (isObject(src.tsukihime)) { + const apiBaseUrl = asString(src.tsukihime.apiBaseUrl); + if (apiBaseUrl !== undefined) resolved.tsukihime.apiBaseUrl = apiBaseUrl; - const maxSearchResults = asNumber(src.animetosho.maxSearchResults); + const maxSearchResults = asNumber(src.tsukihime.maxSearchResults); if (maxSearchResults !== undefined && Math.floor(maxSearchResults) > 0) { - resolved.animetosho.maxSearchResults = Math.floor(maxSearchResults); - } else if (src.animetosho.maxSearchResults !== undefined) { + resolved.tsukihime.maxSearchResults = Math.floor(maxSearchResults); + } else if (src.tsukihime.maxSearchResults !== undefined) { warn( - 'animetosho.maxSearchResults', - src.animetosho.maxSearchResults, - resolved.animetosho.maxSearchResults, + 'tsukihime.maxSearchResults', + src.tsukihime.maxSearchResults, + resolved.tsukihime.maxSearchResults, 'Expected positive number.', ); } diff --git a/src/config/settings/registry.ts b/src/config/settings/registry.ts index 43c91299..423b0780 100644 --- a/src/config/settings/registry.ts +++ b/src/config/settings/registry.ts @@ -594,7 +594,7 @@ function subsectionForPath(path: string): string | undefined { leaf === 'openCharacterDictionaryManager' || leaf === 'openRuntimeOptions' || leaf === 'openJimaku' || - leaf === 'openAnimetosho' || + leaf === 'openTsukihime' || leaf === 'openSessionHelp' || leaf === 'openControllerSelect' || leaf === 'openControllerDebug' diff --git a/src/core/services/anki-jimaku-ipc.test.ts b/src/core/services/anki-jimaku-ipc.test.ts index 4cb30a0e..a0f15017 100644 --- a/src/core/services/anki-jimaku-ipc.test.ts +++ b/src/core/services/anki-jimaku-ipc.test.ts @@ -55,10 +55,10 @@ test('anki/jimaku IPC handlers reject malformed invoke payloads', async () => { isRemoteMediaPath: () => false, downloadToFile: async () => ({ ok: true, path: '/tmp/sub.ass' }), onDownloadedSubtitle: () => {}, - searchAnimetoshoEntries: async () => ({ ok: true, data: [] }), - listAnimetoshoFiles: async () => ({ ok: true, data: [] }), - downloadAnimetoshoSubtitle: async () => ({ ok: true, path: '/tmp/sub.en.ass' }), - getAnimetoshoSecondaryLanguages: () => ['en'], + searchTsukihimeEntries: async () => ({ ok: true, data: [] }), + listTsukihimeFiles: async () => ({ ok: true, data: [] }), + downloadTsukihimeSubtitle: async () => ({ ok: true, path: '/tmp/sub.en.ass' }), + getTsukihimeSecondaryLanguages: () => ['en'], onDownloadedSecondarySubtitle: () => {}, }, registrar, @@ -98,31 +98,31 @@ test('anki/jimaku IPC handlers reject malformed invoke payloads', async () => { error: { error: 'Invalid Jimaku download query payload', code: 400 }, }); - const animetoshoSearchHandler = handleHandlers.get(IPC_CHANNELS.request.animetoshoSearchEntries); - assert.ok(animetoshoSearchHandler); - const invalidAnimetoshoSearch = await animetoshoSearchHandler!({}, { query: 12 }); - assert.deepEqual(invalidAnimetoshoSearch, { + const tsukihimeSearchHandler = handleHandlers.get(IPC_CHANNELS.request.tsukihimeSearchEntries); + assert.ok(tsukihimeSearchHandler); + const invalidTsukihimeSearch = await tsukihimeSearchHandler!({}, { query: 12 }); + assert.deepEqual(invalidTsukihimeSearch, { ok: false, error: { error: 'Invalid TsukiHime search query payload', code: 400 }, }); - const animetoshoFilesHandler = handleHandlers.get(IPC_CHANNELS.request.animetoshoListFiles); - assert.ok(animetoshoFilesHandler); - const invalidAnimetoshoFiles = await animetoshoFilesHandler!({}, { entryId: 'x' }); - assert.deepEqual(invalidAnimetoshoFiles, { + const tsukihimeFilesHandler = handleHandlers.get(IPC_CHANNELS.request.tsukihimeListFiles); + assert.ok(tsukihimeFilesHandler); + const invalidTsukihimeFiles = await tsukihimeFilesHandler!({}, { entryId: 'x' }); + assert.deepEqual(invalidTsukihimeFiles, { ok: false, error: { error: 'Invalid TsukiHime files query payload', code: 400 }, }); - const animetoshoDownloadHandler = handleHandlers.get(IPC_CHANNELS.request.animetoshoDownloadFile); - assert.ok(animetoshoDownloadHandler); - const invalidAnimetoshoDownload = await animetoshoDownloadHandler!({}, { entryId: 1, url: '/x' }); - assert.deepEqual(invalidAnimetoshoDownload, { + const tsukihimeDownloadHandler = handleHandlers.get(IPC_CHANNELS.request.tsukihimeDownloadFile); + assert.ok(tsukihimeDownloadHandler); + const invalidTsukihimeDownload = await tsukihimeDownloadHandler!({}, { entryId: 1, url: '/x' }); + assert.deepEqual(invalidTsukihimeDownload, { ok: false, error: { error: 'Invalid TsukiHime download query payload', code: 400 }, }); - const foreignUrlDownload = await animetoshoDownloadHandler!( + const foreignUrlDownload = await tsukihimeDownloadHandler!( {}, { entryId: 1, url: 'https://evil.example/attach/00000001/1.xz', name: 'sub.ass' }, ); @@ -132,7 +132,7 @@ test('anki/jimaku IPC handlers reject malformed invoke payloads', async () => { }); }); -test('animetosho downloads route by language: secondary for eng, primary for jpn', async () => { +test('tsukihime downloads route by language: secondary for eng, primary for jpn', async () => { const { registrar, handleHandlers } = createFakeRegistrar(); const primaryLoads: string[] = []; const secondaryLoads: string[] = []; @@ -160,10 +160,10 @@ test('animetosho downloads route by language: secondary for eng, primary for jpn onDownloadedSubtitle: (path) => { primaryLoads.push(path); }, - searchAnimetoshoEntries: async () => ({ ok: true, data: [] }), - listAnimetoshoFiles: async () => ({ ok: true, data: [] }), - downloadAnimetoshoSubtitle: async (_url, destPath) => ({ ok: true, path: destPath }), - getAnimetoshoSecondaryLanguages: () => ['en'], + searchTsukihimeEntries: async () => ({ ok: true, data: [] }), + listTsukihimeFiles: async () => ({ ok: true, data: [] }), + downloadTsukihimeSubtitle: async (_url, destPath) => ({ ok: true, path: destPath }), + getTsukihimeSecondaryLanguages: () => ['en'], onDownloadedSecondarySubtitle: (path) => { secondaryLoads.push(path); }, @@ -171,7 +171,7 @@ test('animetosho downloads route by language: secondary for eng, primary for jpn registrar, ); - const downloadHandler = handleHandlers.get(IPC_CHANNELS.request.animetoshoDownloadFile)!; + const downloadHandler = handleHandlers.get(IPC_CHANNELS.request.tsukihimeDownloadFile)!; const engResult = (await downloadHandler!( {}, @@ -232,10 +232,10 @@ test('anki/jimaku IPC command handlers ignore malformed payloads', () => { isRemoteMediaPath: () => false, downloadToFile: async () => ({ ok: true, path: '/tmp/sub.ass' }), onDownloadedSubtitle: () => {}, - searchAnimetoshoEntries: async () => ({ ok: true, data: [] }), - listAnimetoshoFiles: async () => ({ ok: true, data: [] }), - downloadAnimetoshoSubtitle: async () => ({ ok: true, path: '/tmp/sub.en.ass' }), - getAnimetoshoSecondaryLanguages: () => ['en'], + searchTsukihimeEntries: async () => ({ ok: true, data: [] }), + listTsukihimeFiles: async () => ({ ok: true, data: [] }), + downloadTsukihimeSubtitle: async () => ({ ok: true, path: '/tmp/sub.en.ass' }), + getTsukihimeSecondaryLanguages: () => ['en'], onDownloadedSecondarySubtitle: () => {}, }, registrar, diff --git a/src/core/services/anki-jimaku-ipc.ts b/src/core/services/anki-jimaku-ipc.ts index 294128da..22fd9b58 100644 --- a/src/core/services/anki-jimaku-ipc.ts +++ b/src/core/services/anki-jimaku-ipc.ts @@ -4,12 +4,12 @@ import * as path from 'path'; import * as os from 'os'; import { createLogger } from '../../logger'; import { - AnimetoshoApiResponse, - AnimetoshoDownloadResult, - AnimetoshoEntry, - AnimetoshoFilesQuery, - AnimetoshoSearchQuery, - AnimetoshoSubtitleFile, + TsukihimeApiResponse, + TsukihimeDownloadResult, + TsukihimeEntry, + TsukihimeFilesQuery, + TsukihimeSearchQuery, + TsukihimeSubtitleFile, JimakuApiResponse, JimakuDownloadResult, JimakuEntry, @@ -23,9 +23,9 @@ import { } from '../../types'; import { IPC_CHANNELS } from '../../shared/ipc/contracts'; import { - parseAnimetoshoDownloadQuery, - parseAnimetoshoFilesQuery, - parseAnimetoshoSearchQuery, + parseTsukihimeDownloadQuery, + parseTsukihimeFilesQuery, + parseTsukihimeSearchQuery, parseJimakuDownloadQuery, parseJimakuFilesQuery, parseJimakuSearchQuery, @@ -33,7 +33,7 @@ import { parseKikuMergePreviewRequest, } from '../../shared/ipc/validators'; import { buildJimakuSubtitleFilenameFromMediaPath } from './jimaku-download-path'; -import { animetoshoLangToFilenameSuffix, isAnimetoshoDownloadUrl } from '../../animetosho/utils'; +import { tsukihimeLangToFilenameSuffix, isTsukihimeDownloadUrl } from '../../tsukihime/utils'; const { ipcMain } = electron; @@ -57,14 +57,14 @@ export interface AnkiJimakuIpcDeps { headers: Record, ) => Promise; onDownloadedSubtitle: (pathToSubtitle: string) => void; - searchAnimetoshoEntries: ( - query: AnimetoshoSearchQuery, - ) => Promise>; - listAnimetoshoFiles: ( - query: AnimetoshoFilesQuery, - ) => Promise>; - downloadAnimetoshoSubtitle: (url: string, destPath: string) => Promise; - getAnimetoshoSecondaryLanguages: () => string[]; + searchTsukihimeEntries: ( + query: TsukihimeSearchQuery, + ) => Promise>; + listTsukihimeFiles: ( + query: TsukihimeFilesQuery, + ) => Promise>; + downloadTsukihimeSubtitle: (url: string, destPath: string) => Promise; + getTsukihimeSecondaryLanguages: () => string[]; onDownloadedSecondarySubtitle: (pathToSubtitle: string) => void | Promise; } @@ -206,39 +206,39 @@ export function registerAnkiJimakuIpcHandlers( }, ); - ipc.handle(IPC_CHANNELS.request.animetoshoGetSecondaryLanguages, (): string[] => { - return deps.getAnimetoshoSecondaryLanguages(); + ipc.handle(IPC_CHANNELS.request.tsukihimeGetSecondaryLanguages, (): string[] => { + return deps.getTsukihimeSecondaryLanguages(); }); ipc.handle( - IPC_CHANNELS.request.animetoshoSearchEntries, - async (_event, query: unknown): Promise> => { - const parsedQuery = parseAnimetoshoSearchQuery(query); + IPC_CHANNELS.request.tsukihimeSearchEntries, + async (_event, query: unknown): Promise> => { + const parsedQuery = parseTsukihimeSearchQuery(query); if (!parsedQuery) { return { ok: false, error: { error: 'Invalid TsukiHime search query payload', code: 400 }, }; } - return deps.searchAnimetoshoEntries(parsedQuery); + return deps.searchTsukihimeEntries(parsedQuery); }, ); ipc.handle( - IPC_CHANNELS.request.animetoshoListFiles, - async (_event, query: unknown): Promise> => { - const parsedQuery = parseAnimetoshoFilesQuery(query); + IPC_CHANNELS.request.tsukihimeListFiles, + async (_event, query: unknown): Promise> => { + const parsedQuery = parseTsukihimeFilesQuery(query); if (!parsedQuery) { return { ok: false, error: { error: 'Invalid TsukiHime files query payload', code: 400 } }; } - return deps.listAnimetoshoFiles(parsedQuery); + return deps.listTsukihimeFiles(parsedQuery); }, ); ipc.handle( - IPC_CHANNELS.request.animetoshoDownloadFile, - async (_event, query: unknown): Promise => { - const parsedQuery = parseAnimetoshoDownloadQuery(query); + IPC_CHANNELS.request.tsukihimeDownloadFile, + async (_event, query: unknown): Promise => { + const parsedQuery = parseTsukihimeDownloadQuery(query); if (!parsedQuery) { return { ok: false, @@ -246,7 +246,7 @@ export function registerAnkiJimakuIpcHandlers( }; } - if (!isAnimetoshoDownloadUrl(parsedQuery.url)) { + if (!isTsukihimeDownloadUrl(parsedQuery.url)) { return { ok: false, error: { error: 'Refusing to download subtitle from a non-TsukiHime URL.', code: 400 }, @@ -259,13 +259,13 @@ export function registerAnkiJimakuIpcHandlers( } const mediaDir = deps.isRemoteMediaPath(currentMediaPath) - ? fs.mkdtempSync(path.join(os.tmpdir(), 'subminer-animetosho-')) + ? fs.mkdtempSync(path.join(os.tmpdir(), 'subminer-tsukihime-')) : path.dirname(path.resolve(currentMediaPath)); const safeName = path.basename(parsedQuery.name); if (!safeName) { return { ok: false, error: { error: 'Invalid subtitle filename.' } }; } - const languageSuffix = animetoshoLangToFilenameSuffix(parsedQuery.lang); + const languageSuffix = tsukihimeLangToFilenameSuffix(parsedQuery.lang); const subtitleFilename = buildJimakuSubtitleFilenameFromMediaPath( currentMediaPath, safeName, @@ -276,24 +276,24 @@ export function registerAnkiJimakuIpcHandlers( const baseName = ext ? subtitleFilename.slice(0, -ext.length) : subtitleFilename; let targetPath = path.join(mediaDir, subtitleFilename); if (fs.existsSync(targetPath)) { - targetPath = path.join(mediaDir, `${baseName} (animetosho-${parsedQuery.entryId})${ext}`); + targetPath = path.join(mediaDir, `${baseName} (tsukihime-${parsedQuery.entryId})${ext}`); let counter = 2; while (fs.existsSync(targetPath)) { targetPath = path.join( mediaDir, - `${baseName} (animetosho-${parsedQuery.entryId}-${counter})${ext}`, + `${baseName} (tsukihime-${parsedQuery.entryId}-${counter})${ext}`, ); counter += 1; } } logger.info( - `[animetosho] download-file name="${parsedQuery.name}" entryId=${parsedQuery.entryId}`, + `[tsukihime] download-file name="${parsedQuery.name}" entryId=${parsedQuery.entryId}`, ); - const result = await deps.downloadAnimetoshoSubtitle(parsedQuery.url, targetPath); + const result = await deps.downloadTsukihimeSubtitle(parsedQuery.url, targetPath); if (result.ok) { - logger.info(`[animetosho] download-file saved to ${result.path}`); + logger.info(`[tsukihime] download-file saved to ${result.path}`); // Japanese tracks take the primary slot; anything else loads as the // secondary subtitle so the Japanese primary stays in place. if (languageSuffix === 'ja') { @@ -303,7 +303,7 @@ export function registerAnkiJimakuIpcHandlers( } } else { logger.error( - `[animetosho] download-file failed: ${result.error?.error ?? 'unknown error'}`, + `[tsukihime] download-file failed: ${result.error?.error ?? 'unknown error'}`, ); } diff --git a/src/core/services/anki-jimaku.test.ts b/src/core/services/anki-jimaku.test.ts index e5980c99..fe820288 100644 --- a/src/core/services/anki-jimaku.test.ts +++ b/src/core/services/anki-jimaku.test.ts @@ -11,7 +11,7 @@ interface RuntimeHarness { patches: boolean[]; broadcasts: number; fetchCalls: Array<{ endpoint: string; query?: Record }>; - animetoshoFetchCalls: Array<{ endpoint: string; query?: Record }>; + tsukihimeFetchCalls: Array<{ endpoint: string; query?: Record }>; sentCommands: Array<{ command: (string | number)[] }>; }; } @@ -26,7 +26,7 @@ function createHarness(): RuntimeHarness { endpoint: string; query?: Record; }>, - animetoshoFetchCalls: [] as Array<{ + tsukihimeFetchCalls: [] as Array<{ endpoint: string; query?: Record; }>, @@ -37,10 +37,10 @@ function createHarness(): RuntimeHarness { patchAnkiConnectEnabled: (enabled) => { state.patches.push(enabled); }, - getResolvedConfig: () => ({ animetosho: { maxSearchResults: 2 } }), + getResolvedConfig: () => ({ tsukihime: { maxSearchResults: 2 } }), getRuntimeOptionsManager: () => null, - animetoshoFetchJson: async (endpoint, query) => { - state.animetoshoFetchCalls.push({ + tsukihimeFetchJson: async (endpoint, query) => { + state.tsukihimeFetchCalls.push({ endpoint, query: query as Record, }); @@ -174,9 +174,9 @@ test('registerAnkiJimakuIpcRuntime provides full handler surface', () => { 'isRemoteMediaPath', 'downloadToFile', 'onDownloadedSubtitle', - 'searchAnimetoshoEntries', - 'listAnimetoshoFiles', - 'downloadAnimetoshoSubtitle', + 'searchTsukihimeEntries', + 'listTsukihimeFiles', + 'downloadTsukihimeSubtitle', 'onDownloadedSecondarySubtitle', ]; @@ -367,11 +367,11 @@ test('onDownloadedSecondarySubtitle retries until mpv reports the new track', as }); }); -test('searchAnimetoshoEntries caps results using animetosho.maxSearchResults', async () => { +test('searchTsukihimeEntries caps results using tsukihime.maxSearchResults', async () => { const { registered, state } = createHarness(); - const searchResult = await registered.searchAnimetoshoEntries!({ query: 'frieren 28' }); - assert.deepEqual(state.animetoshoFetchCalls, [ + const searchResult = await registered.searchTsukihimeEntries!({ query: 'frieren 28' }); + assert.deepEqual(state.tsukihimeFetchCalls, [ { endpoint: '/search/torrents', query: { q: 'frieren 28', limit: 2 }, @@ -386,11 +386,11 @@ test('searchAnimetoshoEntries caps results using animetosho.maxSearchResults', a ); }); -test('listAnimetoshoFiles extracts subtitle attachments from torrent detail', async () => { +test('listTsukihimeFiles extracts subtitle attachments from torrent detail', async () => { const { registered, state } = createHarness(); - const filesResult = await registered.listAnimetoshoFiles!({ entryId: 606713 }); - assert.deepEqual(state.animetoshoFetchCalls, [ + const filesResult = await registered.listTsukihimeFiles!({ entryId: 606713 }); + assert.deepEqual(state.tsukihimeFetchCalls, [ { endpoint: '/torrents/606713', query: {}, diff --git a/src/core/services/anki-jimaku.ts b/src/core/services/anki-jimaku.ts index 0c35b714..479b72e2 100644 --- a/src/core/services/anki-jimaku.ts +++ b/src/core/services/anki-jimaku.ts @@ -3,8 +3,8 @@ import { AnkiIntegration } from '../../anki-integration'; import { mergeAiConfig } from '../../ai/config'; import { AiConfig, - AnimetoshoApiResponse, - AnimetoshoConfig, + TsukihimeApiResponse, + TsukihimeConfig, AnkiConnectConfig, JimakuApiResponse, JimakuEntry, @@ -18,12 +18,12 @@ import { import { sortJimakuFiles } from '../../jimaku/utils'; import { TSUKIHIME_API_BASE_URL, - animetoshoFetchJson as animetoshoFetchJsonRequest, + tsukihimeFetchJson as tsukihimeFetchJsonRequest, decompressXzFile, - extractAnimetoshoSubtitleFiles, - isAnimetoshoDownloadUrl, - mapAnimetoshoSearchResults, -} from '../../animetosho/utils'; + extractTsukihimeSubtitleFiles, + isTsukihimeDownloadUrl, + mapTsukihimeSearchResults, +} from '../../tsukihime/utils'; import type { AnkiJimakuIpcDeps } from './anki-jimaku-ipc'; import { createLogger } from '../../logger'; @@ -48,7 +48,7 @@ export interface AnkiJimakuIpcRuntimeOptions { getResolvedConfig: () => { ankiConnect?: AnkiConnectConfig; ai?: AiConfig; - animetosho?: AnimetoshoConfig; + tsukihime?: TsukihimeConfig; secondarySub?: { secondarySubLanguages?: string[] }; }; getRuntimeOptionsManager: () => RuntimeOptionsManagerLike | null; @@ -77,10 +77,10 @@ export interface AnkiJimakuIpcRuntimeOptions { endpoint: string, query?: Record, ) => Promise>; - animetoshoFetchJson?: ( + tsukihimeFetchJson?: ( endpoint: string, query?: Record, - ) => Promise>; + ) => Promise>; getJimakuMaxEntryResults: () => number; getJimakuLanguagePreference: () => JimakuLanguagePreference; resolveJimakuApiKey: () => Promise; @@ -101,7 +101,7 @@ export interface AnkiJimakuIpcRuntimeOptions { const logger = createLogger('main:anki-jimaku'); -const DEFAULT_ANIMETOSHO_MAX_SEARCH_RESULTS = 10; +const DEFAULT_TSUKIHIME_MAX_SEARCH_RESULTS = 10; const SECONDARY_TRACK_LOOKUP_ATTEMPTS = 5; const SECONDARY_TRACK_LOOKUP_RETRY_MS = 100; @@ -109,24 +109,24 @@ function delay(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } -function getAnimetoshoMaxSearchResults(options: AnkiJimakuIpcRuntimeOptions): number { - const value = options.getResolvedConfig().animetosho?.maxSearchResults; +function getTsukihimeMaxSearchResults(options: AnkiJimakuIpcRuntimeOptions): number { + const value = options.getResolvedConfig().tsukihime?.maxSearchResults; if (typeof value === 'number' && Number.isFinite(value) && value > 0) { return Math.floor(value); } - return DEFAULT_ANIMETOSHO_MAX_SEARCH_RESULTS; + return DEFAULT_TSUKIHIME_MAX_SEARCH_RESULTS; } -function animetoshoFetch( +function tsukihimeFetch( options: AnkiJimakuIpcRuntimeOptions, endpoint: string, query: Record, -): Promise> { - if (options.animetoshoFetchJson) { - return options.animetoshoFetchJson(endpoint, query); +): Promise> { + if (options.tsukihimeFetchJson) { + return options.tsukihimeFetchJson(endpoint, query); } - const baseUrl = options.getResolvedConfig().animetosho?.apiBaseUrl || TSUKIHIME_API_BASE_URL; - return animetoshoFetchJsonRequest(endpoint, query, { baseUrl }); + const baseUrl = options.getResolvedConfig().tsukihime?.apiBaseUrl || TSUKIHIME_API_BASE_URL; + return tsukihimeFetchJsonRequest(endpoint, query, { baseUrl }); } export function registerAnkiJimakuIpcRuntime( @@ -242,41 +242,41 @@ export function registerAnkiJimakuIpcRuntime( isRemoteMediaPath: (mediaPath) => options.isRemoteMediaPath(mediaPath), downloadToFile: (url, destPath, headers) => options.downloadToFile(url, destPath, headers), - searchAnimetoshoEntries: async (query) => { - logger.info(`[animetosho] search-entries query: "${query.query}"`); - const maxResults = getAnimetoshoMaxSearchResults(options); - const response = await animetoshoFetch(options, '/search/torrents', { + searchTsukihimeEntries: async (query) => { + logger.info(`[tsukihime] search-entries query: "${query.query}"`); + const maxResults = getTsukihimeMaxSearchResults(options); + const response = await tsukihimeFetch(options, '/search/torrents', { q: query.query, // The API caps limit at 100. limit: Math.min(maxResults, 100), }); if (!response.ok) return response; - const entries = mapAnimetoshoSearchResults(response.data, maxResults); - logger.info(`[animetosho] search-entries returned ${entries.length} results`); + const entries = mapTsukihimeSearchResults(response.data, maxResults); + logger.info(`[tsukihime] search-entries returned ${entries.length} results`); return { ok: true, data: entries }; }, - listAnimetoshoFiles: async (query) => { - logger.info(`[animetosho] list-files entryId=${query.entryId}`); - const response = await animetoshoFetch( + listTsukihimeFiles: async (query) => { + logger.info(`[tsukihime] list-files entryId=${query.entryId}`); + const response = await tsukihimeFetch( options, `/torrents/${encodeURIComponent(query.entryId)}`, {}, ); if (!response.ok) return response; - const files = extractAnimetoshoSubtitleFiles(response.data); - logger.info(`[animetosho] list-files returned ${files.length} subtitle attachments`); + const files = extractTsukihimeSubtitleFiles(response.data); + logger.info(`[tsukihime] list-files returned ${files.length} subtitle attachments`); return { ok: true, data: files }; }, - getAnimetoshoSecondaryLanguages: () => + getTsukihimeSecondaryLanguages: () => options.getResolvedConfig().secondarySub?.secondarySubLanguages ?? [], - downloadAnimetoshoSubtitle: async (url, destPath) => { + downloadTsukihimeSubtitle: async (url, destPath) => { const tempXzPath = `${destPath}.xz`; const downloaded = await options.downloadToFile( url, tempXzPath, { 'User-Agent': 'SubMiner' }, - // animetosho.org redirects to storage.animetosho.org; keep the hop in-domain. - { isAllowedRedirect: (redirectUrl) => isAnimetoshoDownloadUrl(redirectUrl) }, + // The /tosho/ mirror 302s to storage.animetosho.org; keep the hop in-allowlist. + { isAllowedRedirect: (redirectUrl) => isTsukihimeDownloadUrl(redirectUrl) }, ); if (!downloaded.ok) return downloaded; const result = await decompressXzFile(tempXzPath, destPath); @@ -312,14 +312,14 @@ export function registerAnkiJimakuIpcRuntime( return; } } catch (error) { - logger.warn('[animetosho] failed to select downloaded subtitle as secondary:', error); + logger.warn('[tsukihime] failed to select downloaded subtitle as secondary:', error); return; } await delay(SECONDARY_TRACK_LOOKUP_RETRY_MS); } logger.warn( - `[animetosho] could not find downloaded subtitle in track-list: ${pathToSubtitle}`, + `[tsukihime] could not find downloaded subtitle in track-list: ${pathToSubtitle}`, ); }, }); diff --git a/src/core/services/app-lifecycle.test.ts b/src/core/services/app-lifecycle.test.ts index 36fa9fa6..a314f34c 100644 --- a/src/core/services/app-lifecycle.test.ts +++ b/src/core/services/app-lifecycle.test.ts @@ -39,7 +39,7 @@ function makeArgs(overrides: Partial = {}): CliArgs { openControllerSelect: false, openControllerDebug: false, openJimaku: false, - openAnimetosho: false, + openTsukihime: false, openYoutubePicker: false, openPlaylistBrowser: false, replayCurrentSubtitle: false, diff --git a/src/core/services/cli-command.test.ts b/src/core/services/cli-command.test.ts index df57ad01..52e9b97a 100644 --- a/src/core/services/cli-command.test.ts +++ b/src/core/services/cli-command.test.ts @@ -44,7 +44,7 @@ function makeArgs(overrides: Partial = {}): CliArgs { openControllerSelect: false, openControllerDebug: false, openJimaku: false, - openAnimetosho: false, + openTsukihime: false, openYoutubePicker: false, openPlaylistBrowser: false, togglePrimarySubtitleBar: false, diff --git a/src/core/services/cli-command.ts b/src/core/services/cli-command.ts index 60c72323..03d0790f 100644 --- a/src/core/services/cli-command.ts +++ b/src/core/services/cli-command.ts @@ -539,11 +539,11 @@ export function handleCliCommand( ); } else if (args.openJimaku) { dispatchCliSessionAction({ actionId: 'openJimaku' }, 'openJimaku', 'Open jimaku failed'); - } else if (args.openAnimetosho) { + } else if (args.openTsukihime) { dispatchCliSessionAction( - { actionId: 'openAnimetosho' }, - 'openAnimetosho', - 'Open animetosho failed', + { actionId: 'openTsukihime' }, + 'openTsukihime', + 'Open tsukihime failed', ); } else if (args.openYoutubePicker) { dispatchCliSessionAction( diff --git a/src/core/services/ipc-command.test.ts b/src/core/services/ipc-command.test.ts index 2041f345..14ab2662 100644 --- a/src/core/services/ipc-command.test.ts +++ b/src/core/services/ipc-command.test.ts @@ -12,7 +12,7 @@ function createOptions(overrides: Partial { calls.push('jimaku'); }, - openAnimetosho: () => { - calls.push('animetosho'); + openTsukihime: () => { + calls.push('tsukihime'); }, openYoutubeTrackPicker: () => { calls.push('youtube-picker'); diff --git a/src/core/services/ipc-command.ts b/src/core/services/ipc-command.ts index 6716bd6d..fa84094d 100644 --- a/src/core/services/ipc-command.ts +++ b/src/core/services/ipc-command.ts @@ -10,7 +10,7 @@ export interface HandleMpvCommandFromIpcOptions { SUBSYNC_TRIGGER: string; RUNTIME_OPTIONS_OPEN: string; JIMAKU_OPEN: string; - ANIMETOSHO_OPEN: string; + TSUKIHIME_OPEN: string; RUNTIME_OPTION_CYCLE_PREFIX: string; REPLAY_SUBTITLE: string; PLAY_NEXT_SUBTITLE: string; @@ -20,7 +20,7 @@ export interface HandleMpvCommandFromIpcOptions { triggerSubsyncFromConfig: () => void; openRuntimeOptionsPalette: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; openYoutubeTrackPicker: () => void | Promise; openPlaylistBrowser: () => void | Promise; runtimeOptionsCycle: (id: RuntimeOptionId, direction: 1 | -1) => RuntimeOptionApplyResult; @@ -114,8 +114,8 @@ export function handleMpvCommandFromIpc( return; } - if (first === options.specialCommands.ANIMETOSHO_OPEN) { - options.openAnimetosho(); + if (first === options.specialCommands.TSUKIHIME_OPEN) { + options.openTsukihime(); return; } diff --git a/src/core/services/overlay-shortcut-handler.test.ts b/src/core/services/overlay-shortcut-handler.test.ts index c47daf85..f6fff56e 100644 --- a/src/core/services/overlay-shortcut-handler.test.ts +++ b/src/core/services/overlay-shortcut-handler.test.ts @@ -28,7 +28,7 @@ function makeShortcuts(overrides: Partial = {}): Configured openCharacterDictionaryManager: null, openRuntimeOptions: null, openJimaku: null, - openAnimetosho: null, + openTsukihime: null, openSessionHelp: null, openControllerSelect: null, openControllerDebug: null, @@ -55,8 +55,8 @@ function createDeps(overrides: Partial = {}) { openJimaku: () => { calls.push('openJimaku'); }, - openAnimetosho: () => { - calls.push('openAnimetosho'); + openTsukihime: () => { + calls.push('openTsukihime'); }, markAudioCard: async () => { calls.push('markAudioCard'); @@ -168,7 +168,7 @@ test('runOverlayShortcutLocalFallback dispatches matching single-step actions', openRuntimeOptions: () => handled.push('openRuntimeOptions'), openCharacterDictionaryManager: () => handled.push('openCharacterDictionaryManager'), openJimaku: () => handled.push('openJimaku'), - openAnimetosho: () => handled.push('openAnimetosho'), + openTsukihime: () => handled.push('openTsukihime'), markAudioCard: () => handled.push('markAudioCard'), copySubtitleMultiple: (timeoutMs) => handled.push(`copySubtitleMultiple:${timeoutMs}`), copySubtitle: () => handled.push('copySubtitle'), @@ -202,7 +202,7 @@ test('runOverlayShortcutLocalFallback leaves multi-step numeric shortcuts for re openRuntimeOptions: () => handled.push('openRuntimeOptions'), openCharacterDictionaryManager: () => handled.push('openCharacterDictionaryManager'), openJimaku: () => handled.push('openJimaku'), - openAnimetosho: () => handled.push('openAnimetosho'), + openTsukihime: () => handled.push('openTsukihime'), markAudioCard: () => handled.push('markAudioCard'), copySubtitleMultiple: (timeoutMs) => handled.push(`copySubtitleMultiple:${timeoutMs}`), copySubtitle: () => handled.push('copySubtitle'), @@ -223,7 +223,7 @@ test('runOverlayShortcutLocalFallback leaves multi-step numeric shortcuts for re openRuntimeOptions: () => handled.push('openRuntimeOptions'), openCharacterDictionaryManager: () => handled.push('openCharacterDictionaryManager'), openJimaku: () => handled.push('openJimaku'), - openAnimetosho: () => handled.push('openAnimetosho'), + openTsukihime: () => handled.push('openTsukihime'), markAudioCard: () => handled.push('markAudioCard'), copySubtitleMultiple: (timeoutMs) => handled.push(`copySubtitleMultiple:${timeoutMs}`), copySubtitle: () => handled.push('copySubtitle'), @@ -261,7 +261,7 @@ test('runOverlayShortcutLocalFallback passes allowWhenRegistered for secondary-s openRuntimeOptions: () => {}, openCharacterDictionaryManager: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, markAudioCard: () => {}, copySubtitleMultiple: () => {}, copySubtitle: () => {}, @@ -298,7 +298,7 @@ test('runOverlayShortcutLocalFallback allows registered-global jimaku shortcut', openRuntimeOptions: () => {}, openCharacterDictionaryManager: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, markAudioCard: () => {}, copySubtitleMultiple: () => {}, copySubtitle: () => {}, @@ -331,7 +331,7 @@ test('runOverlayShortcutLocalFallback returns false when no action matches', () openJimaku: () => { called = true; }, - openAnimetosho: () => { + openTsukihime: () => { called = true; }, markAudioCard: () => { @@ -416,7 +416,7 @@ test('registerOverlayShortcutsRuntime reports active shortcuts when configured', openCharacterDictionaryManager: () => {}, openRuntimeOptions: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, }), cancelPendingMultiCopy: () => {}, cancelPendingMineSentenceMultiple: () => {}, @@ -444,7 +444,7 @@ test('unregisterOverlayShortcutsRuntime clears pending shortcut work when active openCharacterDictionaryManager: () => {}, openRuntimeOptions: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, }), cancelPendingMultiCopy: () => { calls.push('cancel-multi-copy'); diff --git a/src/core/services/overlay-shortcut-handler.ts b/src/core/services/overlay-shortcut-handler.ts index 8dda3598..e1c0e0aa 100644 --- a/src/core/services/overlay-shortcut-handler.ts +++ b/src/core/services/overlay-shortcut-handler.ts @@ -8,7 +8,7 @@ export interface OverlayShortcutFallbackHandlers { openRuntimeOptions: () => void; openCharacterDictionaryManager: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; markAudioCard: () => void; copySubtitleMultiple: (timeoutMs: number) => void; copySubtitle: () => void; @@ -25,7 +25,7 @@ export interface OverlayShortcutRuntimeDeps { openRuntimeOptions: () => void; openCharacterDictionaryManager: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; markAudioCard: () => Promise; copySubtitleMultiple: (timeoutMs: number) => void; copySubtitle: () => void; @@ -105,8 +105,8 @@ export function createOverlayShortcutRuntimeHandlers(deps: OverlayShortcutRuntim openJimaku: () => { deps.openJimaku(); }, - openAnimetosho: () => { - deps.openAnimetosho(); + openTsukihime: () => { + deps.openTsukihime(); }, }; @@ -114,7 +114,7 @@ export function createOverlayShortcutRuntimeHandlers(deps: OverlayShortcutRuntim openRuntimeOptions: overlayHandlers.openRuntimeOptions, openCharacterDictionaryManager: overlayHandlers.openCharacterDictionaryManager, openJimaku: overlayHandlers.openJimaku, - openAnimetosho: overlayHandlers.openAnimetosho, + openTsukihime: overlayHandlers.openTsukihime, markAudioCard: overlayHandlers.markAudioCard, copySubtitleMultiple: overlayHandlers.copySubtitleMultiple, copySubtitle: overlayHandlers.copySubtitle, @@ -160,9 +160,9 @@ export function runOverlayShortcutLocalFallback( allowWhenRegistered: true, }, { - accelerator: shortcuts.openAnimetosho, + accelerator: shortcuts.openTsukihime, run: () => { - handlers.openAnimetosho(); + handlers.openTsukihime(); }, allowWhenRegistered: true, }, diff --git a/src/core/services/overlay-shortcut.test.ts b/src/core/services/overlay-shortcut.test.ts index d8c3ecb9..8daa1867 100644 --- a/src/core/services/overlay-shortcut.test.ts +++ b/src/core/services/overlay-shortcut.test.ts @@ -23,7 +23,7 @@ function createShortcuts(overrides: Partial = {}): Configur openCharacterDictionaryManager: null, openRuntimeOptions: null, openJimaku: null, - openAnimetosho: null, + openTsukihime: null, openSessionHelp: null, openControllerSelect: null, openControllerDebug: null, @@ -49,7 +49,7 @@ test('registerOverlayShortcuts reports active overlay shortcuts when configured' openCharacterDictionaryManager: () => {}, openRuntimeOptions: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, }), true, ); @@ -70,7 +70,7 @@ test('registerOverlayShortcuts stays inactive when overlay shortcuts are absent' openCharacterDictionaryManager: () => {}, openRuntimeOptions: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, }), false, ); @@ -93,7 +93,7 @@ test('syncOverlayShortcutsRuntime deactivates cleanly when shortcuts were active openCharacterDictionaryManager: () => {}, openRuntimeOptions: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, }), cancelPendingMultiCopy: () => { calls.push('cancel-multi-copy'); diff --git a/src/core/services/overlay-shortcut.ts b/src/core/services/overlay-shortcut.ts index e58ad2c9..e12af393 100644 --- a/src/core/services/overlay-shortcut.ts +++ b/src/core/services/overlay-shortcut.ts @@ -13,7 +13,7 @@ export interface OverlayShortcutHandlers { openCharacterDictionaryManager: () => void; openRuntimeOptions: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; } export interface OverlayShortcutLifecycleDeps { @@ -36,7 +36,7 @@ const OVERLAY_SHORTCUT_KEYS: Array = {}) { openControllerSelect: () => calls.push('controller-select'), openControllerDebug: () => calls.push('controller-debug'), openJimaku: () => calls.push('jimaku'), - openAnimetosho: () => calls.push('animetosho'), + openTsukihime: () => calls.push('tsukihime'), openYoutubeTrackPicker: () => { calls.push('youtube'); }, diff --git a/src/core/services/session-actions.ts b/src/core/services/session-actions.ts index 5407aa5f..9e22775b 100644 --- a/src/core/services/session-actions.ts +++ b/src/core/services/session-actions.ts @@ -24,7 +24,7 @@ export interface SessionActionExecutorDeps { openControllerSelect: () => void; openControllerDebug: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; openYoutubeTrackPicker: () => void | Promise; openPlaylistBrowser: () => boolean | void | Promise; replayCurrentSubtitle: () => void; @@ -116,8 +116,8 @@ export async function dispatchSessionAction( case 'openJimaku': deps.openJimaku(); return; - case 'openAnimetosho': - deps.openAnimetosho(); + case 'openTsukihime': + deps.openTsukihime(); return; case 'openYoutubePicker': await deps.openYoutubeTrackPicker(); diff --git a/src/core/services/session-bindings.test.ts b/src/core/services/session-bindings.test.ts index fe4e0399..9d3cda55 100644 --- a/src/core/services/session-bindings.test.ts +++ b/src/core/services/session-bindings.test.ts @@ -22,7 +22,7 @@ function createShortcuts(overrides: Partial = {}): Configur openCharacterDictionaryManager: null, openRuntimeOptions: null, openJimaku: null, - openAnimetosho: null, + openTsukihime: null, openSessionHelp: null, openControllerSelect: null, openControllerDebug: null, diff --git a/src/core/services/session-bindings.ts b/src/core/services/session-bindings.ts index 584d2ca9..dccd3b36 100644 --- a/src/core/services/session-bindings.ts +++ b/src/core/services/session-bindings.ts @@ -55,7 +55,7 @@ const SESSION_SHORTCUT_ACTIONS: Array<{ { key: 'openCharacterDictionaryManager', actionId: 'openCharacterDictionaryManager' }, { key: 'openRuntimeOptions', actionId: 'openRuntimeOptions' }, { key: 'openJimaku', actionId: 'openJimaku' }, - { key: 'openAnimetosho', actionId: 'openAnimetosho' }, + { key: 'openTsukihime', actionId: 'openTsukihime' }, { key: 'openSessionHelp', actionId: 'openSessionHelp' }, { key: 'openControllerSelect', actionId: 'openControllerSelect' }, { key: 'openControllerDebug', actionId: 'openControllerDebug' }, @@ -305,9 +305,9 @@ function resolveCommandBinding( if (command.length !== 1) return null; return { actionType: 'session-action', actionId: 'openJimaku' }; } - if (first === SPECIAL_COMMANDS.ANIMETOSHO_OPEN) { + if (first === SPECIAL_COMMANDS.TSUKIHIME_OPEN) { if (command.length !== 1) return null; - return { actionType: 'session-action', actionId: 'openAnimetosho' }; + return { actionType: 'session-action', actionId: 'openTsukihime' }; } if (first === SPECIAL_COMMANDS.YOUTUBE_PICKER_OPEN) { if (command.length !== 1) return null; diff --git a/src/core/services/startup-bootstrap.test.ts b/src/core/services/startup-bootstrap.test.ts index 0698165f..a07f2f98 100644 --- a/src/core/services/startup-bootstrap.test.ts +++ b/src/core/services/startup-bootstrap.test.ts @@ -39,7 +39,7 @@ function makeArgs(overrides: Partial = {}): CliArgs { openControllerSelect: false, openControllerDebug: false, openJimaku: false, - openAnimetosho: false, + openTsukihime: false, openYoutubePicker: false, openPlaylistBrowser: false, replayCurrentSubtitle: false, diff --git a/src/core/utils/shortcut-config.ts b/src/core/utils/shortcut-config.ts index 7c07ec19..b45deeb3 100644 --- a/src/core/utils/shortcut-config.ts +++ b/src/core/utils/shortcut-config.ts @@ -15,7 +15,7 @@ export interface ConfiguredShortcuts { openCharacterDictionaryManager: string | null | undefined; openRuntimeOptions: string | null | undefined; openJimaku: string | null | undefined; - openAnimetosho: string | null | undefined; + openTsukihime: string | null | undefined; openSessionHelp: string | null | undefined; openControllerSelect: string | null | undefined; openControllerDebug: string | null | undefined; @@ -66,7 +66,7 @@ export function resolveConfiguredShortcuts( ), openRuntimeOptions: normalizeShortcut(shortcutValue('openRuntimeOptions')), openJimaku: normalizeShortcut(shortcutValue('openJimaku')), - openAnimetosho: normalizeShortcut(shortcutValue('openAnimetosho')), + openTsukihime: normalizeShortcut(shortcutValue('openTsukihime')), openSessionHelp: normalizeShortcut(shortcutValue('openSessionHelp')), openControllerSelect: normalizeShortcut(shortcutValue('openControllerSelect')), openControllerDebug: normalizeShortcut(shortcutValue('openControllerDebug')), diff --git a/src/main.ts b/src/main.ts index 8f8b8173..35de3e21 100644 --- a/src/main.ts +++ b/src/main.ts @@ -467,7 +467,7 @@ import { createOverlayModalInputState } from './main/runtime/overlay-modal-input import { openYoutubeTrackPicker } from './main/runtime/youtube-picker-open'; import { openRuntimeOptionsModal as openRuntimeOptionsModalRuntime } from './main/runtime/runtime-options-open'; import { openJimakuModal as openJimakuModalRuntime } from './main/runtime/jimaku-open'; -import { openAnimetoshoModal as openAnimetoshoModalRuntime } from './main/runtime/animetosho-open'; +import { openTsukihimeModal as openTsukihimeModalRuntime } from './main/runtime/tsukihime-open'; import { openSubsyncManualModal as openSubsyncManualModalRuntime } from './main/runtime/subsync-open'; import { openSessionHelpModal as openSessionHelpModalRuntime } from './main/runtime/session-help-open'; import { openCharacterDictionaryManagerModal as openCharacterDictionaryManagerModalRuntime } from './main/runtime/character-dictionary-open'; @@ -2061,8 +2061,8 @@ const overlayShortcutsRuntime = createOverlayShortcutsRuntimeService( openJimaku: () => { openJimakuOverlay(); }, - openAnimetosho: () => { - openAnimetoshoOverlay(); + openTsukihime: () => { + openTsukihimeOverlay(); }, markAudioCard: () => markLastCardAsAudioCard(), copySubtitleMultiple: (timeoutMs: number) => { @@ -2925,9 +2925,9 @@ function openJimakuOverlay(): void { ); } -function openAnimetoshoOverlay(): void { +function openTsukihimeOverlay(): void { openOverlayHostedModalWithOsd( - openAnimetoshoModalRuntime, + openTsukihimeModalRuntime, 'TsukiHime overlay unavailable.', 'Failed to open TsukiHime overlay.', ); @@ -5448,7 +5448,7 @@ async function dispatchSessionAction(request: SessionActionDispatchRequest): Pro }, openRuntimeOptionsPalette: () => openRuntimeOptionsPalette(), openJimaku: () => openJimakuOverlay(), - openAnimetosho: () => openAnimetoshoOverlay(), + openTsukihime: () => openTsukihimeOverlay(), openSessionHelp: () => openSessionHelpOverlay(), openCharacterDictionaryManager: () => openCharacterDictionaryManagerOverlay(), openControllerSelect: () => openControllerSelectOverlay(), @@ -5482,7 +5482,7 @@ const { registerIpcRuntimeHandlers } = composeIpcRuntimeHandlers({ triggerSubsyncFromConfig: () => triggerSubsyncFromConfig(), openRuntimeOptionsPalette: () => openRuntimeOptionsPalette(), openJimaku: () => openJimakuOverlay(), - openAnimetosho: () => openAnimetoshoOverlay(), + openTsukihime: () => openTsukihimeOverlay(), openYoutubeTrackPicker: () => openYoutubeTrackPickerFromPlayback(), openPlaylistBrowser: () => openPlaylistBrowser(), cycleRuntimeOption: (id, direction) => { diff --git a/src/main/dependencies.ts b/src/main/dependencies.ts index 0559774a..93c90431 100644 --- a/src/main/dependencies.ts +++ b/src/main/dependencies.ts @@ -228,7 +228,7 @@ export interface MpvCommandRuntimeServiceDepsParams { triggerSubsyncFromConfig: HandleMpvCommandFromIpcOptions['triggerSubsyncFromConfig']; openRuntimeOptionsPalette: HandleMpvCommandFromIpcOptions['openRuntimeOptionsPalette']; openJimaku: HandleMpvCommandFromIpcOptions['openJimaku']; - openAnimetosho: HandleMpvCommandFromIpcOptions['openAnimetosho']; + openTsukihime: HandleMpvCommandFromIpcOptions['openTsukihime']; openYoutubeTrackPicker: HandleMpvCommandFromIpcOptions['openYoutubeTrackPicker']; openPlaylistBrowser: HandleMpvCommandFromIpcOptions['openPlaylistBrowser']; showMpvOsd: HandleMpvCommandFromIpcOptions['showMpvOsd']; @@ -435,7 +435,7 @@ export function createMpvCommandRuntimeServiceDeps( triggerSubsyncFromConfig: params.triggerSubsyncFromConfig, openRuntimeOptionsPalette: params.openRuntimeOptionsPalette, openJimaku: params.openJimaku, - openAnimetosho: params.openAnimetosho, + openTsukihime: params.openTsukihime, openYoutubeTrackPicker: params.openYoutubeTrackPicker, openPlaylistBrowser: params.openPlaylistBrowser, runtimeOptionsCycle: params.runtimeOptionsCycle, diff --git a/src/main/ipc-mpv-command.ts b/src/main/ipc-mpv-command.ts index c60390d1..abae5df3 100644 --- a/src/main/ipc-mpv-command.ts +++ b/src/main/ipc-mpv-command.ts @@ -13,7 +13,7 @@ export interface MpvCommandFromIpcRuntimeDeps { triggerSubsyncFromConfig: () => void; openRuntimeOptionsPalette: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; openYoutubeTrackPicker: () => void | Promise; openPlaylistBrowser: () => void | Promise; cycleRuntimeOption: (id: RuntimeOptionId, direction: 1 | -1) => RuntimeOptionApplyResult; @@ -39,7 +39,7 @@ export function handleMpvCommandFromIpcRuntime( triggerSubsyncFromConfig: deps.triggerSubsyncFromConfig, openRuntimeOptionsPalette: deps.openRuntimeOptionsPalette, openJimaku: deps.openJimaku, - openAnimetosho: deps.openAnimetosho, + openTsukihime: deps.openTsukihime, openYoutubeTrackPicker: deps.openYoutubeTrackPicker, openPlaylistBrowser: deps.openPlaylistBrowser, runtimeOptionsCycle: deps.cycleRuntimeOption, diff --git a/src/main/overlay-runtime.ts b/src/main/overlay-runtime.ts index 5bafc606..d35c98e6 100644 --- a/src/main/overlay-runtime.ts +++ b/src/main/overlay-runtime.ts @@ -49,7 +49,7 @@ export interface OverlayModalRuntime { ) => boolean; openRuntimeOptionsPalette: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; handleOverlayModalClosed: (modal: OverlayHostedModal) => void; notifyOverlayModalOpened: (modal: OverlayHostedModal) => void; waitForModalOpen: (modal: OverlayHostedModal, timeoutMs: number) => Promise; @@ -433,9 +433,9 @@ export function createOverlayModalRuntimeService( }); }; - const openAnimetosho = (): void => { - sendToActiveOverlayWindow('animetosho:open', undefined, { - restoreOnModalClose: 'animetosho', + const openTsukihime = (): void => { + sendToActiveOverlayWindow('tsukihime:open', undefined, { + restoreOnModalClose: 'tsukihime', }); }; @@ -518,7 +518,7 @@ export function createOverlayModalRuntimeService( sendToActiveOverlayWindow, openRuntimeOptionsPalette, openJimaku, - openAnimetosho, + openTsukihime, handleOverlayModalClosed, notifyOverlayModalOpened, waitForModalOpen, diff --git a/src/main/overlay-shortcuts-runtime.ts b/src/main/overlay-shortcuts-runtime.ts index e52643f4..4fcaf2ad 100644 --- a/src/main/overlay-shortcuts-runtime.ts +++ b/src/main/overlay-shortcuts-runtime.ts @@ -21,7 +21,7 @@ export interface OverlayShortcutRuntimeServiceInput { openRuntimeOptionsPalette: () => void; openCharacterDictionaryManager: () => void; openJimaku: () => void; - openAnimetosho: () => void; + openTsukihime: () => void; markAudioCard: () => Promise; copySubtitleMultiple: (timeoutMs: number) => void; copySubtitle: () => void; @@ -57,8 +57,8 @@ export function createOverlayShortcutsRuntimeService( openJimaku: () => { input.openJimaku(); }, - openAnimetosho: () => { - input.openAnimetosho(); + openTsukihime: () => { + input.openTsukihime(); }, markAudioCard: () => { return input.markAudioCard(); diff --git a/src/main/runtime/composers/ipc-runtime-composer.test.ts b/src/main/runtime/composers/ipc-runtime-composer.test.ts index bd49e0e6..8a20a477 100644 --- a/src/main/runtime/composers/ipc-runtime-composer.test.ts +++ b/src/main/runtime/composers/ipc-runtime-composer.test.ts @@ -11,7 +11,7 @@ test('composeIpcRuntimeHandlers returns callable IPC handlers and registration b triggerSubsyncFromConfig: async () => {}, openRuntimeOptionsPalette: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, openYoutubeTrackPicker: () => {}, openPlaylistBrowser: () => {}, cycleRuntimeOption: () => ({ ok: true }), diff --git a/src/main/runtime/first-run-setup-service.test.ts b/src/main/runtime/first-run-setup-service.test.ts index a59cac59..fcd3fe9e 100644 --- a/src/main/runtime/first-run-setup-service.test.ts +++ b/src/main/runtime/first-run-setup-service.test.ts @@ -54,7 +54,7 @@ function makeArgs(overrides: Partial = {}): CliArgs { openControllerSelect: false, openControllerDebug: false, openJimaku: false, - openAnimetosho: false, + openTsukihime: false, openYoutubePicker: false, openPlaylistBrowser: false, replayCurrentSubtitle: false, diff --git a/src/main/runtime/first-run-setup-service.ts b/src/main/runtime/first-run-setup-service.ts index 299f77f7..8a9f1241 100644 --- a/src/main/runtime/first-run-setup-service.ts +++ b/src/main/runtime/first-run-setup-service.ts @@ -97,7 +97,7 @@ function hasAnyStartupCommandBeyondSetup(args: CliArgs): boolean { args.openControllerSelect || args.openControllerDebug || args.openJimaku || - args.openAnimetosho || + args.openTsukihime || args.openYoutubePicker || args.openPlaylistBrowser || args.replayCurrentSubtitle || diff --git a/src/main/runtime/global-shortcuts-runtime-handlers.test.ts b/src/main/runtime/global-shortcuts-runtime-handlers.test.ts index c4fa6579..76431508 100644 --- a/src/main/runtime/global-shortcuts-runtime-handlers.test.ts +++ b/src/main/runtime/global-shortcuts-runtime-handlers.test.ts @@ -19,7 +19,7 @@ function createShortcuts(): ConfiguredShortcuts { openCharacterDictionaryManager: null, openRuntimeOptions: null, openJimaku: null, - openAnimetosho: null, + openTsukihime: null, openSessionHelp: null, openControllerSelect: null, openControllerDebug: null, diff --git a/src/main/runtime/global-shortcuts.test.ts b/src/main/runtime/global-shortcuts.test.ts index 5a33377b..f144ef22 100644 --- a/src/main/runtime/global-shortcuts.test.ts +++ b/src/main/runtime/global-shortcuts.test.ts @@ -23,7 +23,7 @@ function createShortcuts(): ConfiguredShortcuts { openCharacterDictionaryManager: null, openRuntimeOptions: null, openJimaku: null, - openAnimetosho: null, + openTsukihime: null, openSessionHelp: null, openControllerSelect: null, openControllerDebug: null, diff --git a/src/main/runtime/ipc-bridge-actions-main-deps.test.ts b/src/main/runtime/ipc-bridge-actions-main-deps.test.ts index 4bffd1f7..a4ba896a 100644 --- a/src/main/runtime/ipc-bridge-actions-main-deps.test.ts +++ b/src/main/runtime/ipc-bridge-actions-main-deps.test.ts @@ -14,7 +14,7 @@ test('ipc bridge action main deps builders map callbacks', async () => { triggerSubsyncFromConfig: async () => {}, openRuntimeOptionsPalette: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, openYoutubeTrackPicker: () => {}, openPlaylistBrowser: () => {}, cycleRuntimeOption: () => ({ ok: false as const, error: 'x' }), diff --git a/src/main/runtime/ipc-bridge-actions.test.ts b/src/main/runtime/ipc-bridge-actions.test.ts index 6e1bf974..2579a205 100644 --- a/src/main/runtime/ipc-bridge-actions.test.ts +++ b/src/main/runtime/ipc-bridge-actions.test.ts @@ -11,7 +11,7 @@ test('handle mpv command handler forwards command and built deps', () => { triggerSubsyncFromConfig: () => {}, openRuntimeOptionsPalette: () => {}, openJimaku: () => {}, - openAnimetosho: () => {}, + openTsukihime: () => {}, openYoutubeTrackPicker: () => {}, openPlaylistBrowser: () => {}, cycleRuntimeOption: () => ({ ok: false as const, error: 'x' }), diff --git a/src/main/runtime/ipc-mpv-command-main-deps.test.ts b/src/main/runtime/ipc-mpv-command-main-deps.test.ts index ee7cc009..013f886c 100644 --- a/src/main/runtime/ipc-mpv-command-main-deps.test.ts +++ b/src/main/runtime/ipc-mpv-command-main-deps.test.ts @@ -8,7 +8,7 @@ test('ipc mpv command main deps builder maps callbacks', () => { triggerSubsyncFromConfig: () => calls.push('subsync'), openRuntimeOptionsPalette: () => calls.push('palette'), openJimaku: () => calls.push('jimaku'), - openAnimetosho: () => calls.push('animetosho'), + openTsukihime: () => calls.push('tsukihime'), openYoutubeTrackPicker: () => { calls.push('youtube-picker'); }, @@ -30,7 +30,7 @@ test('ipc mpv command main deps builder maps callbacks', () => { deps.triggerSubsyncFromConfig(); deps.openRuntimeOptionsPalette(); deps.openJimaku(); - deps.openAnimetosho(); + deps.openTsukihime(); void deps.openYoutubeTrackPicker(); void deps.openPlaylistBrowser(); assert.deepEqual(deps.cycleRuntimeOption('anki.nPlusOneMatchMode', 1), { ok: false, error: 'x' }); @@ -47,7 +47,7 @@ test('ipc mpv command main deps builder maps callbacks', () => { 'subsync', 'palette', 'jimaku', - 'animetosho', + 'tsukihime', 'youtube-picker', 'playlist-browser', 'osd:hello', diff --git a/src/main/runtime/ipc-mpv-command-main-deps.ts b/src/main/runtime/ipc-mpv-command-main-deps.ts index 4dae4876..189e0b5b 100644 --- a/src/main/runtime/ipc-mpv-command-main-deps.ts +++ b/src/main/runtime/ipc-mpv-command-main-deps.ts @@ -10,7 +10,7 @@ export function createBuildMpvCommandFromIpcRuntimeMainDepsHandler( triggerSubsyncFromConfig: () => deps.triggerSubsyncFromConfig(), openRuntimeOptionsPalette: () => deps.openRuntimeOptionsPalette(), openJimaku: () => deps.openJimaku(), - openAnimetosho: () => deps.openAnimetosho(), + openTsukihime: () => deps.openTsukihime(), openYoutubeTrackPicker: () => deps.openYoutubeTrackPicker(), openPlaylistBrowser: () => deps.openPlaylistBrowser(), cycleRuntimeOption: (id, direction) => deps.cycleRuntimeOption(id, direction), diff --git a/src/main/runtime/overlay-shortcuts-runtime-main-deps.test.ts b/src/main/runtime/overlay-shortcuts-runtime-main-deps.test.ts index f574ea62..a1ad1e53 100644 --- a/src/main/runtime/overlay-shortcuts-runtime-main-deps.test.ts +++ b/src/main/runtime/overlay-shortcuts-runtime-main-deps.test.ts @@ -18,7 +18,7 @@ test('overlay shortcuts runtime main deps builder maps lifecycle and action call openRuntimeOptionsPalette: () => calls.push('runtime-options'), openCharacterDictionaryManager: () => calls.push('character-dictionary-manager'), openJimaku: () => calls.push('jimaku'), - openAnimetosho: () => calls.push('animetosho'), + openTsukihime: () => calls.push('tsukihime'), markAudioCard: async () => { calls.push('mark-audio'); }, diff --git a/src/main/runtime/overlay-shortcuts-runtime-main-deps.ts b/src/main/runtime/overlay-shortcuts-runtime-main-deps.ts index 81de3e21..238cffe0 100644 --- a/src/main/runtime/overlay-shortcuts-runtime-main-deps.ts +++ b/src/main/runtime/overlay-shortcuts-runtime-main-deps.ts @@ -13,7 +13,7 @@ export function createBuildOverlayShortcutsRuntimeMainDepsHandler( openRuntimeOptionsPalette: () => deps.openRuntimeOptionsPalette(), openCharacterDictionaryManager: () => deps.openCharacterDictionaryManager(), openJimaku: () => deps.openJimaku(), - openAnimetosho: () => deps.openAnimetosho(), + openTsukihime: () => deps.openTsukihime(), markAudioCard: () => deps.markAudioCard(), copySubtitleMultiple: (timeoutMs: number) => deps.copySubtitleMultiple(timeoutMs), copySubtitle: () => deps.copySubtitle(), diff --git a/src/main/runtime/animetosho-open.ts b/src/main/runtime/tsukihime-open.ts similarity index 74% rename from src/main/runtime/animetosho-open.ts rename to src/main/runtime/tsukihime-open.ts index 0a498ca8..f9fc04fa 100644 --- a/src/main/runtime/animetosho-open.ts +++ b/src/main/runtime/tsukihime-open.ts @@ -2,10 +2,10 @@ import type { OverlayHostedModal } from '../../shared/ipc/contracts'; import { IPC_CHANNELS } from '../../shared/ipc/contracts'; import { openOverlayHostedModal, retryOverlayModalOpen } from './overlay-hosted-modal-open'; -const ANIMETOSHO_MODAL: OverlayHostedModal = 'animetosho'; -const ANIMETOSHO_OPEN_TIMEOUT_MS = 1500; +const TSUKIHIME_MODAL: OverlayHostedModal = 'tsukihime'; +const TSUKIHIME_OPEN_TIMEOUT_MS = 1500; -export async function openAnimetoshoModal(deps: { +export async function openTsukihimeModal(deps: { ensureOverlayStartupPrereqs: () => void; ensureOverlayWindowsReadyForVisibilityActions: () => void; sendToActiveOverlayWindow: ( @@ -25,10 +25,10 @@ export async function openAnimetoshoModal(deps: { logWarn: deps.logWarn, }, { - modal: ANIMETOSHO_MODAL, - timeoutMs: ANIMETOSHO_OPEN_TIMEOUT_MS, + modal: TSUKIHIME_MODAL, + timeoutMs: TSUKIHIME_OPEN_TIMEOUT_MS, retryWarning: - 'Animetosho modal did not acknowledge modal open on first attempt; retrying dedicated modal window.', + 'Tsukihime modal did not acknowledge modal open on first attempt; retrying dedicated modal window.', sendOpen: () => openOverlayHostedModal( { @@ -38,8 +38,8 @@ export async function openAnimetoshoModal(deps: { sendToActiveOverlayWindow: deps.sendToActiveOverlayWindow, }, { - channel: IPC_CHANNELS.event.animetoshoOpen, - modal: ANIMETOSHO_MODAL, + channel: IPC_CHANNELS.event.tsukihimeOpen, + modal: TSUKIHIME_MODAL, preferModalWindow: true, }, ), diff --git a/src/preload.ts b/src/preload.ts index 925dfe0f..b64819b6 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -34,13 +34,13 @@ import type { JimakuFileEntry, JimakuApiResponse, JimakuDownloadResult, - AnimetoshoSearchQuery, - AnimetoshoFilesQuery, - AnimetoshoDownloadQuery, - AnimetoshoEntry, - AnimetoshoSubtitleFile, - AnimetoshoApiResponse, - AnimetoshoDownloadResult, + TsukihimeSearchQuery, + TsukihimeFilesQuery, + TsukihimeDownloadQuery, + TsukihimeEntry, + TsukihimeSubtitleFile, + TsukihimeApiResponse, + TsukihimeDownloadResult, SubsyncManualPayload, SubsyncManualRunRequest, SubsyncResult, @@ -174,7 +174,7 @@ const onOpenControllerSelectEvent = createQueuedIpcListener( ); const onOpenControllerDebugEvent = createQueuedIpcListener(IPC_CHANNELS.event.controllerDebugOpen); const onOpenJimakuEvent = createQueuedIpcListener(IPC_CHANNELS.event.jimakuOpen); -const onOpenAnimetoshoEvent = createQueuedIpcListener(IPC_CHANNELS.event.animetoshoOpen); +const onOpenTsukihimeEvent = createQueuedIpcListener(IPC_CHANNELS.event.tsukihimeOpen); const onOpenYoutubeTrackPickerEvent = createQueuedIpcListenerWithPayload( IPC_CHANNELS.event.youtubePickerOpen, (payload) => payload as YoutubePickerOpenPayload, @@ -358,18 +358,18 @@ const electronAPI: ElectronAPI = { jimakuDownloadFile: (query: JimakuDownloadQuery): Promise => ipcRenderer.invoke(IPC_CHANNELS.request.jimakuDownloadFile, query), - animetoshoSearchEntries: ( - query: AnimetoshoSearchQuery, - ): Promise> => - ipcRenderer.invoke(IPC_CHANNELS.request.animetoshoSearchEntries, query), - animetoshoListFiles: ( - query: AnimetoshoFilesQuery, - ): Promise> => - ipcRenderer.invoke(IPC_CHANNELS.request.animetoshoListFiles, query), - animetoshoDownloadFile: (query: AnimetoshoDownloadQuery): Promise => - ipcRenderer.invoke(IPC_CHANNELS.request.animetoshoDownloadFile, query), - animetoshoGetSecondaryLanguages: (): Promise => - ipcRenderer.invoke(IPC_CHANNELS.request.animetoshoGetSecondaryLanguages), + tsukihimeSearchEntries: ( + query: TsukihimeSearchQuery, + ): Promise> => + ipcRenderer.invoke(IPC_CHANNELS.request.tsukihimeSearchEntries, query), + tsukihimeListFiles: ( + query: TsukihimeFilesQuery, + ): Promise> => + ipcRenderer.invoke(IPC_CHANNELS.request.tsukihimeListFiles, query), + tsukihimeDownloadFile: (query: TsukihimeDownloadQuery): Promise => + ipcRenderer.invoke(IPC_CHANNELS.request.tsukihimeDownloadFile, query), + tsukihimeGetSecondaryLanguages: (): Promise => + ipcRenderer.invoke(IPC_CHANNELS.request.tsukihimeGetSecondaryLanguages), quitApp: () => { ipcRenderer.send(IPC_CHANNELS.command.quitApp); @@ -450,7 +450,7 @@ const electronAPI: ElectronAPI = { onOpenControllerSelect: onOpenControllerSelectEvent, onOpenControllerDebug: onOpenControllerDebugEvent, onOpenJimaku: onOpenJimakuEvent, - onOpenAnimetosho: onOpenAnimetoshoEvent, + onOpenTsukihime: onOpenTsukihimeEvent, onOpenYoutubeTrackPicker: onOpenYoutubeTrackPickerEvent, onOpenPlaylistBrowser: onOpenPlaylistBrowserEvent, onOpenCharacterDictionaryManager: onOpenCharacterDictionaryManagerEvent, diff --git a/src/renderer/handlers/keyboard.test.ts b/src/renderer/handlers/keyboard.test.ts index b173ac55..8c3b532f 100644 --- a/src/renderer/handlers/keyboard.test.ts +++ b/src/renderer/handlers/keyboard.test.ts @@ -90,7 +90,7 @@ function createEmptyShortcuts(): ConfiguredShortcuts { openCharacterDictionaryManager: null, openRuntimeOptions: null, openJimaku: null, - openAnimetosho: null, + openTsukihime: null, openSessionHelp: null, openControllerSelect: null, openControllerDebug: null, @@ -492,7 +492,7 @@ function createKeyboardHandlerHarness() { handleSubsyncKeydown: () => false, handleKikuKeydown: () => false, handleJimakuKeydown: () => false, - handleAnimetoshoKeydown: () => false, + handleTsukihimeKeydown: () => false, handleControllerSelectKeydown: () => { controllerSelectKeydownCount += 1; return true; diff --git a/src/renderer/handlers/keyboard.ts b/src/renderer/handlers/keyboard.ts index 5bc50156..6dc7f0f7 100644 --- a/src/renderer/handlers/keyboard.ts +++ b/src/renderer/handlers/keyboard.ts @@ -16,7 +16,7 @@ export function createKeyboardHandlers( handleSubsyncKeydown: (e: KeyboardEvent) => boolean; handleKikuKeydown: (e: KeyboardEvent) => boolean; handleJimakuKeydown: (e: KeyboardEvent) => boolean; - handleAnimetoshoKeydown: (e: KeyboardEvent) => boolean; + handleTsukihimeKeydown: (e: KeyboardEvent) => boolean; handleYoutubePickerKeydown: (e: KeyboardEvent) => boolean; handlePlaylistBrowserKeydown: (e: KeyboardEvent) => boolean; handleControllerSelectKeydown: (e: KeyboardEvent) => boolean; @@ -1120,8 +1120,8 @@ export function createKeyboardHandlers( options.handleJimakuKeydown(e); return; } - if (ctx.state.animetoshoModalOpen) { - options.handleAnimetoshoKeydown(e); + if (ctx.state.tsukihimeModalOpen) { + options.handleTsukihimeKeydown(e); return; } if (ctx.state.youtubePickerModalOpen) { diff --git a/src/renderer/index.html b/src/renderer/index.html index 6961d96d..d4e295f6 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -116,40 +116,40 @@ -