feat(config): reorganize settings window and move annotation colors to subtitleStyle

- Reorganize Configuration window into Appearance, Behavior, Anki, Input, and Integration sections
- Add AnkiConnect-backed deck, note-type, and field pickers in the Anki section
- Add click-to-learn keybinding controls
- Move known-word and N+1 highlight colors to subtitleStyle.knownWordColor / subtitleStyle.nPlusOneColor; legacy ankiConnect.knownWords.color and ankiConnect.nPlusOne.nPlusOne keys still accepted with deprecation warnings
- Add deckNames, modelNames, modelFieldNames, and fieldNamesForDeck methods to AnkiConnectClient
- Mark discordPresence.presenceStyle as an enum in the config registry
This commit is contained in:
2026-05-17 02:10:16 -07:00
parent a54f03f0cd
commit 309ce6ef8f
44 changed files with 2152 additions and 321 deletions
@@ -59,7 +59,6 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
addMinedWordsImmediately: true,
matchMode: 'headword',
decks: {},
color: '#a6da95',
},
behavior: {
overwriteAudio: true,
@@ -71,7 +70,6 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
},
nPlusOne: {
minSentenceWords: 3,
nPlusOne: '#c6a0f6',
},
metadata: {
pattern: '[SubMiner] %f (%t)',
+14 -2
View File
@@ -63,10 +63,8 @@ const UNDOCUMENTED_LEAVES: ReadonlySet<string> = new Set([
'subtitleStyle.jlptColors.N3',
'subtitleStyle.jlptColors.N4',
'subtitleStyle.jlptColors.N5',
'subtitleStyle.knownWordColor',
'subtitleStyle.letterSpacing',
'subtitleStyle.lineHeight',
'subtitleStyle.nPlusOneColor',
'subtitleStyle.secondary.backdropFilter',
'subtitleStyle.secondary.backgroundColor',
'subtitleStyle.secondary.fontColor',
@@ -112,6 +110,20 @@ test('config option registry includes critical paths and has unique entries', ()
assert.equal(new Set(paths).size, paths.length);
});
test('known-word annotation color has one public config path', () => {
const leaves = collectConfigLeafPaths(DEFAULT_CONFIG);
assert.ok(leaves.includes('subtitleStyle.knownWordColor'));
assert.ok(!leaves.includes('ankiConnect.knownWords.color'));
});
test('n+1 annotation color has one public config path', () => {
const leaves = collectConfigLeafPaths(DEFAULT_CONFIG);
assert.ok(leaves.includes('subtitleStyle.nPlusOneColor'));
assert.ok(!leaves.includes('ankiConnect.nPlusOne.nPlusOne'));
});
test('every DEFAULT_CONFIG leaf is in CONFIG_OPTION_REGISTRY or UNDOCUMENTED_LEAVES', () => {
const registryPaths = new Set(CONFIG_OPTION_REGISTRY.map((entry) => entry.path));
const leaves = collectConfigLeafPaths(DEFAULT_CONFIG);
+2 -13
View File
@@ -291,18 +291,6 @@ export function buildIntegrationConfigOptionRegistry(
description:
'Decks and fields for known-word cache. Object mapping deck names to arrays of field names to extract, e.g. { "Kaishi 1.5k": ["Word", "Word Reading"] }.',
},
{
path: 'ankiConnect.nPlusOne.nPlusOne',
kind: 'string',
defaultValue: defaultConfig.ankiConnect.nPlusOne.nPlusOne,
description: 'Color used for the single N+1 target token highlight.',
},
{
path: 'ankiConnect.knownWords.color',
kind: 'string',
defaultValue: defaultConfig.ankiConnect.knownWords.color,
description: 'Color used for known-word highlights.',
},
{
path: 'ankiConnect.isKiku.fieldGrouping',
kind: 'enum',
@@ -567,7 +555,8 @@ export function buildIntegrationConfigOptionRegistry(
},
{
path: 'discordPresence.presenceStyle',
kind: 'string',
kind: 'enum',
enumValues: ['default', 'meme', 'japanese', 'minimal'],
defaultValue: defaultConfig.discordPresence.presenceStyle,
description:
'Presence card text preset: "default" (clean bilingual), "meme" (Mining and crafting), "japanese" (fully JP), or "minimal".',
@@ -69,6 +69,18 @@ export function buildSubtitleConfigOptionRegistry(
description:
'Hex color used when a subtitle token matches an entry from the SubMiner character dictionary.',
},
{
path: 'subtitleStyle.knownWordColor',
kind: 'string',
defaultValue: defaultConfig.subtitleStyle.knownWordColor,
description: 'Color used for known-word subtitle highlights.',
},
{
path: 'subtitleStyle.nPlusOneColor',
kind: 'string',
defaultValue: defaultConfig.subtitleStyle.nPlusOneColor,
description: 'Color used for the single N+1 target token subtitle highlight.',
},
{
path: 'subtitleStyle.frequencyDictionary.enabled',
kind: 'boolean',