mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 12:55:16 -07:00
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:
@@ -1,39 +1,75 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { DEFAULT_CONFIG } from '../definitions';
|
||||
import {
|
||||
buildConfigSettingsRegistry,
|
||||
getConfigSettingsCoverage,
|
||||
LEGACY_HIDDEN_CONFIG_PATHS,
|
||||
} from './registry';
|
||||
import { buildConfigSettingsRegistry } from './registry';
|
||||
|
||||
test('config settings registry places hover pause under viewing playback behavior', () => {
|
||||
const fields = buildConfigSettingsRegistry(DEFAULT_CONFIG);
|
||||
const hoverPause = fields.find(
|
||||
(field) => field.configPath === 'subtitleStyle.autoPauseVideoOnHover',
|
||||
);
|
||||
const fields = buildConfigSettingsRegistry(DEFAULT_CONFIG);
|
||||
|
||||
assert.ok(hoverPause);
|
||||
assert.equal(hoverPause.category, 'viewing');
|
||||
assert.equal(hoverPause.section, 'Playback pause behavior');
|
||||
assert.equal(hoverPause.control, 'boolean');
|
||||
function field(path: string) {
|
||||
const match = fields.find((candidate) => candidate.configPath === path);
|
||||
assert.ok(match, `missing settings field: ${path}`);
|
||||
return match;
|
||||
}
|
||||
|
||||
test('settings registry splits viewing into appearance and behavior categories', () => {
|
||||
assert.equal(field('subtitleStyle.fontSize').category, 'appearance');
|
||||
assert.equal(field('subtitleStyle.primaryDefaultMode').category, 'behavior');
|
||||
assert.equal(field('subtitleStyle.primaryDefaultMode').section, 'Subtitle Behavior');
|
||||
assert.equal(field('secondarySub.defaultMode').category, 'behavior');
|
||||
assert.equal(field('subtitlePosition.yPercent').label, 'Subtitle Position');
|
||||
});
|
||||
|
||||
test('config settings registry hides legacy and ignored paths from normal fields', () => {
|
||||
const fields = buildConfigSettingsRegistry(DEFAULT_CONFIG);
|
||||
const visiblePaths = new Set(
|
||||
fields.filter((field) => !field.legacyHidden).map((field) => field.configPath),
|
||||
test('settings registry groups annotation display fields by config group', () => {
|
||||
assert.equal(field('ankiConnect.knownWords.highlightEnabled').section, 'Annotation Display');
|
||||
assert.equal(field('ankiConnect.knownWords.highlightEnabled').subsection, 'Known Words');
|
||||
assert.equal(field('subtitleStyle.knownWordColor').subsection, 'Known Words');
|
||||
assert.equal(field('subtitleStyle.nPlusOneColor').subsection, 'N+1');
|
||||
assert.equal(field('subtitleStyle.enableJlpt').subsection, 'JLPT');
|
||||
assert.equal(field('subtitleStyle.jlptColors.N1').control, 'color');
|
||||
});
|
||||
|
||||
test('settings registry exposes specialized controls for config-assisted inputs', () => {
|
||||
assert.equal(field('ankiConnect.knownWords.decks').control, 'known-words-decks');
|
||||
assert.equal(field('ankiConnect.isLapis.sentenceCardModel').control, 'anki-note-type');
|
||||
assert.equal(field('ankiConnect.fields.word').control, 'anki-field');
|
||||
assert.equal(field('keybindings').control, 'mpv-keybindings');
|
||||
assert.equal(field('shortcuts.copySubtitle').control, 'keyboard-shortcut');
|
||||
assert.equal(field('subtitleSidebar.toggleKey').control, 'key-code');
|
||||
assert.equal(field('stats.toggleKey').control, 'key-code');
|
||||
assert.equal(field('discordPresence.presenceStyle').control, 'select');
|
||||
});
|
||||
|
||||
test('settings registry puts feature toggles first, then other toggles alphabetically', () => {
|
||||
const ankiConnect = fields.filter((candidate) => candidate.section === 'AnkiConnect');
|
||||
assert.equal(ankiConnect[0]?.configPath, 'ankiConnect.enabled');
|
||||
assert.ok(
|
||||
ankiConnect.findIndex((candidate) => candidate.configPath === 'ankiConnect.enabled') <
|
||||
ankiConnect.findIndex((candidate) => candidate.configPath === 'ankiConnect.pollingRate'),
|
||||
);
|
||||
|
||||
for (const path of LEGACY_HIDDEN_CONFIG_PATHS) {
|
||||
assert.equal(visiblePaths.has(path), false, path);
|
||||
const kikuLapis = fields.filter(
|
||||
(candidate) => candidate.section === 'Kiku Features And Lapis Features',
|
||||
);
|
||||
assert.deepEqual(
|
||||
kikuLapis.slice(0, 2).map((candidate) => candidate.configPath),
|
||||
['ankiConnect.isLapis.enabled', 'ankiConnect.isKiku.enabled'],
|
||||
);
|
||||
});
|
||||
|
||||
test('settings registry hides app-managed and inactive config surfaces', () => {
|
||||
const paths = new Set(fields.map((candidate) => candidate.configPath));
|
||||
for (const hiddenPath of [
|
||||
'controller.bindings',
|
||||
'controller.preferredGamepadId',
|
||||
'controller.preferredGamepadLabel',
|
||||
'controller.profiles',
|
||||
'youtubeSubgen.whisperBin',
|
||||
'jellyfin.clientVersion',
|
||||
'jellyfin.defaultLibraryId',
|
||||
'jellyfin.deviceId',
|
||||
'jellyfin.clientName',
|
||||
]) {
|
||||
assert.equal(paths.has(hiddenPath), false, `${hiddenPath} should be hidden`);
|
||||
}
|
||||
assert.equal(visiblePaths.has('controller.buttonIndices'), false);
|
||||
});
|
||||
|
||||
test('config settings registry covers canonical defaults or marks explicit raw-only gaps', () => {
|
||||
const fields = buildConfigSettingsRegistry(DEFAULT_CONFIG);
|
||||
const coverage = getConfigSettingsCoverage(DEFAULT_CONFIG, fields);
|
||||
|
||||
assert.deepEqual(coverage.uncoveredDefaultPaths, []);
|
||||
assert.equal(field('anilist.characterDictionary.enabled').section, 'Character Dictionary');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user