Wire Yomitan session into overlay window creation

- Pass `yomitanSession` through overlay window factory deps
- Set BrowserWindow `webPreferences.session` when session is available
- Extend tests to verify session plumbing across runtime/factory layers
This commit is contained in:
2026-03-11 20:08:14 -07:00
parent aa569272db
commit ae44477a69
8 changed files with 38 additions and 7 deletions

View File

@@ -9,3 +9,10 @@ test('overlay window config explicitly disables renderer sandbox for preload com
assert.match(source, /webPreferences:\s*\{[\s\S]*sandbox:\s*false[\s\S]*\}/m); assert.match(source, /webPreferences:\s*\{[\s\S]*sandbox:\s*false[\s\S]*\}/m);
}); });
test('overlay window config uses the provided Yomitan session when available', () => {
const sourcePath = path.join(process.cwd(), 'src/core/services/overlay-window.ts');
const source = fs.readFileSync(sourcePath, 'utf8');
assert.match(source, /session:\s*options\.yomitanSession\s*\?\?\s*undefined/);
});

View File

@@ -1,4 +1,4 @@
import { BrowserWindow } from 'electron'; import { BrowserWindow, type Session } from 'electron';
import * as path from 'path'; import * as path from 'path';
import { WindowGeometry } from '../../types'; import { WindowGeometry } from '../../types';
import { createLogger } from '../../logger'; import { createLogger } from '../../logger';
@@ -78,6 +78,7 @@ export function createOverlayWindow(
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean; tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void; forwardTabToMpv: () => void;
onWindowClosed: (kind: OverlayWindowKind) => void; onWindowClosed: (kind: OverlayWindowKind) => void;
yomitanSession?: Session | null;
}, },
): BrowserWindow { ): BrowserWindow {
const showNativeDebugFrame = process.platform === 'win32' && options.isDev; const showNativeDebugFrame = process.platform === 'win32' && options.isDev;
@@ -102,6 +103,7 @@ export function createOverlayWindow(
nodeIntegration: false, nodeIntegration: false,
sandbox: false, sandbox: false,
webSecurity: true, webSecurity: true,
session: options.yomitanSession ?? undefined,
additionalArguments: [`--overlay-layer=${kind}`], additionalArguments: [`--overlay-layer=${kind}`],
}, },
}); });

View File

@@ -3558,6 +3558,7 @@ const { createMainWindow: createMainWindowHandler, createModalWindow: createModa
setOverlayDebugVisualizationEnabled(enabled), setOverlayDebugVisualizationEnabled(enabled),
isOverlayVisible: (windowKind) => isOverlayVisible: (windowKind) =>
windowKind === 'visible' ? overlayManager.getVisibleOverlayVisible() : false, windowKind === 'visible' ? overlayManager.getVisibleOverlayVisible() : false,
getYomitanSession: () => appState.yomitanSession,
tryHandleOverlayShortcutLocalFallback: (input) => tryHandleOverlayShortcutLocalFallback: (input) =>
overlayShortcutsRuntime.tryHandleOverlayShortcutLocalFallback(input), overlayShortcutsRuntime.tryHandleOverlayShortcutLocalFallback(input),
forwardTabToMpv: () => sendMpvCommandRuntime(appState.mpvClient, ['keypress', 'TAB']), forwardTabToMpv: () => sendMpvCommandRuntime(appState.mpvClient, ['keypress', 'TAB']),

View File

@@ -8,6 +8,7 @@ import {
test('overlay window factory main deps builders return mapped handlers', () => { test('overlay window factory main deps builders return mapped handlers', () => {
const calls: string[] = []; const calls: string[] = [];
const yomitanSession = { id: 'session' } as never;
const buildOverlayDeps = createBuildCreateOverlayWindowMainDepsHandler({ const buildOverlayDeps = createBuildCreateOverlayWindowMainDepsHandler({
createOverlayWindowCore: (kind) => ({ kind }), createOverlayWindowCore: (kind) => ({ kind }),
isDev: true, isDev: true,
@@ -18,11 +19,13 @@ test('overlay window factory main deps builders return mapped handlers', () => {
tryHandleOverlayShortcutLocalFallback: () => false, tryHandleOverlayShortcutLocalFallback: () => false,
forwardTabToMpv: () => calls.push('forward-tab'), forwardTabToMpv: () => calls.push('forward-tab'),
onWindowClosed: (kind) => calls.push(`closed:${kind}`), onWindowClosed: (kind) => calls.push(`closed:${kind}`),
getYomitanSession: () => yomitanSession,
}); });
const overlayDeps = buildOverlayDeps(); const overlayDeps = buildOverlayDeps();
assert.equal(overlayDeps.isDev, true); assert.equal(overlayDeps.isDev, true);
assert.equal(overlayDeps.isOverlayVisible('visible'), true); assert.equal(overlayDeps.isOverlayVisible('visible'), true);
assert.equal(overlayDeps.getYomitanSession(), yomitanSession);
overlayDeps.forwardTabToMpv(); overlayDeps.forwardTabToMpv();
const buildMainDeps = createBuildCreateMainWindowMainDepsHandler({ const buildMainDeps = createBuildCreateMainWindowMainDepsHandler({

View File

@@ -1,3 +1,5 @@
import type { Session } from 'electron';
export function createBuildCreateOverlayWindowMainDepsHandler<TWindow>(deps: { export function createBuildCreateOverlayWindowMainDepsHandler<TWindow>(deps: {
createOverlayWindowCore: ( createOverlayWindowCore: (
kind: 'visible' | 'modal', kind: 'visible' | 'modal',
@@ -10,6 +12,7 @@ export function createBuildCreateOverlayWindowMainDepsHandler<TWindow>(deps: {
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean; tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void; forwardTabToMpv: () => void;
onWindowClosed: (windowKind: 'visible' | 'modal') => void; onWindowClosed: (windowKind: 'visible' | 'modal') => void;
yomitanSession?: Session | null;
}, },
) => TWindow; ) => TWindow;
isDev: boolean; isDev: boolean;
@@ -20,6 +23,7 @@ export function createBuildCreateOverlayWindowMainDepsHandler<TWindow>(deps: {
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean; tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void; forwardTabToMpv: () => void;
onWindowClosed: (windowKind: 'visible' | 'modal') => void; onWindowClosed: (windowKind: 'visible' | 'modal') => void;
getYomitanSession?: () => Session | null;
}) { }) {
return () => ({ return () => ({
createOverlayWindowCore: deps.createOverlayWindowCore, createOverlayWindowCore: deps.createOverlayWindowCore,
@@ -31,6 +35,7 @@ export function createBuildCreateOverlayWindowMainDepsHandler<TWindow>(deps: {
tryHandleOverlayShortcutLocalFallback: deps.tryHandleOverlayShortcutLocalFallback, tryHandleOverlayShortcutLocalFallback: deps.tryHandleOverlayShortcutLocalFallback,
forwardTabToMpv: deps.forwardTabToMpv, forwardTabToMpv: deps.forwardTabToMpv,
onWindowClosed: deps.onWindowClosed, onWindowClosed: deps.onWindowClosed,
getYomitanSession: () => deps.getYomitanSession?.() ?? null,
}); });
} }

View File

@@ -9,12 +9,14 @@ import {
test('create overlay window handler forwards options and kind', () => { test('create overlay window handler forwards options and kind', () => {
const calls: string[] = []; const calls: string[] = [];
const window = { id: 1 }; const window = { id: 1 };
const yomitanSession = { id: 'session' } as never;
const createOverlayWindow = createCreateOverlayWindowHandler({ const createOverlayWindow = createCreateOverlayWindowHandler({
createOverlayWindowCore: (kind, options) => { createOverlayWindowCore: (kind, options) => {
calls.push(`kind:${kind}`); calls.push(`kind:${kind}`);
assert.equal(options.isDev, true); assert.equal(options.isDev, true);
assert.equal(options.isOverlayVisible('visible'), true); assert.equal(options.isOverlayVisible('visible'), true);
assert.equal(options.isOverlayVisible('modal'), false); assert.equal(options.isOverlayVisible('modal'), false);
assert.equal(options.yomitanSession, yomitanSession);
options.forwardTabToMpv(); options.forwardTabToMpv();
options.onRuntimeOptionsChanged(); options.onRuntimeOptionsChanged();
options.setOverlayDebugVisualizationEnabled(true); options.setOverlayDebugVisualizationEnabled(true);
@@ -29,6 +31,7 @@ test('create overlay window handler forwards options and kind', () => {
tryHandleOverlayShortcutLocalFallback: () => false, tryHandleOverlayShortcutLocalFallback: () => false,
forwardTabToMpv: () => calls.push('forward-tab'), forwardTabToMpv: () => calls.push('forward-tab'),
onWindowClosed: (kind) => calls.push(`closed:${kind}`), onWindowClosed: (kind) => calls.push(`closed:${kind}`),
getYomitanSession: () => yomitanSession,
}); });
assert.equal(createOverlayWindow('visible'), window); assert.equal(createOverlayWindow('visible'), window);

View File

@@ -1,3 +1,5 @@
import type { Session } from 'electron';
type OverlayWindowKind = 'visible' | 'modal'; type OverlayWindowKind = 'visible' | 'modal';
export function createCreateOverlayWindowHandler<TWindow>(deps: { export function createCreateOverlayWindowHandler<TWindow>(deps: {
@@ -12,6 +14,7 @@ export function createCreateOverlayWindowHandler<TWindow>(deps: {
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean; tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void; forwardTabToMpv: () => void;
onWindowClosed: (windowKind: OverlayWindowKind) => void; onWindowClosed: (windowKind: OverlayWindowKind) => void;
yomitanSession?: Session | null;
}, },
) => TWindow; ) => TWindow;
isDev: boolean; isDev: boolean;
@@ -22,6 +25,7 @@ export function createCreateOverlayWindowHandler<TWindow>(deps: {
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean; tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void; forwardTabToMpv: () => void;
onWindowClosed: (windowKind: OverlayWindowKind) => void; onWindowClosed: (windowKind: OverlayWindowKind) => void;
getYomitanSession?: () => Session | null;
}) { }) {
return (kind: OverlayWindowKind): TWindow => { return (kind: OverlayWindowKind): TWindow => {
return deps.createOverlayWindowCore(kind, { return deps.createOverlayWindowCore(kind, {
@@ -33,6 +37,7 @@ export function createCreateOverlayWindowHandler<TWindow>(deps: {
tryHandleOverlayShortcutLocalFallback: deps.tryHandleOverlayShortcutLocalFallback, tryHandleOverlayShortcutLocalFallback: deps.tryHandleOverlayShortcutLocalFallback,
forwardTabToMpv: deps.forwardTabToMpv, forwardTabToMpv: deps.forwardTabToMpv,
onWindowClosed: deps.onWindowClosed, onWindowClosed: deps.onWindowClosed,
yomitanSession: deps.getYomitanSession?.() ?? null,
}); });
}; };
} }

View File

@@ -7,10 +7,14 @@ test('overlay window runtime handlers compose create/main/modal handlers', () =>
let modalWindow: { kind: string } | null = null; let modalWindow: { kind: string } | null = null;
let debugEnabled = false; let debugEnabled = false;
const calls: string[] = []; const calls: string[] = [];
const yomitanSession = { id: 'session' } as never;
const runtime = createOverlayWindowRuntimeHandlers({ const runtime = createOverlayWindowRuntimeHandlers<{ kind: string }>({
createOverlayWindowDeps: { createOverlayWindowDeps: {
createOverlayWindowCore: (kind) => ({ kind }), createOverlayWindowCore: (kind, options) => {
assert.equal(options.yomitanSession, yomitanSession);
return { kind };
},
isDev: true, isDev: true,
ensureOverlayWindowLevel: () => calls.push('ensure-level'), ensureOverlayWindowLevel: () => calls.push('ensure-level'),
onRuntimeOptionsChanged: () => calls.push('runtime-options-changed'), onRuntimeOptionsChanged: () => calls.push('runtime-options-changed'),
@@ -21,6 +25,7 @@ test('overlay window runtime handlers compose create/main/modal handlers', () =>
tryHandleOverlayShortcutLocalFallback: () => false, tryHandleOverlayShortcutLocalFallback: () => false,
forwardTabToMpv: () => calls.push('forward-tab'), forwardTabToMpv: () => calls.push('forward-tab'),
onWindowClosed: (kind) => calls.push(`closed:${kind}`), onWindowClosed: (kind) => calls.push(`closed:${kind}`),
getYomitanSession: () => yomitanSession,
}, },
setMainWindow: (window) => { setMainWindow: (window) => {
mainWindow = window; mainWindow = window;