mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-15 08:12:53 -07:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4cb0dbfaad | |||
|
801cdcafca
|
@@ -0,0 +1,4 @@
|
|||||||
|
type: internal
|
||||||
|
area: tests
|
||||||
|
|
||||||
|
- Removed stale Yomitan vendor source-inspection assertions for changes that were not shipped.
|
||||||
@@ -3,8 +3,9 @@ area: tray
|
|||||||
|
|
||||||
- Kept the tray app running when closing tray-launched Yomitan settings.
|
- Kept the tray app running when closing tray-launched Yomitan settings.
|
||||||
- Kept tray-launched Yomitan settings loading from blocking other tray actions.
|
- Kept tray-launched Yomitan settings loading from blocking other tray actions.
|
||||||
- Replaced the default native Yomitan settings menu with a close-only menu so closing settings does not quit the tray app.
|
- Removed the default native app menu from Yomitan settings so File > Quit cannot put the tray app into a stuck quit state.
|
||||||
- Added an in-page close button for Yomitan settings on Linux window managers that do not show native decorations.
|
|
||||||
- Disabled Yomitan's embedded popup preview in the tray-launched settings window to avoid renderer hangs during normal sidebar navigation.
|
- Disabled Yomitan's embedded popup preview in the tray-launched settings window to avoid renderer hangs during normal sidebar navigation.
|
||||||
|
- Skipped heavy Yomitan settings startup preview, storage, dictionary, and Anki controllers when launched from SubMiner to avoid renderer hangs with large dictionary databases.
|
||||||
|
- Cached Yomitan settings dictionary metadata after explicit loads to avoid repeated large IndexedDB reads.
|
||||||
- Serialized copied Yomitan extension refreshes so startup cannot race itself and leave extension loading in an error state.
|
- Serialized copied Yomitan extension refreshes so startup cannot race itself and leave extension loading in an error state.
|
||||||
- Fixed tray-launched session help focus handling so the modal can close without mpv running.
|
- Fixed tray-launched session help focus handling so the modal can close without mpv running.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const DOCS_HOSTNAME = 'https://docs.subminer.moe';
|
const DOCS_HOSTNAME = 'https://docs.subminer.moe';
|
||||||
const PLAUSIBLE_PROXY_HOSTNAME = 'https://worker.subminer.moe';
|
const PLAUSIBLE_PROXY_HOSTNAME = 'https://worker.sudacode.com';
|
||||||
const PLAUSIBLE_SITE_SCRIPT_PATH = '/js/pa-h28Pn9ppgTJRmiSJlyPT6.js';
|
const PLAUSIBLE_SITE_SCRIPT_PATH = '/js/pa-h28Pn9ppgTJRmiSJlyPT6.js';
|
||||||
const PLAUSIBLE_ENDPOINT = `${PLAUSIBLE_PROXY_HOSTNAME}/api/event`;
|
const PLAUSIBLE_ENDPOINT = `${PLAUSIBLE_PROXY_HOSTNAME}/api/event`;
|
||||||
const PLAUSIBLE_INIT_SCRIPT = [
|
const PLAUSIBLE_INIT_SCRIPT = [
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const docsPackageContents = readFileSync(docsPackagePath, 'utf8');
|
|||||||
test('docs site loads the docs.subminer.moe Plausible script through the analytics proxy', () => {
|
test('docs site loads the docs.subminer.moe Plausible script through the analytics proxy', () => {
|
||||||
expect(docsConfigContents).toContain("const DOCS_HOSTNAME = 'https://docs.subminer.moe'");
|
expect(docsConfigContents).toContain("const DOCS_HOSTNAME = 'https://docs.subminer.moe'");
|
||||||
expect(docsConfigContents).toContain(
|
expect(docsConfigContents).toContain(
|
||||||
"const PLAUSIBLE_PROXY_HOSTNAME = 'https://worker.subminer.moe'",
|
"const PLAUSIBLE_PROXY_HOSTNAME = 'https://worker.sudacode.com'",
|
||||||
);
|
);
|
||||||
expect(docsConfigContents).toContain(
|
expect(docsConfigContents).toContain(
|
||||||
"const PLAUSIBLE_SITE_SCRIPT_PATH = '/js/pa-h28Pn9ppgTJRmiSJlyPT6.js'",
|
"const PLAUSIBLE_SITE_SCRIPT_PATH = '/js/pa-h28Pn9ppgTJRmiSJlyPT6.js'",
|
||||||
|
|||||||
@@ -358,89 +358,3 @@ test('runAppReadyRuntime loads Yomitan before auto-initializing overlay runtime'
|
|||||||
assert.ok(calls.indexOf('init-overlay') !== -1);
|
assert.ok(calls.indexOf('init-overlay') !== -1);
|
||||||
assert.ok(calls.indexOf('load-yomitan') < calls.indexOf('init-overlay'));
|
assert.ok(calls.indexOf('load-yomitan') < calls.indexOf('init-overlay'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('runAppReadyRuntime reuses guarded Yomitan loader after scheduling startup warmups', async () => {
|
|
||||||
const calls: string[] = [];
|
|
||||||
|
|
||||||
await runAppReadyRuntime({
|
|
||||||
ensureDefaultConfigBootstrap: () => {
|
|
||||||
calls.push('bootstrap');
|
|
||||||
},
|
|
||||||
loadSubtitlePosition: () => {
|
|
||||||
calls.push('load-subtitle-position');
|
|
||||||
},
|
|
||||||
resolveKeybindings: () => {
|
|
||||||
calls.push('resolve-keybindings');
|
|
||||||
},
|
|
||||||
createMpvClient: () => {
|
|
||||||
calls.push('create-mpv');
|
|
||||||
},
|
|
||||||
reloadConfig: () => {
|
|
||||||
calls.push('reload-config');
|
|
||||||
},
|
|
||||||
getResolvedConfig: () => ({
|
|
||||||
websocket: { enabled: false },
|
|
||||||
annotationWebsocket: { enabled: false },
|
|
||||||
texthooker: { launchAtStartup: false },
|
|
||||||
}),
|
|
||||||
getConfigWarnings: () => [],
|
|
||||||
logConfigWarning: () => {},
|
|
||||||
setLogLevel: () => {
|
|
||||||
calls.push('set-log-level');
|
|
||||||
},
|
|
||||||
initRuntimeOptionsManager: () => {
|
|
||||||
calls.push('init-runtime-options');
|
|
||||||
},
|
|
||||||
setSecondarySubMode: () => {
|
|
||||||
calls.push('set-secondary-sub-mode');
|
|
||||||
},
|
|
||||||
defaultSecondarySubMode: 'hover',
|
|
||||||
defaultWebsocketPort: 0,
|
|
||||||
defaultAnnotationWebsocketPort: 0,
|
|
||||||
defaultTexthookerPort: 0,
|
|
||||||
hasMpvWebsocketPlugin: () => false,
|
|
||||||
startSubtitleWebsocket: () => {},
|
|
||||||
startAnnotationWebsocket: () => {},
|
|
||||||
startTexthooker: () => {},
|
|
||||||
log: () => {
|
|
||||||
calls.push('log');
|
|
||||||
},
|
|
||||||
createMecabTokenizerAndCheck: async () => {},
|
|
||||||
createSubtitleTimingTracker: () => {
|
|
||||||
calls.push('subtitle-timing');
|
|
||||||
},
|
|
||||||
createImmersionTracker: () => {
|
|
||||||
calls.push('immersion');
|
|
||||||
},
|
|
||||||
startJellyfinRemoteSession: async () => {},
|
|
||||||
loadYomitanExtension: async () => {
|
|
||||||
calls.push('load-yomitan-direct');
|
|
||||||
},
|
|
||||||
ensureYomitanExtensionLoaded: async () => {
|
|
||||||
calls.push('load-yomitan-guarded');
|
|
||||||
},
|
|
||||||
handleFirstRunSetup: async () => {
|
|
||||||
calls.push('first-run');
|
|
||||||
},
|
|
||||||
prewarmSubtitleDictionaries: async () => {},
|
|
||||||
startBackgroundWarmups: () => {
|
|
||||||
calls.push('warmups');
|
|
||||||
},
|
|
||||||
texthookerOnlyMode: false,
|
|
||||||
shouldAutoInitializeOverlayRuntimeFromConfig: () => false,
|
|
||||||
setVisibleOverlayVisible: () => {
|
|
||||||
calls.push('visible-overlay');
|
|
||||||
},
|
|
||||||
initializeOverlayRuntime: () => {
|
|
||||||
calls.push('init-overlay');
|
|
||||||
},
|
|
||||||
handleInitialArgs: () => {
|
|
||||||
calls.push('handle-initial-args');
|
|
||||||
},
|
|
||||||
shouldUseMinimalStartup: () => false,
|
|
||||||
shouldSkipHeavyStartup: () => false,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(calls.includes('load-yomitan-direct'), false);
|
|
||||||
assert.equal(calls.includes('load-yomitan-guarded'), true);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -131,7 +131,6 @@ export interface AppReadyRuntimeDeps {
|
|||||||
createImmersionTracker?: () => void;
|
createImmersionTracker?: () => void;
|
||||||
startJellyfinRemoteSession?: () => Promise<void>;
|
startJellyfinRemoteSession?: () => Promise<void>;
|
||||||
loadYomitanExtension: () => Promise<void>;
|
loadYomitanExtension: () => Promise<void>;
|
||||||
ensureYomitanExtensionLoaded?: () => Promise<void>;
|
|
||||||
handleFirstRunSetup: () => Promise<void>;
|
handleFirstRunSetup: () => Promise<void>;
|
||||||
prewarmSubtitleDictionaries?: () => Promise<void>;
|
prewarmSubtitleDictionaries?: () => Promise<void>;
|
||||||
startBackgroundWarmups: () => void;
|
startBackgroundWarmups: () => void;
|
||||||
@@ -216,8 +215,6 @@ export function isAutoUpdateEnabledRuntime(
|
|||||||
export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<void> {
|
export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<void> {
|
||||||
const now = deps.now ?? (() => Date.now());
|
const now = deps.now ?? (() => Date.now());
|
||||||
const startupStartedAtMs = now();
|
const startupStartedAtMs = now();
|
||||||
const ensureYomitanExtensionReady =
|
|
||||||
deps.ensureYomitanExtensionLoaded ?? deps.loadYomitanExtension;
|
|
||||||
deps.ensureDefaultConfigBootstrap();
|
deps.ensureDefaultConfigBootstrap();
|
||||||
if (deps.shouldRunHeadlessInitialCommand?.()) {
|
if (deps.shouldRunHeadlessInitialCommand?.()) {
|
||||||
deps.reloadConfig();
|
deps.reloadConfig();
|
||||||
@@ -227,7 +224,7 @@ export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<voi
|
|||||||
} else {
|
} else {
|
||||||
deps.createMpvClient();
|
deps.createMpvClient();
|
||||||
deps.createSubtitleTimingTracker();
|
deps.createSubtitleTimingTracker();
|
||||||
await ensureYomitanExtensionReady();
|
await deps.loadYomitanExtension();
|
||||||
deps.initializeOverlayRuntime();
|
deps.initializeOverlayRuntime();
|
||||||
deps.handleInitialArgs();
|
deps.handleInitialArgs();
|
||||||
}
|
}
|
||||||
@@ -241,7 +238,7 @@ export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<voi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (deps.shouldSkipHeavyStartup?.()) {
|
if (deps.shouldSkipHeavyStartup?.()) {
|
||||||
await ensureYomitanExtensionReady();
|
await deps.loadYomitanExtension();
|
||||||
deps.reloadConfig();
|
deps.reloadConfig();
|
||||||
await deps.handleFirstRunSetup();
|
await deps.handleFirstRunSetup();
|
||||||
deps.handleInitialArgs();
|
deps.handleInitialArgs();
|
||||||
@@ -251,7 +248,7 @@ export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<voi
|
|||||||
deps.logDebug?.('App-ready critical path started.');
|
deps.logDebug?.('App-ready critical path started.');
|
||||||
|
|
||||||
if (deps.shouldSkipHeavyStartup?.()) {
|
if (deps.shouldSkipHeavyStartup?.()) {
|
||||||
await ensureYomitanExtensionReady();
|
await deps.loadYomitanExtension();
|
||||||
deps.reloadConfig();
|
deps.reloadConfig();
|
||||||
await deps.handleFirstRunSetup();
|
await deps.handleFirstRunSetup();
|
||||||
deps.handleInitialArgs();
|
deps.handleInitialArgs();
|
||||||
@@ -322,12 +319,12 @@ export async function runAppReadyRuntime(deps: AppReadyRuntimeDeps): Promise<voi
|
|||||||
if (deps.texthookerOnlyMode) {
|
if (deps.texthookerOnlyMode) {
|
||||||
deps.log('Texthooker-only mode enabled; skipping overlay window.');
|
deps.log('Texthooker-only mode enabled; skipping overlay window.');
|
||||||
} else if (deps.shouldAutoInitializeOverlayRuntimeFromConfig()) {
|
} else if (deps.shouldAutoInitializeOverlayRuntimeFromConfig()) {
|
||||||
await ensureYomitanExtensionReady();
|
await deps.loadYomitanExtension();
|
||||||
deps.setVisibleOverlayVisible(true);
|
deps.setVisibleOverlayVisible(true);
|
||||||
deps.initializeOverlayRuntime();
|
deps.initializeOverlayRuntime();
|
||||||
} else {
|
} else {
|
||||||
deps.log('Overlay runtime deferred: waiting for explicit overlay command.');
|
deps.log('Overlay runtime deferred: waiting for explicit overlay command.');
|
||||||
await ensureYomitanExtensionReady();
|
await deps.loadYomitanExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
await deps.handleFirstRunSetup();
|
await deps.handleFirstRunSetup();
|
||||||
|
|||||||
@@ -2,61 +2,27 @@ import assert from 'node:assert/strict';
|
|||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
buildYomitanSettingsCloseButtonScript,
|
|
||||||
buildYomitanSettingsWindowMenuTemplate,
|
|
||||||
buildYomitanSettingsUrl,
|
buildYomitanSettingsUrl,
|
||||||
configureYomitanSettingsWindowChrome,
|
configureYomitanSettingsWindowChrome,
|
||||||
destroyYomitanSettingsWindow,
|
destroyYomitanSettingsWindow,
|
||||||
showYomitanSettingsWindow,
|
showYomitanSettingsWindow,
|
||||||
} from './yomitan-settings';
|
} from './yomitan-settings';
|
||||||
|
|
||||||
test('yomitan settings window uses a close-only menu without app quit', () => {
|
test('yomitan settings window removes default app menu quit action', () => {
|
||||||
const calls: string[] = [];
|
const calls: string[] = [];
|
||||||
|
|
||||||
configureYomitanSettingsWindowChrome({
|
configureYomitanSettingsWindowChrome({
|
||||||
isDestroyed: () => false,
|
|
||||||
close: () => calls.push('close'),
|
|
||||||
setAutoHideMenuBar: (hide: boolean) => calls.push(`auto-hide:${hide}`),
|
setAutoHideMenuBar: (hide: boolean) => calls.push(`auto-hide:${hide}`),
|
||||||
setMenu: (menu: unknown) => calls.push(`menu:${menu === null ? 'null' : 'custom'}`),
|
setMenu: (menu: unknown) => calls.push(`menu:${menu === null ? 'null' : 'custom'}`),
|
||||||
} as never, (template) => {
|
|
||||||
calls.push(`menu-label:${template[0]?.label ?? ''}`);
|
|
||||||
const submenu = template[0]?.submenu;
|
|
||||||
assert.ok(Array.isArray(submenu));
|
|
||||||
const closeItem = submenu[0];
|
|
||||||
assert.equal(closeItem?.label, 'Close');
|
|
||||||
assert.notEqual(closeItem?.role, 'quit');
|
|
||||||
closeItem?.click?.({} as never, {} as never, {} as never);
|
|
||||||
return { id: 'settings-menu' } as never;
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.deepEqual(calls, ['auto-hide:false', 'menu-label:File', 'close', 'menu:custom']);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('yomitan settings close menu skips destroyed windows', () => {
|
|
||||||
const calls: string[] = [];
|
|
||||||
const template = buildYomitanSettingsWindowMenuTemplate({
|
|
||||||
isDestroyed: () => true,
|
|
||||||
close: () => calls.push('close'),
|
|
||||||
} as never);
|
} as never);
|
||||||
const submenu = template[0]?.submenu;
|
|
||||||
assert.ok(Array.isArray(submenu));
|
|
||||||
submenu[0]?.click?.({} as never, {} as never, {} as never);
|
|
||||||
assert.deepEqual(calls, []);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('yomitan settings close button script installs an idempotent in-page close control', () => {
|
assert.deepEqual(calls, ['auto-hide:true', 'menu:null']);
|
||||||
const script = buildYomitanSettingsCloseButtonScript();
|
|
||||||
|
|
||||||
assert.match(script, /subminer-yomitan-settings-close/);
|
|
||||||
assert.match(script, /aria-label', 'Close Yomitan settings'/);
|
|
||||||
assert.match(script, /window\.close\(\)/);
|
|
||||||
assert.match(script, /getElementById\(buttonId\)/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('yomitan settings URL disables the embedded popup preview', () => {
|
test('yomitan settings URL disables the embedded popup preview', () => {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
buildYomitanSettingsUrl('abc123'),
|
buildYomitanSettingsUrl('abc123'),
|
||||||
'chrome-extension://abc123/settings.html?popup-preview=false',
|
'chrome-extension://abc123/settings.html?popup-preview=false&subminer-settings-safe=true',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import electron from 'electron';
|
import electron from 'electron';
|
||||||
import type { BrowserWindow, Extension, Menu, MenuItemConstructorOptions, Session } from 'electron';
|
import type { BrowserWindow, Extension, Session } from 'electron';
|
||||||
import { createLogger } from '../../logger';
|
import { createLogger } from '../../logger';
|
||||||
|
|
||||||
const { BrowserWindow: ElectronBrowserWindow, Menu: ElectronMenu, session } = electron;
|
const { BrowserWindow: ElectronBrowserWindow, session } = electron;
|
||||||
const logger = createLogger('main:yomitan-settings');
|
const logger = createLogger('main:yomitan-settings');
|
||||||
|
|
||||||
export interface OpenYomitanSettingsWindowOptions {
|
export interface OpenYomitanSettingsWindowOptions {
|
||||||
@@ -13,107 +13,15 @@ export interface OpenYomitanSettingsWindowOptions {
|
|||||||
onWindowClosed?: () => void;
|
onWindowClosed?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type YomitanSettingsWindowMenuOwner = Pick<BrowserWindow, 'close' | 'isDestroyed'>;
|
|
||||||
|
|
||||||
export function buildYomitanSettingsWindowMenuTemplate(
|
|
||||||
settingsWindow: YomitanSettingsWindowMenuOwner,
|
|
||||||
): MenuItemConstructorOptions[] {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
label: 'File',
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: 'Close',
|
|
||||||
accelerator: process.platform === 'darwin' ? 'Command+W' : 'Ctrl+W',
|
|
||||||
click: () => {
|
|
||||||
if (!settingsWindow.isDestroyed()) {
|
|
||||||
settingsWindow.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildYomitanSettingsCloseButtonScript(): string {
|
|
||||||
return `
|
|
||||||
(() => {
|
|
||||||
const buttonId = 'subminer-yomitan-settings-close';
|
|
||||||
const styleId = 'subminer-yomitan-settings-close-style';
|
|
||||||
if (document.getElementById(buttonId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!document.getElementById(styleId)) {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.id = styleId;
|
|
||||||
style.textContent = \`
|
|
||||||
#\${buttonId} {
|
|
||||||
position: fixed;
|
|
||||||
top: 10px;
|
|
||||||
left: 10px;
|
|
||||||
z-index: 2147483647;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
padding: 0;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.28);
|
|
||||||
border-radius: 4px;
|
|
||||||
background: rgba(24, 24, 24, 0.92);
|
|
||||||
color: #f2f2f2;
|
|
||||||
font: 22px/1 system-ui, sans-serif;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
#\${buttonId}:hover {
|
|
||||||
background: rgba(54, 54, 54, 0.96);
|
|
||||||
border-color: rgba(255, 255, 255, 0.5);
|
|
||||||
}
|
|
||||||
#\${buttonId}:focus-visible {
|
|
||||||
outline: 2px solid #8ab4f8;
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
\`;
|
|
||||||
document.head.appendChild(style);
|
|
||||||
}
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.id = buttonId;
|
|
||||||
button.type = 'button';
|
|
||||||
button.title = 'Close';
|
|
||||||
button.setAttribute('aria-label', 'Close Yomitan settings');
|
|
||||||
button.textContent = '\\u00d7';
|
|
||||||
button.addEventListener('click', () => {
|
|
||||||
window.close();
|
|
||||||
});
|
|
||||||
document.body.appendChild(button);
|
|
||||||
})();
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function installYomitanSettingsCloseButton(
|
|
||||||
settingsWindow: Pick<BrowserWindow, 'isDestroyed' | 'webContents'>,
|
|
||||||
): void {
|
|
||||||
if (settingsWindow.isDestroyed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
settingsWindow.webContents
|
|
||||||
.executeJavaScript(buildYomitanSettingsCloseButtonScript())
|
|
||||||
.catch((error: Error) => {
|
|
||||||
logger.warn('Failed to install Yomitan settings close button:', error.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function configureYomitanSettingsWindowChrome(
|
export function configureYomitanSettingsWindowChrome(
|
||||||
settingsWindow: Pick<BrowserWindow, 'close' | 'isDestroyed' | 'setAutoHideMenuBar' | 'setMenu'>,
|
settingsWindow: Pick<BrowserWindow, 'setAutoHideMenuBar' | 'setMenu'>,
|
||||||
buildMenu: (template: MenuItemConstructorOptions[]) => Menu = (template) =>
|
|
||||||
ElectronMenu.buildFromTemplate(template),
|
|
||||||
): void {
|
): void {
|
||||||
settingsWindow.setAutoHideMenuBar(false);
|
settingsWindow.setAutoHideMenuBar(true);
|
||||||
settingsWindow.setMenu(buildMenu(buildYomitanSettingsWindowMenuTemplate(settingsWindow)));
|
settingsWindow.setMenu(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildYomitanSettingsUrl(extensionId: string): string {
|
export function buildYomitanSettingsUrl(extensionId: string): string {
|
||||||
return `chrome-extension://${extensionId}/settings.html?popup-preview=false`;
|
return `chrome-extension://${extensionId}/settings.html?popup-preview=false&subminer-settings-safe=true`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showYomitanSettingsWindow(settingsWindow: BrowserWindow): void {
|
export function showYomitanSettingsWindow(settingsWindow: BrowserWindow): void {
|
||||||
@@ -200,7 +108,6 @@ export function openYomitanSettingsWindow(options: OpenYomitanSettingsWindowOpti
|
|||||||
|
|
||||||
settingsWindow.webContents.on('did-finish-load', () => {
|
settingsWindow.webContents.on('did-finish-load', () => {
|
||||||
logger.info('Settings page loaded successfully');
|
logger.info('Settings page loaded successfully');
|
||||||
installYomitanSettingsCloseButton(settingsWindow);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -3854,9 +3854,6 @@ const { appReadyRuntimeRunner } = composeAppReadyRuntime({
|
|||||||
loadYomitanExtension: async () => {
|
loadYomitanExtension: async () => {
|
||||||
await loadYomitanExtension();
|
await loadYomitanExtension();
|
||||||
},
|
},
|
||||||
ensureYomitanExtensionLoaded: async () => {
|
|
||||||
await ensureYomitanExtensionLoaded();
|
|
||||||
},
|
|
||||||
handleFirstRunSetup: async () => {
|
handleFirstRunSetup: async () => {
|
||||||
const snapshot = await firstRunSetupService.ensureSetupStateInitialized();
|
const snapshot = await firstRunSetupService.ensureSetupStateInitialized();
|
||||||
appState.firstRunSetupCompleted = snapshot.state.status === 'completed';
|
appState.firstRunSetupCompleted = snapshot.state.status === 'completed';
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ export interface AppReadyRuntimeDepsFactoryInput {
|
|||||||
createImmersionTracker?: AppReadyRuntimeDeps['createImmersionTracker'];
|
createImmersionTracker?: AppReadyRuntimeDeps['createImmersionTracker'];
|
||||||
startJellyfinRemoteSession?: AppReadyRuntimeDeps['startJellyfinRemoteSession'];
|
startJellyfinRemoteSession?: AppReadyRuntimeDeps['startJellyfinRemoteSession'];
|
||||||
loadYomitanExtension: AppReadyRuntimeDeps['loadYomitanExtension'];
|
loadYomitanExtension: AppReadyRuntimeDeps['loadYomitanExtension'];
|
||||||
ensureYomitanExtensionLoaded?: AppReadyRuntimeDeps['ensureYomitanExtensionLoaded'];
|
|
||||||
handleFirstRunSetup: AppReadyRuntimeDeps['handleFirstRunSetup'];
|
handleFirstRunSetup: AppReadyRuntimeDeps['handleFirstRunSetup'];
|
||||||
prewarmSubtitleDictionaries?: AppReadyRuntimeDeps['prewarmSubtitleDictionaries'];
|
prewarmSubtitleDictionaries?: AppReadyRuntimeDeps['prewarmSubtitleDictionaries'];
|
||||||
startBackgroundWarmups: AppReadyRuntimeDeps['startBackgroundWarmups'];
|
startBackgroundWarmups: AppReadyRuntimeDeps['startBackgroundWarmups'];
|
||||||
@@ -110,7 +109,6 @@ export function createAppReadyRuntimeDeps(
|
|||||||
createImmersionTracker: params.createImmersionTracker,
|
createImmersionTracker: params.createImmersionTracker,
|
||||||
startJellyfinRemoteSession: params.startJellyfinRemoteSession,
|
startJellyfinRemoteSession: params.startJellyfinRemoteSession,
|
||||||
loadYomitanExtension: params.loadYomitanExtension,
|
loadYomitanExtension: params.loadYomitanExtension,
|
||||||
ensureYomitanExtensionLoaded: params.ensureYomitanExtensionLoaded,
|
|
||||||
handleFirstRunSetup: params.handleFirstRunSetup,
|
handleFirstRunSetup: params.handleFirstRunSetup,
|
||||||
prewarmSubtitleDictionaries: params.prewarmSubtitleDictionaries,
|
prewarmSubtitleDictionaries: params.prewarmSubtitleDictionaries,
|
||||||
startBackgroundWarmups: params.startBackgroundWarmups,
|
startBackgroundWarmups: params.startBackgroundWarmups,
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ test('app-ready main deps builder returns mapped app-ready runtime deps', async
|
|||||||
loadYomitanExtension: async () => {
|
loadYomitanExtension: async () => {
|
||||||
calls.push('load-yomitan');
|
calls.push('load-yomitan');
|
||||||
},
|
},
|
||||||
ensureYomitanExtensionLoaded: async () => {
|
|
||||||
calls.push('ensure-yomitan');
|
|
||||||
},
|
|
||||||
handleFirstRunSetup: async () => {
|
handleFirstRunSetup: async () => {
|
||||||
calls.push('handle-first-run-setup');
|
calls.push('handle-first-run-setup');
|
||||||
},
|
},
|
||||||
@@ -70,7 +67,6 @@ test('app-ready main deps builder returns mapped app-ready runtime deps', async
|
|||||||
onReady.createMpvClient();
|
onReady.createMpvClient();
|
||||||
await onReady.createMecabTokenizerAndCheck();
|
await onReady.createMecabTokenizerAndCheck();
|
||||||
await onReady.loadYomitanExtension();
|
await onReady.loadYomitanExtension();
|
||||||
await onReady.ensureYomitanExtensionLoaded?.();
|
|
||||||
await onReady.handleFirstRunSetup();
|
await onReady.handleFirstRunSetup();
|
||||||
await onReady.prewarmSubtitleDictionaries?.();
|
await onReady.prewarmSubtitleDictionaries?.();
|
||||||
onReady.startBackgroundWarmups();
|
onReady.startBackgroundWarmups();
|
||||||
@@ -83,7 +79,6 @@ test('app-ready main deps builder returns mapped app-ready runtime deps', async
|
|||||||
'create-mpv-client',
|
'create-mpv-client',
|
||||||
'create-mecab',
|
'create-mecab',
|
||||||
'load-yomitan',
|
'load-yomitan',
|
||||||
'ensure-yomitan',
|
|
||||||
'handle-first-run-setup',
|
'handle-first-run-setup',
|
||||||
'prewarm-dicts',
|
'prewarm-dicts',
|
||||||
'start-warmups',
|
'start-warmups',
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ export function createBuildAppReadyRuntimeMainDepsHandler(deps: AppReadyRuntimeD
|
|||||||
createImmersionTracker: deps.createImmersionTracker,
|
createImmersionTracker: deps.createImmersionTracker,
|
||||||
startJellyfinRemoteSession: deps.startJellyfinRemoteSession,
|
startJellyfinRemoteSession: deps.startJellyfinRemoteSession,
|
||||||
loadYomitanExtension: deps.loadYomitanExtension,
|
loadYomitanExtension: deps.loadYomitanExtension,
|
||||||
ensureYomitanExtensionLoaded: deps.ensureYomitanExtensionLoaded,
|
|
||||||
handleFirstRunSetup: deps.handleFirstRunSetup,
|
handleFirstRunSetup: deps.handleFirstRunSetup,
|
||||||
prewarmSubtitleDictionaries: deps.prewarmSubtitleDictionaries,
|
prewarmSubtitleDictionaries: deps.prewarmSubtitleDictionaries,
|
||||||
startBackgroundWarmups: deps.startBackgroundWarmups,
|
startBackgroundWarmups: deps.startBackgroundWarmups,
|
||||||
|
|||||||
@@ -575,6 +575,7 @@ test('numeric selection ignores non-digit keys instead of falling through to oth
|
|||||||
testGlobals.commandEvents.some((event) => event.type === 'forwardKeyDown'),
|
testGlobals.commandEvents.some((event) => event.type === 'forwardKeyDown'),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
testGlobals.dispatchKeydown({ key: 'Escape', code: 'Escape' });
|
||||||
} finally {
|
} finally {
|
||||||
testGlobals.restore();
|
testGlobals.restore();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user