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 e84674e3b5
commit a4314ab5de
44 changed files with 2152 additions and 321 deletions
+9 -9
View File
@@ -1846,7 +1846,7 @@ test('accepts valid ankiConnect knownWords match mode values', () => {
assert.equal(config.ankiConnect.knownWords.matchMode, 'surface');
});
test('validates ankiConnect knownWords and n+1 color values', () => {
test('validates legacy ankiConnect knownWords and n+1 color values', () => {
const dir = makeTempDir();
fs.writeFileSync(
path.join(dir, 'config.jsonc'),
@@ -1867,13 +1867,13 @@ test('validates ankiConnect knownWords and n+1 color values', () => {
const config = service.getConfig();
const warnings = service.getWarnings();
assert.equal(config.ankiConnect.nPlusOne.nPlusOne, DEFAULT_CONFIG.ankiConnect.nPlusOne.nPlusOne);
assert.equal(config.ankiConnect.knownWords.color, DEFAULT_CONFIG.ankiConnect.knownWords.color);
assert.equal(config.subtitleStyle.nPlusOneColor, DEFAULT_CONFIG.subtitleStyle.nPlusOneColor);
assert.equal(config.subtitleStyle.knownWordColor, DEFAULT_CONFIG.subtitleStyle.knownWordColor);
assert.ok(warnings.some((warning) => warning.path === 'ankiConnect.nPlusOne.nPlusOne'));
assert.ok(warnings.some((warning) => warning.path === 'ankiConnect.knownWords.color'));
});
test('accepts valid ankiConnect knownWords and n+1 color values', () => {
test('maps legacy ankiConnect knownWords and n+1 color values to subtitleStyle', () => {
const dir = makeTempDir();
fs.writeFileSync(
path.join(dir, 'config.jsonc'),
@@ -1893,8 +1893,8 @@ test('accepts valid ankiConnect knownWords and n+1 color values', () => {
const service = new ConfigService(dir);
const config = service.getConfig();
assert.equal(config.ankiConnect.nPlusOne.nPlusOne, '#c6a0f6');
assert.equal(config.ankiConnect.knownWords.color, '#a6da95');
assert.equal(config.subtitleStyle.nPlusOneColor, '#c6a0f6');
assert.equal(config.subtitleStyle.knownWordColor, '#a6da95');
});
test('supports legacy ankiConnect nPlusOne known-word settings as fallback', () => {
@@ -1926,7 +1926,7 @@ test('supports legacy ankiConnect nPlusOne known-word settings as fallback', ()
Mining: ['Expression', 'Word', 'Reading', 'Word Reading'],
'Kaishi 1.5k': ['Expression', 'Word', 'Reading', 'Word Reading'],
});
assert.equal(config.ankiConnect.knownWords.color, '#a6da95');
assert.equal(config.subtitleStyle.knownWordColor, '#a6da95');
assert.ok(
warnings.some(
(warning) =>
@@ -2280,9 +2280,9 @@ test('template generator includes known keys', () => {
assert.match(output, /"characterDictionary":\s*\{/);
assert.match(output, /"preserveLineBreaks": false/);
assert.match(output, /"knownWords"\s*:\s*\{/);
assert.match(output, /"color": "#a6da95"/);
assert.match(output, /"knownWordColor": "#a6da95"/);
assert.match(output, /"nPlusOneColor": "#c6a0f6"/);
assert.match(output, /"nPlusOne"\s*:\s*\{/);
assert.match(output, /"nPlusOne": "#c6a0f6"/);
assert.match(output, /"minSentenceWords": 3/);
assert.match(output, /auto-generated from src\/config\/definitions.ts/);
assert.match(