feat(stats): speed up session maintenance and improve stats UI (#111)

This commit is contained in:
sudacode authored and GitHub committed 2026-06-08 02:20:52 -07:00
1 parent e6a16a069b
commit 311f1e8ee5
108 files changed
+7440 -728

No files matched your search

@@ -1,6 +1,10 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { DEFAULT_CONFIG, deepCloneConfig } from '../../config';
import { resolveConfig } from '../../config/resolve';
import { IPC_CHANNELS } from '../../shared/ipc/contracts';
import { createConfigSettingsRuntime } from './config-settings-runtime';
@@ -10,7 +14,13 @@ test('config settings runtime exposes inferred Yomitan Anki deck lookup', async
fields: [],
getConfigPath: () => '/tmp/config.jsonc',
getRawConfig: () => ({}),
getConfig: () => deepCloneConfig(DEFAULT_CONFIG),
getConfig: () => ({
...deepCloneConfig(DEFAULT_CONFIG),
ankiConnect: {
...deepCloneConfig(DEFAULT_CONFIG).ankiConnect,
deck: 'Configured',
},
}),
getWarnings: () => [],
reloadConfigStrict: () =>
({
@@ -48,3 +58,62 @@ test('config settings runtime exposes inferred Yomitan Anki deck lookup', async
assert.ok(handler);
assert.deepEqual(await handler({}, undefined), { ok: true, value: 'Mining' });
});
test('config settings runtime persists inferred Yomitan Anki deck when config deck is empty', async () => {
const handlers = new Map<string, (event: unknown, ...args: unknown[]) => unknown>();
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'subminer-settings-'));
const configPath = path.join(dir, 'config.jsonc');
fs.writeFileSync(configPath, '{"ankiConnect":{"deck":""}}\n', 'utf-8');
try {
let rawConfig = { ankiConnect: { deck: '' } };
let resolvedConfig = resolveConfig(rawConfig).resolved;
const runtime = createConfigSettingsRuntime({
fields: [],
getConfigPath: () => configPath,
getRawConfig: () => rawConfig,
getConfig: () => resolvedConfig,
getWarnings: () => [],
reloadConfigStrict: () => {
rawConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
resolvedConfig = resolveConfig(rawConfig).resolved;
return {
ok: true,
config: resolvedConfig,
warnings: [],
path: configPath,
};
},
getSettingsWindow: () => null,
setSettingsWindow: () => undefined,
createSettingsWindow: () => ({}) as never,
settingsHtmlPath: '/tmp/settings.html',
openPath: async () => '',
defaultAnkiConnectUrl: DEFAULT_CONFIG.ankiConnect.url,
createAnkiClient: () =>
({
deckNames: async () => [],
fieldNamesForDeck: async () => [],
modelNamesForDeck: async () => [],
modelNames: async () => [],
modelFieldNames: async () => [],
}) as never,
getYomitanAnkiDeckName: async () => 'Minecraft',
ipcMain: {
handle: (channel, listener) => {
handlers.set(channel, listener);
},
},
ipcChannels: IPC_CHANNELS.request,
});
runtime.registerHandlers();
const handler = handlers.get(IPC_CHANNELS.request.getConfigSettingsYomitanAnkiDeckName);
assert.ok(handler);
assert.deepEqual(await handler({}, undefined), { ok: true, value: 'Minecraft' });
assert.equal(JSON.parse(fs.readFileSync(configPath, 'utf-8')).ankiConnect.deck, 'Minecraft');
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
});