mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-01 18:22:41 -08:00
docs: document Kiku/Lapis integration in config and anki pages
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { hasExplicitCommand, parseArgs, shouldStartApp } from './args';
|
||||
import { hasExplicitCommand, parseArgs, shouldRunSettingsOnlyStartup, shouldStartApp } from './args';
|
||||
|
||||
test('parseArgs parses booleans and value flags', () => {
|
||||
const args = parseArgs([
|
||||
@@ -60,6 +60,28 @@ test('hasExplicitCommand and shouldStartApp preserve command intent', () => {
|
||||
assert.equal(hasExplicitCommand(refreshKnownWords), true);
|
||||
assert.equal(shouldStartApp(refreshKnownWords), false);
|
||||
|
||||
const settings = parseArgs(['--settings']);
|
||||
assert.equal(settings.settings, true);
|
||||
assert.equal(hasExplicitCommand(settings), true);
|
||||
assert.equal(shouldStartApp(settings), true);
|
||||
assert.equal(shouldRunSettingsOnlyStartup(settings), true);
|
||||
|
||||
const settingsWithOverlay = parseArgs(['--settings', '--toggle-visible-overlay']);
|
||||
assert.equal(settingsWithOverlay.settings, true);
|
||||
assert.equal(settingsWithOverlay.toggleVisibleOverlay, true);
|
||||
assert.equal(shouldRunSettingsOnlyStartup(settingsWithOverlay), false);
|
||||
|
||||
const yomitanAlias = parseArgs(['--yomitan']);
|
||||
assert.equal(yomitanAlias.settings, true);
|
||||
assert.equal(hasExplicitCommand(yomitanAlias), true);
|
||||
assert.equal(shouldStartApp(yomitanAlias), true);
|
||||
|
||||
const help = parseArgs(['--help']);
|
||||
assert.equal(help.help, true);
|
||||
assert.equal(hasExplicitCommand(help), true);
|
||||
assert.equal(shouldStartApp(help), false);
|
||||
assert.equal(shouldRunSettingsOnlyStartup(help), false);
|
||||
|
||||
const anilistStatus = parseArgs(['--anilist-status']);
|
||||
assert.equal(anilistStatus.anilistStatus, true);
|
||||
assert.equal(hasExplicitCommand(anilistStatus), true);
|
||||
|
||||
@@ -295,6 +295,7 @@ export function shouldStartApp(args: CliArgs): boolean {
|
||||
args.start ||
|
||||
args.toggle ||
|
||||
args.toggleVisibleOverlay ||
|
||||
args.settings ||
|
||||
args.copySubtitle ||
|
||||
args.copySubtitleMultiple ||
|
||||
args.mineSentence ||
|
||||
@@ -314,6 +315,50 @@ export function shouldStartApp(args: CliArgs): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function shouldRunSettingsOnlyStartup(args: CliArgs): boolean {
|
||||
return (
|
||||
args.settings &&
|
||||
!args.background &&
|
||||
!args.start &&
|
||||
!args.stop &&
|
||||
!args.toggle &&
|
||||
!args.toggleVisibleOverlay &&
|
||||
!args.show &&
|
||||
!args.hide &&
|
||||
!args.showVisibleOverlay &&
|
||||
!args.hideVisibleOverlay &&
|
||||
!args.copySubtitle &&
|
||||
!args.copySubtitleMultiple &&
|
||||
!args.mineSentence &&
|
||||
!args.mineSentenceMultiple &&
|
||||
!args.updateLastCardFromClipboard &&
|
||||
!args.refreshKnownWords &&
|
||||
!args.toggleSecondarySub &&
|
||||
!args.triggerFieldGrouping &&
|
||||
!args.triggerSubsync &&
|
||||
!args.markAudioCard &&
|
||||
!args.openRuntimeOptions &&
|
||||
!args.anilistStatus &&
|
||||
!args.anilistLogout &&
|
||||
!args.anilistSetup &&
|
||||
!args.anilistRetryQueue &&
|
||||
!args.jellyfin &&
|
||||
!args.jellyfinLogin &&
|
||||
!args.jellyfinLogout &&
|
||||
!args.jellyfinLibraries &&
|
||||
!args.jellyfinItems &&
|
||||
!args.jellyfinSubtitles &&
|
||||
!args.jellyfinPlay &&
|
||||
!args.jellyfinRemoteAnnounce &&
|
||||
!args.texthooker &&
|
||||
!args.help &&
|
||||
!args.autoStartOverlay &&
|
||||
!args.generateConfig &&
|
||||
!args.backupOverwrite &&
|
||||
!args.debug
|
||||
);
|
||||
}
|
||||
|
||||
export function commandNeedsOverlayRuntime(args: CliArgs): boolean {
|
||||
return (
|
||||
args.toggle ||
|
||||
|
||||
@@ -66,6 +66,55 @@ test('runAppReadyRuntime starts websocket in auto mode when plugin missing', asy
|
||||
);
|
||||
});
|
||||
|
||||
test('runAppReadyRuntime skips heavy startup when shouldSkipHeavyStartup returns true', async () => {
|
||||
const { deps, calls } = makeDeps({
|
||||
shouldSkipHeavyStartup: () => true,
|
||||
reloadConfig: () => calls.push('reloadConfig'),
|
||||
getResolvedConfig: () => {
|
||||
calls.push('getResolvedConfig');
|
||||
return {
|
||||
websocket: { enabled: 'auto' },
|
||||
secondarySub: {},
|
||||
};
|
||||
},
|
||||
getConfigWarnings: () => {
|
||||
calls.push('getConfigWarnings');
|
||||
return [];
|
||||
},
|
||||
setLogLevel: (level, source) => calls.push(`setLogLevel:${level}:${source}`),
|
||||
initRuntimeOptionsManager: () => calls.push('initRuntimeOptionsManager'),
|
||||
startBackgroundWarmups: () => calls.push('startBackgroundWarmups'),
|
||||
loadSubtitlePosition: () => calls.push('loadSubtitlePosition'),
|
||||
resolveKeybindings: () => calls.push('resolveKeybindings'),
|
||||
createMpvClient: () => calls.push('createMpvClient'),
|
||||
logConfigWarning: () => calls.push('logConfigWarning'),
|
||||
startJellyfinRemoteSession: async () => {
|
||||
calls.push('startJellyfinRemoteSession');
|
||||
},
|
||||
createImmersionTracker: () => calls.push('createImmersionTracker'),
|
||||
handleInitialArgs: () => calls.push('handleInitialArgs'),
|
||||
});
|
||||
|
||||
await runAppReadyRuntime(deps);
|
||||
|
||||
assert.equal(calls.includes('reloadConfig'), false);
|
||||
assert.equal(calls.includes('getResolvedConfig'), false);
|
||||
assert.equal(calls.includes('getConfigWarnings'), false);
|
||||
assert.equal(calls.includes('setLogLevel:warn:config'), false);
|
||||
assert.equal(calls.includes('startBackgroundWarmups'), false);
|
||||
assert.equal(calls.includes('loadSubtitlePosition'), false);
|
||||
assert.equal(calls.includes('resolveKeybindings'), false);
|
||||
assert.equal(calls.includes('createMpvClient'), false);
|
||||
assert.equal(calls.includes('initRuntimeOptionsManager'), false);
|
||||
assert.equal(calls.includes('createImmersionTracker'), false);
|
||||
assert.equal(calls.includes('startJellyfinRemoteSession'), false);
|
||||
assert.equal(calls.includes('logConfigWarning'), false);
|
||||
assert.equal(calls.includes('handleInitialArgs'), true);
|
||||
assert.equal(calls.includes('loadYomitanExtension'), true);
|
||||
assert.equal(calls[0], 'loadYomitanExtension');
|
||||
assert.equal(calls[calls.length - 1], 'handleInitialArgs');
|
||||
});
|
||||
|
||||
test('runAppReadyRuntime skips Jellyfin remote startup when dependency is not wired', async () => {
|
||||
const { deps, calls } = makeDeps({
|
||||
startJellyfinRemoteSession: undefined,
|
||||
|
||||
@@ -121,6 +121,7 @@ export interface AppReadyRuntimeDeps {
|
||||
logDebug?: (message: string) => void;
|
||||
onCriticalConfigErrors?: (errors: string[]) => void;
|
||||
now?: () => number;
|
||||
shouldSkipHeavyStartup?: () => boolean;
|
||||
}
|
||||
|
||||
const REQUIRED_ANKI_FIELD_MAPPING_KEYS = [
|
||||
@@ -169,6 +170,13 @@ export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<voi
|
||||
const startupStartedAtMs = now();
|
||||
deps.logDebug?.('App-ready critical path started.');
|
||||
|
||||
if (deps.shouldSkipHeavyStartup?.()) {
|
||||
await deps.loadYomitanExtension();
|
||||
deps.handleInitialArgs();
|
||||
deps.logDebug?.(`App-ready critical path finished in ${now() - startupStartedAtMs}ms.`);
|
||||
return;
|
||||
}
|
||||
|
||||
deps.reloadConfig();
|
||||
const config = deps.getResolvedConfig();
|
||||
const criticalConfigErrors = getStartupCriticalConfigErrors(config);
|
||||
|
||||
@@ -101,7 +101,12 @@ import { SubtitleTimingTracker } from './subtitle-timing-tracker';
|
||||
import { RuntimeOptionsManager } from './runtime-options';
|
||||
import { downloadToFile, isRemoteMediaPath, parseMediaInfo } from './jimaku/utils';
|
||||
import { createLogger, setLogLevel, type LogLevelSource } from './logger';
|
||||
import { commandNeedsOverlayRuntime, parseArgs, shouldStartApp } from './cli/args';
|
||||
import {
|
||||
commandNeedsOverlayRuntime,
|
||||
parseArgs,
|
||||
shouldRunSettingsOnlyStartup,
|
||||
shouldStartApp,
|
||||
} from './cli/args';
|
||||
import type { CliArgs, CliCommandSource } from './cli/args';
|
||||
import { printHelp } from './cli/help';
|
||||
import {
|
||||
@@ -2163,6 +2168,8 @@ const { reloadConfig: reloadConfigHandler, appReadyRuntimeRunner } = composeAppR
|
||||
: configDerivedRuntime.shouldAutoInitializeOverlayRuntimeFromConfig(),
|
||||
initializeOverlayRuntime: () => initializeOverlayRuntime(),
|
||||
handleInitialArgs: () => handleInitialArgs(),
|
||||
shouldSkipHeavyStartup: () =>
|
||||
Boolean(appState.initialArgs && shouldRunSettingsOnlyStartup(appState.initialArgs)),
|
||||
createImmersionTracker: () => {
|
||||
ensureImmersionTrackerStarted();
|
||||
},
|
||||
|
||||
@@ -48,6 +48,7 @@ export interface AppReadyRuntimeDepsFactoryInput {
|
||||
onCriticalConfigErrors?: AppReadyRuntimeDeps['onCriticalConfigErrors'];
|
||||
logDebug?: AppReadyRuntimeDeps['logDebug'];
|
||||
now?: AppReadyRuntimeDeps['now'];
|
||||
shouldSkipHeavyStartup?: AppReadyRuntimeDeps['shouldSkipHeavyStartup'];
|
||||
}
|
||||
|
||||
export function createAppLifecycleRuntimeDeps(
|
||||
@@ -103,6 +104,7 @@ export function createAppReadyRuntimeDeps(
|
||||
onCriticalConfigErrors: params.onCriticalConfigErrors,
|
||||
logDebug: params.logDebug,
|
||||
now: params.now,
|
||||
shouldSkipHeavyStartup: params.shouldSkipHeavyStartup,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +31,6 @@ export function createBuildAppReadyRuntimeMainDepsHandler(deps: AppReadyRuntimeD
|
||||
onCriticalConfigErrors: deps.onCriticalConfigErrors,
|
||||
logDebug: deps.logDebug,
|
||||
now: deps.now,
|
||||
shouldSkipHeavyStartup: deps.shouldSkipHeavyStartup,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user