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 799cce6991
commit 0298a066ad
44 changed files with 2152 additions and 321 deletions
-2
View File
@@ -212,10 +212,8 @@ export interface ResolvedConfig {
addMinedWordsImmediately: boolean;
matchMode: NPlusOneMatchMode;
decks: Record<string, string[]>;
color: string;
};
nPlusOne: {
nPlusOne: string;
minSentenceWords: number;
};
behavior: {
+3 -2
View File
@@ -31,6 +31,7 @@ import type {
SubtitlePosition,
SubtitleSidebarConfig,
SubtitleSidebarSnapshot,
SubtitleRendererStyleConfig,
SubtitleStyleConfig,
} from './subtitle';
import type {
@@ -343,7 +344,7 @@ export interface ConfigHotReloadPayload {
keybindings: Keybinding[];
sessionBindings: CompiledSessionBinding[];
sessionBindingWarnings: SessionBindingWarning[];
subtitleStyle: SubtitleStyleConfig | null;
subtitleStyle: SubtitleRendererStyleConfig | null;
subtitleSidebar: Required<SubtitleSidebarConfig>;
primarySubMode: PrimarySubMode;
secondarySubMode: SecondarySubMode;
@@ -426,7 +427,7 @@ export interface ElectronAPI {
getSecondarySubMode: () => Promise<SecondarySubMode>;
getCurrentSecondarySub: () => Promise<string>;
focusMainWindow: () => Promise<void>;
getSubtitleStyle: () => Promise<SubtitleStyleConfig | null>;
getSubtitleStyle: () => Promise<SubtitleRendererStyleConfig | null>;
onSubsyncManualOpen: (callback: (payload: SubsyncManualPayload) => void) => void;
runSubsyncManual: (request: SubsyncManualRunRequest) => Promise<SubsyncResult>;
onKikuFieldGroupingRequest: (callback: (data: KikuFieldGroupingRequestData) => void) => void;
+27 -2
View File
@@ -1,7 +1,8 @@
import type { ConfigValidationWarning } from './config';
export type ConfigSettingsCategory =
| 'viewing'
| 'appearance'
| 'behavior'
| 'mining-anki'
| 'playback-sources'
| 'input'
@@ -18,7 +19,14 @@ export type ConfigSettingsControl =
| 'color'
| 'string-list'
| 'json'
| 'secret';
| 'secret'
| 'keyboard-shortcut'
| 'key-code'
| 'known-words-decks'
| 'anki-note-type'
| 'anki-field'
| 'mpv-keybindings'
| 'color-list';
export type ConfigSettingsRestartBehavior = 'hot-reload' | 'restart';
@@ -29,6 +37,7 @@ export interface ConfigSettingsField {
configPath: string;
category: ConfigSettingsCategory;
section: string;
subsection?: string;
control: ConfigSettingsControl;
defaultValue: unknown;
enumValues?: readonly string[];
@@ -77,4 +86,20 @@ export interface ConfigSettingsAPI {
savePatch(patch: ConfigSettingsPatch): Promise<ConfigSettingsSaveResult>;
openSettingsFile(): Promise<boolean>;
openSettingsWindow(): Promise<boolean>;
getAnkiDeckNames(draftUrl?: string): Promise<ConfigSettingsAnkiListResult>;
getAnkiDeckFieldNames(
deckName: string,
draftUrl?: string,
): Promise<ConfigSettingsAnkiListResult>;
getAnkiModelNames(draftUrl?: string): Promise<ConfigSettingsAnkiListResult>;
getAnkiModelFieldNames(
modelName: string,
draftUrl?: string,
): Promise<ConfigSettingsAnkiListResult>;
}
export interface ConfigSettingsAnkiListResult {
ok: boolean;
values: string[];
error?: string;
}
+2
View File
@@ -126,6 +126,8 @@ export interface SubtitleStyleConfig {
};
}
export type SubtitleRendererStyleConfig = SubtitleStyleConfig;
export interface TokenPos1ExclusionConfig {
defaults?: string[];
add?: string[];