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

@@ -132,7 +132,10 @@ export function createMainBootServices<
TSubtitleWebSocket,
TLogger,
TRuntimeRegistry,
TOverlayManager extends { getMainWindow: () => BrowserWindow | null; getModalWindow: () => BrowserWindow | null },
TOverlayManager extends {
getMainWindow: () => BrowserWindow | null;
getModalWindow: () => BrowserWindow | null;
},
TOverlayModalInputState extends OverlayModalInputStateShape,
TOverlayContentMeasurementStore,
TOverlayModalRuntime,

View File

@@ -180,13 +180,15 @@ function createMockWindow(): MockWindow & {
get: () => state.contentReady,
set: (value: boolean) => {
state.contentReady = value;
(window as typeof window & { __subminerOverlayContentReady?: boolean }).__subminerOverlayContentReady =
value;
(
window as typeof window & { __subminerOverlayContentReady?: boolean }
).__subminerOverlayContentReady = value;
},
});
(window as typeof window & { __subminerOverlayContentReady?: boolean }).__subminerOverlayContentReady =
state.contentReady;
(
window as typeof window & { __subminerOverlayContentReady?: boolean }
).__subminerOverlayContentReady = state.contentReady;
return window;
}
@@ -561,23 +563,26 @@ test('handleOverlayModalClosed destroys modal window for single kiku modal', ()
test('modal fallback reveal skips showing window when content is not ready', async () => {
const window = createMockWindow();
let scheduledReveal: (() => void) | null = null;
const runtime = createOverlayModalRuntimeService({
getMainWindow: () => null,
getModalWindow: () => window as never,
createModalWindow: () => {
throw new Error('modal window should not be created when already present');
const runtime = createOverlayModalRuntimeService(
{
getMainWindow: () => null,
getModalWindow: () => window as never,
createModalWindow: () => {
throw new Error('modal window should not be created when already present');
},
getModalGeometry: () => ({ x: 0, y: 0, width: 400, height: 300 }),
setModalWindowBounds: () => {},
},
getModalGeometry: () => ({ x: 0, y: 0, width: 400, height: 300 }),
setModalWindowBounds: () => {},
}, {
scheduleRevealFallback: (callback) => {
scheduledReveal = callback;
return { scheduled: true } as never;
{
scheduleRevealFallback: (callback) => {
scheduledReveal = callback;
return { scheduled: true } as never;
},
clearRevealFallback: () => {
scheduledReveal = null;
},
},
clearRevealFallback: () => {
scheduledReveal = null;
},
});
);
window.loading = true;
window.url = '';

View File

@@ -54,10 +54,7 @@ type RevealFallbackHandle = NonNullable<Parameters<typeof globalThis.clearTimeou
export interface OverlayModalRuntimeOptions {
onModalStateChange?: (isActive: boolean) => void;
scheduleRevealFallback?: (
callback: () => void,
delayMs: number,
) => RevealFallbackHandle;
scheduleRevealFallback?: (callback: () => void, delayMs: number) => RevealFallbackHandle;
clearRevealFallback?: (timeout: RevealFallbackHandle) => void;
}
@@ -73,10 +70,7 @@ export function createOverlayModalRuntimeService(
let modalWindowPrimedForImmediateShow = false;
let pendingModalWindowReveal: BrowserWindow | null = null;
let pendingModalWindowRevealTimeout: RevealFallbackHandle | null = null;
const scheduleRevealFallback = (
callback: () => void,
delayMs: number,
): RevealFallbackHandle =>
const scheduleRevealFallback = (callback: () => void, delayMs: number): RevealFallbackHandle =>
(options.scheduleRevealFallback ?? globalThis.setTimeout)(callback, delayMs);
const clearRevealFallback = (timeout: RevealFallbackHandle): void =>
(options.clearRevealFallback ?? globalThis.clearTimeout)(timeout);

View File

@@ -16,7 +16,8 @@ test('on will quit cleanup handler runs all cleanup steps', () => {
unregisterAllGlobalShortcuts: () => calls.push('unregister-shortcuts'),
stopSubtitleWebsocket: () => calls.push('stop-ws'),
stopTexthookerService: () => calls.push('stop-texthooker'),
clearWindowsVisibleOverlayForegroundPollLoop: () => calls.push('clear-windows-visible-overlay-poll'),
clearWindowsVisibleOverlayForegroundPollLoop: () =>
calls.push('clear-windows-visible-overlay-poll'),
destroyMainOverlayWindow: () => calls.push('destroy-main-overlay-window'),
destroyModalOverlayWindow: () => calls.push('destroy-modal-overlay-window'),
destroyYomitanParserWindow: () => calls.push('destroy-yomitan-window'),

View File

@@ -45,11 +45,7 @@ export function buildConfigHotReloadPayload(config: ResolvedConfig): ConfigHotRe
shortcuts: resolveConfiguredShortcuts(config, DEFAULT_CONFIG),
statsToggleKey: config.stats.toggleKey,
platform:
process.platform === 'darwin'
? 'darwin'
: process.platform === 'win32'
? 'win32'
: 'linux',
process.platform === 'darwin' ? 'darwin' : process.platform === 'win32' ? 'win32' : 'linux',
rawConfig: config,
});
return {

View File

@@ -94,10 +94,7 @@ test('shouldAutoOpenFirstRunSetup only for startup/setup intents', () => {
});
test('shouldAutoOpenFirstRunSetup treats numeric startup counts as explicit commands', () => {
assert.equal(
shouldAutoOpenFirstRunSetup(makeArgs({ start: true, copySubtitleCount: 2 })),
false,
);
assert.equal(shouldAutoOpenFirstRunSetup(makeArgs({ start: true, copySubtitleCount: 2 })), false);
assert.equal(
shouldAutoOpenFirstRunSetup(makeArgs({ background: true, mineSentenceCount: 1 })),
false,

View File

@@ -194,7 +194,9 @@ test('createImmersionTrackerStartupHandler keeps tracker startup alive when mpv
),
);
assert.equal(
calls.some((entry) => entry.startsWith('warn:Immersion tracker startup failed; disabling tracking.')),
calls.some((entry) =>
entry.startsWith('warn:Immersion tracker startup failed; disabling tracking.'),
),
false,
);
});

View File

@@ -105,7 +105,10 @@ export function createImmersionTrackerStartupHandler(
try {
mpvClient.connect();
} catch (error) {
deps.logWarn('MPV auto-connect failed during immersion tracker startup; continuing.', error);
deps.logWarn(
'MPV auto-connect failed during immersion tracker startup; continuing.',
error,
);
}
}
deps.seedTrackerFromCurrentMedia();