mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-28 00:55:16 -07:00
feat(config): add configuration window (#70)
This commit is contained in:
@@ -3,6 +3,7 @@ import { compileSessionBindings } from '../../core/services/session-bindings';
|
||||
import { resolveKeybindings } from '../../core/utils/keybindings';
|
||||
import { resolveConfiguredShortcuts } from '../../core/utils/shortcut-config';
|
||||
import { DEFAULT_CONFIG, DEFAULT_KEYBINDINGS } from '../../config';
|
||||
import type { AnkiConnectConfig } from '../../types/anki';
|
||||
import type { ConfigHotReloadPayload, ResolvedConfig, SecondarySubMode } from '../../types';
|
||||
|
||||
type ConfigHotReloadAppliedDeps = {
|
||||
@@ -14,9 +15,11 @@ type ConfigHotReloadAppliedDeps = {
|
||||
refreshGlobalAndOverlayShortcuts: () => void;
|
||||
setSecondarySubMode: (mode: SecondarySubMode) => void;
|
||||
broadcastToOverlayWindows: (channel: string, payload: unknown) => void;
|
||||
applyAnkiRuntimeConfigPatch: (patch: {
|
||||
ai: ResolvedConfig['ankiConnect']['ai']['enabled'];
|
||||
}) => void;
|
||||
applyAnkiRuntimeConfigPatch: (patch: Partial<AnkiConnectConfig>) => void;
|
||||
invalidateTokenizationCache?: () => void;
|
||||
refreshSubtitlePrefetch?: () => void;
|
||||
refreshCurrentSubtitle?: () => void;
|
||||
setLogLevel?: (level: ResolvedConfig['logging']['level']) => void;
|
||||
};
|
||||
|
||||
type ConfigHotReloadMessageDeps = {
|
||||
@@ -30,8 +33,8 @@ export function resolveSubtitleStyleForRenderer(config: ResolvedConfig) {
|
||||
}
|
||||
return {
|
||||
...config.subtitleStyle,
|
||||
nPlusOneColor: config.ankiConnect.nPlusOne.nPlusOne,
|
||||
knownWordColor: config.ankiConnect.knownWords.color,
|
||||
nPlusOneColor: config.subtitleStyle.nPlusOneColor,
|
||||
knownWordColor: config.subtitleStyle.knownWordColor,
|
||||
nameMatchColor: config.subtitleStyle.nameMatchColor,
|
||||
enableJlpt: config.subtitleStyle.enableJlpt,
|
||||
frequencyDictionary: config.subtitleStyle.frequencyDictionary,
|
||||
@@ -44,6 +47,7 @@ export function buildConfigHotReloadPayload(config: ResolvedConfig): ConfigHotRe
|
||||
keybindings,
|
||||
shortcuts: resolveConfiguredShortcuts(config, DEFAULT_CONFIG),
|
||||
statsToggleKey: config.stats.toggleKey,
|
||||
statsMarkWatchedKey: config.stats.markWatchedKey,
|
||||
platform:
|
||||
process.platform === 'darwin' ? 'darwin' : process.platform === 'win32' ? 'win32' : 'linux',
|
||||
rawConfig: config,
|
||||
@@ -59,6 +63,70 @@ export function buildConfigHotReloadPayload(config: ResolvedConfig): ConfigHotRe
|
||||
};
|
||||
}
|
||||
|
||||
function hasAnyHotReloadField(diff: ConfigHotReloadDiff, prefixes: string[]): boolean {
|
||||
return diff.hotReloadFields.some((field) =>
|
||||
prefixes.some((prefix) => field === prefix || field.startsWith(`${prefix}.`)),
|
||||
);
|
||||
}
|
||||
|
||||
function buildAnkiRuntimeConfigPatch(
|
||||
diff: ConfigHotReloadDiff,
|
||||
config: ResolvedConfig,
|
||||
): Partial<AnkiConnectConfig> | null {
|
||||
const patch: Partial<AnkiConnectConfig> = {};
|
||||
|
||||
if (diff.hotReloadFields.includes('ankiConnect.ai')) {
|
||||
patch.ai = config.ankiConnect.ai.enabled;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.ai.enabled')) {
|
||||
patch.ai = config.ankiConnect.ai.enabled;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.behavior.autoUpdateNewCards')) {
|
||||
patch.behavior = { autoUpdateNewCards: config.ankiConnect.behavior.autoUpdateNewCards };
|
||||
}
|
||||
if (hasAnyHotReloadField(diff, ['ankiConnect.knownWords'])) {
|
||||
patch.knownWords = config.ankiConnect.knownWords;
|
||||
}
|
||||
if (hasAnyHotReloadField(diff, ['ankiConnect.nPlusOne'])) {
|
||||
patch.nPlusOne = config.ankiConnect.nPlusOne;
|
||||
}
|
||||
const fieldPatch: NonNullable<AnkiConnectConfig['fields']> = {};
|
||||
if (diff.hotReloadFields.includes('ankiConnect.fields.word')) {
|
||||
fieldPatch.word = config.ankiConnect.fields.word;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.fields.audio')) {
|
||||
fieldPatch.audio = config.ankiConnect.fields.audio;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.fields.image')) {
|
||||
fieldPatch.image = config.ankiConnect.fields.image;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.fields.sentence')) {
|
||||
fieldPatch.sentence = config.ankiConnect.fields.sentence;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.fields.miscInfo')) {
|
||||
fieldPatch.miscInfo = config.ankiConnect.fields.miscInfo;
|
||||
}
|
||||
if (Object.keys(fieldPatch).length > 0) {
|
||||
patch.fields = fieldPatch;
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.isLapis.sentenceCardModel')) {
|
||||
patch.isLapis = { sentenceCardModel: config.ankiConnect.isLapis.sentenceCardModel };
|
||||
}
|
||||
if (diff.hotReloadFields.includes('ankiConnect.isKiku.fieldGrouping')) {
|
||||
patch.isKiku = { fieldGrouping: config.ankiConnect.isKiku.fieldGrouping };
|
||||
}
|
||||
|
||||
return Object.keys(patch).length > 0 ? patch : null;
|
||||
}
|
||||
|
||||
function hasAnnotationRuntimeHotReload(diff: ConfigHotReloadDiff): boolean {
|
||||
return hasAnyHotReloadField(diff, [
|
||||
'ankiConnect.knownWords',
|
||||
'ankiConnect.nPlusOne',
|
||||
'ankiConnect.fields.word',
|
||||
]);
|
||||
}
|
||||
|
||||
export function createConfigHotReloadAppliedHandler(deps: ConfigHotReloadAppliedDeps) {
|
||||
return (diff: ConfigHotReloadDiff, config: ResolvedConfig): void => {
|
||||
const payload = buildConfigHotReloadPayload(config);
|
||||
@@ -74,8 +142,19 @@ export function createConfigHotReloadAppliedHandler(deps: ConfigHotReloadApplied
|
||||
deps.broadcastToOverlayWindows('secondary-subtitle:mode', payload.secondarySubMode);
|
||||
}
|
||||
|
||||
if (diff.hotReloadFields.includes('ankiConnect.ai')) {
|
||||
deps.applyAnkiRuntimeConfigPatch({ ai: config.ankiConnect.ai.enabled });
|
||||
const ankiPatch = buildAnkiRuntimeConfigPatch(diff, config);
|
||||
if (ankiPatch) {
|
||||
deps.applyAnkiRuntimeConfigPatch(ankiPatch);
|
||||
}
|
||||
|
||||
if (hasAnnotationRuntimeHotReload(diff)) {
|
||||
deps.invalidateTokenizationCache?.();
|
||||
deps.refreshSubtitlePrefetch?.();
|
||||
deps.refreshCurrentSubtitle?.();
|
||||
}
|
||||
|
||||
if (diff.hotReloadFields.includes('logging.level')) {
|
||||
deps.setLogLevel?.(config.logging.level);
|
||||
}
|
||||
|
||||
if (diff.hotReloadFields.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user