feat(stats): add stats server, API endpoints, config, and Anki integration

- Hono HTTP server with 20+ REST endpoints for stats data
- Stats overlay BrowserWindow with toggle keybinding
- IPC channel definitions and preload bridge
- Stats config section (toggleKey, serverPort, autoStartServer, autoOpenBrowser)
- Config resolver for stats section
- AnkiConnect proxy endpoints (guiBrowse, notesInfo)
- Note ID passthrough in card mining callback chain
- Stats CLI command with autoOpenBrowser respect
This commit is contained in:
2026-03-14 22:14:09 -07:00
parent fe8bb167c4
commit ffe5c6e1c6
36 changed files with 2273 additions and 86 deletions

View File

@@ -621,6 +621,13 @@ export interface YoutubeSubgenConfig {
primarySubLanguages?: string[];
}
export interface StatsConfig {
toggleKey?: string;
serverPort?: number;
autoStartServer?: boolean;
autoOpenBrowser?: boolean;
}
export interface ImmersionTrackingConfig {
enabled?: boolean;
dbPath?: string;
@@ -660,6 +667,7 @@ export interface Config {
ai?: AiConfig;
youtubeSubgen?: YoutubeSubgenConfig;
immersionTracking?: ImmersionTrackingConfig;
stats?: StatsConfig;
logging?: {
level?: 'debug' | 'info' | 'warn' | 'error';
};
@@ -855,6 +863,12 @@ export interface ResolvedConfig {
vacuumIntervalDays: number;
};
};
stats: {
toggleKey: string;
serverPort: number;
autoStartServer: boolean;
autoOpenBrowser: boolean;
};
logging: {
level: 'debug' | 'info' | 'warn' | 'error';
};
@@ -1041,6 +1055,7 @@ export interface ElectronAPI {
sendMpvCommand: (command: (string | number)[]) => void;
getKeybindings: () => Promise<Keybinding[]>;
getConfiguredShortcuts: () => Promise<Required<ShortcutsConfig>>;
getStatsToggleKey: () => Promise<string>;
getControllerConfig: () => Promise<ResolvedControllerConfig>;
saveControllerConfig: (update: ControllerConfigUpdate) => Promise<void>;
saveControllerPreference: (update: ControllerPreferenceUpdate) => Promise<void>;
@@ -1051,6 +1066,7 @@ export interface ElectronAPI {
quitApp: () => void;
toggleDevTools: () => void;
toggleOverlay: () => void;
toggleStatsOverlay: () => void;
getAnkiConnectStatus: () => Promise<boolean>;
setAnkiConnectEnabled: (enabled: boolean) => void;
clearAnkiConnectHistory: () => void;