chore(release): prepare v0.12.0

This commit is contained in:
2026-04-11 21:54:00 -07:00
parent 52bab1d611
commit 7ac51cd5e9
56 changed files with 466 additions and 296 deletions

View File

@@ -75,9 +75,7 @@ test('runAppReadyRuntime starts websocket in auto mode when plugin missing', asy
calls.indexOf('setVisibleOverlayVisible:true') < calls.indexOf('initializeOverlayRuntime'),
);
assert.ok(calls.includes('startBackgroundWarmups'));
assert.ok(
calls.includes('log:Runtime ready: immersion tracker startup requested.'),
);
assert.ok(calls.includes('log:Runtime ready: immersion tracker startup requested.'));
});
test('runAppReadyRuntime starts texthooker on startup when enabled in config', async () => {

View File

@@ -277,12 +277,7 @@ export function handleCliCommand(
logLabel: string,
osdLabel: string,
): void => {
runAsyncWithOsd(
() => deps.dispatchSessionAction(request),
deps,
logLabel,
osdLabel,
);
runAsyncWithOsd(() => deps.dispatchSessionAction(request), deps, logLabel, osdLabel);
};
if (args.logLevel) {

View File

@@ -3840,16 +3840,7 @@ test('getTrendsDashboard builds librarySummary with per-title aggregates', () =>
lines_seen = ?, tokens_seen = ?, cards_mined = ?, yomitan_lookup_count = ?
WHERE session_id = ?
`,
).run(
`${startedAtMs + activeMs}`,
activeMs,
activeMs,
10,
tokens,
cards,
lookups,
sessionId,
);
).run(`${startedAtMs + activeMs}`, activeMs, activeMs, 10, tokens, cards, lookups, sessionId);
}
for (const [day, active, tokens, cards] of [
@@ -3947,16 +3938,7 @@ test('getTrendsDashboard librarySummary returns null lookupsPerHundred when word
lines_seen = ?, tokens_seen = ?, cards_mined = ?, yomitan_lookup_count = ?
WHERE session_id = ?
`,
).run(
`${startMs + 20 * 60_000}`,
20 * 60_000,
20 * 60_000,
5,
0,
0,
0,
session.sessionId,
);
).run(`${startMs + 20 * 60_000}`, 20 * 60_000, 20 * 60_000, 5, 0, 0, 0, session.sessionId);
db.prepare(
`

View File

@@ -414,8 +414,7 @@ function buildLibrarySummary(
cards: acc.cards,
words: acc.words,
lookups: acc.lookups,
lookupsPerHundred:
acc.words > 0 ? +((acc.lookups / acc.words) * 100).toFixed(1) : null,
lookupsPerHundred: acc.words > 0 ? +((acc.lookups / acc.words) * 100).toFixed(1) : null,
firstWatched: acc.firstWatched,
lastWatched: acc.lastWatched,
});

View File

@@ -606,13 +606,15 @@ test('ensureSchema migrates session event timestamps to text and repairs libsql-
}>;
assert.equal(column.find((entry) => entry.name === 'ts_ms')?.type, 'TEXT');
const row = db.prepare(
`
const row = db
.prepare(
`
SELECT ts_ms AS tsMs, typeof(ts_ms) AS tsType, CREATED_DATE AS createdDate
FROM imm_session_events
WHERE event_id = 1
`,
).get() as {
)
.get() as {
tsMs: string;
tsType: string;
createdDate: string;

View File

@@ -171,10 +171,12 @@ function hasColumn(db: DatabaseSync, tableName: string, columnName: string): boo
}
function getColumnType(db: DatabaseSync, tableName: string, columnName: string): string | null {
const row = (db.prepare(`PRAGMA table_info(${tableName})`).all() as Array<{
name: string;
type: string;
}>).find((entry) => entry.name === columnName);
const row = (
db.prepare(`PRAGMA table_info(${tableName})`).all() as Array<{
name: string;
type: string;
}>
).find((entry) => entry.name === columnName);
return row?.type ?? null;
}

View File

@@ -886,29 +886,47 @@ test('registerIpcHandlers validates dispatchSessionAction payloads', async () =>
await dispatchHandler!({}, { actionId: 'unknown-action' });
}, /Invalid session action payload/);
await dispatchHandler!({}, {
actionId: 'copySubtitleMultiple',
payload: { count: 3 },
});
await dispatchHandler!({}, {
actionId: 'cycleRuntimeOption',
payload: {
runtimeOptionId: 'anki.autoUpdateNewCards',
direction: -1,
await dispatchHandler!(
{},
{
actionId: 'copySubtitleMultiple',
payload: { count: 3 },
},
});
await dispatchHandler!({}, {
actionId: 'toggleSubtitleSidebar',
});
await dispatchHandler!({}, {
actionId: 'openSessionHelp',
});
await dispatchHandler!({}, {
actionId: 'openControllerSelect',
});
await dispatchHandler!({}, {
actionId: 'openControllerDebug',
});
);
await dispatchHandler!(
{},
{
actionId: 'cycleRuntimeOption',
payload: {
runtimeOptionId: 'anki.autoUpdateNewCards',
direction: -1,
},
},
);
await dispatchHandler!(
{},
{
actionId: 'toggleSubtitleSidebar',
},
);
await dispatchHandler!(
{},
{
actionId: 'openSessionHelp',
},
);
await dispatchHandler!(
{},
{
actionId: 'openControllerSelect',
},
);
await dispatchHandler!(
{},
{
actionId: 'openControllerDebug',
},
);
assert.deepEqual(dispatched, [
{

View File

@@ -45,11 +45,7 @@ test('collectDroppedVideoPaths parses text/uri-list entries and de-duplicates',
test('collectDroppedSubtitlePaths keeps supported dropped subtitle paths in order', () => {
const transfer = makeTransfer({
files: [
{ path: '/subs/ep02.ass' },
{ path: '/subs/readme.txt' },
{ path: '/subs/ep03.SRT' },
],
files: [{ path: '/subs/ep02.ass' }, { path: '/subs/readme.txt' }, { path: '/subs/ep03.SRT' }],
});
const result = collectDroppedSubtitlePaths(transfer);

View File

@@ -158,18 +158,24 @@ export function updateVisibleOverlayVisibility(args: {
setOverlayWindowOpacity(mainWindow, 0);
mainWindow.showInactive();
mainWindow.setIgnoreMouseEvents(true, { forward: true });
scheduleWindowsOverlayReveal(mainWindow, shouldBindTrackedWindowsOverlay
? (window) => args.syncWindowsOverlayToMpvZOrder?.(window)
: undefined);
scheduleWindowsOverlayReveal(
mainWindow,
shouldBindTrackedWindowsOverlay
? (window) => args.syncWindowsOverlayToMpvZOrder?.(window)
: undefined,
);
} else {
if (args.isWindowsPlatform) {
setOverlayWindowOpacity(mainWindow, 0);
}
mainWindow.show();
if (args.isWindowsPlatform) {
scheduleWindowsOverlayReveal(mainWindow, shouldBindTrackedWindowsOverlay
? (window) => args.syncWindowsOverlayToMpvZOrder?.(window)
: undefined);
scheduleWindowsOverlayReveal(
mainWindow,
shouldBindTrackedWindowsOverlay
? (window) => args.syncWindowsOverlayToMpvZOrder?.(window)
: undefined,
);
}
}
}

View File

@@ -54,9 +54,7 @@ test('compileSessionBindings merges shortcuts and keybindings into one canonical
code: binding.key.code,
modifiers: binding.key.modifiers,
target:
binding.actionType === 'session-action'
? binding.actionId
: binding.command.join(' '),
binding.actionType === 'session-action' ? binding.actionId : binding.command.join(' '),
})),
[
{
@@ -191,9 +189,10 @@ test('compileSessionBindings omits disabled bindings', () => {
});
assert.equal(result.warnings.length, 0);
assert.deepEqual(result.bindings.map((binding) => binding.sourcePath), [
'shortcuts.toggleVisibleOverlayGlobal',
]);
assert.deepEqual(
result.bindings.map((binding) => binding.sourcePath),
['shortcuts.toggleVisibleOverlayGlobal'],
);
});
test('compileSessionBindings warns on unsupported shortcut and keybinding syntax', () => {
@@ -222,12 +221,16 @@ test('compileSessionBindings rejects malformed command arrays', () => {
platform: 'linux',
});
assert.deepEqual(result.bindings.map((binding) => binding.sourcePath), ['keybindings[0].key']);
assert.deepEqual(
result.bindings.map((binding) => binding.sourcePath),
['keybindings[0].key'],
);
assert.equal(result.bindings[0]?.actionType, 'mpv-command');
assert.deepEqual(result.bindings[0]?.command, ['show-text', 3000]);
assert.deepEqual(result.warnings.map((warning) => `${warning.kind}:${warning.path}`), [
'unsupported:keybindings[1].command',
]);
assert.deepEqual(
result.warnings.map((warning) => `${warning.kind}:${warning.path}`),
['unsupported:keybindings[1].command'],
);
});
test('compileSessionBindings rejects non-string command heads and extra args on special commands', () => {
@@ -241,10 +244,10 @@ test('compileSessionBindings rejects non-string command heads and extra args on
});
assert.deepEqual(result.bindings, []);
assert.deepEqual(result.warnings.map((warning) => `${warning.kind}:${warning.path}`), [
'unsupported:keybindings[0].command',
'unsupported:keybindings[1].command',
]);
assert.deepEqual(
result.warnings.map((warning) => `${warning.kind}:${warning.path}`),
['unsupported:keybindings[0].command', 'unsupported:keybindings[1].command'],
);
});
test('compileSessionBindings points unsupported command warnings at the command field', () => {
@@ -255,9 +258,10 @@ test('compileSessionBindings points unsupported command warnings at the command
});
assert.deepEqual(result.bindings, []);
assert.deepEqual(result.warnings.map((warning) => `${warning.kind}:${warning.path}`), [
'unsupported:keybindings[0].command',
]);
assert.deepEqual(
result.warnings.map((warning) => `${warning.kind}:${warning.path}`),
['unsupported:keybindings[0].command'],
);
});
test('compileSessionBindings warns on deprecated toggleVisibleOverlayGlobal config', () => {

View File

@@ -342,9 +342,7 @@ function getBindingFingerprint(binding: CompiledSessionBinding): string {
return `session:${binding.actionId}:${JSON.stringify(binding.payload ?? null)}`;
}
export function compileSessionBindings(
input: CompileSessionBindingsInput,
): {
export function compileSessionBindings(input: CompileSessionBindingsInput): {
bindings: CompiledSessionBinding[];
warnings: SessionBindingWarning[];
} {