mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 12:55:16 -07:00
feat: add auto update support
This commit is contained in:
@@ -2,7 +2,12 @@ import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { SPECIAL_COMMANDS } from '../../config/definitions';
|
||||
import { describeSessionHelpCommand, formatSessionHelpKeybinding } from './session-help.js';
|
||||
import { createRendererState } from '../state.js';
|
||||
import {
|
||||
createSessionHelpModal,
|
||||
describeSessionHelpCommand,
|
||||
formatSessionHelpKeybinding,
|
||||
} from './session-help.js';
|
||||
|
||||
test('session help describes sub-seek commands as subtitle-line navigation', () => {
|
||||
assert.equal(describeSessionHelpCommand(['sub-seek', 1]), 'Jump to next subtitle');
|
||||
@@ -24,3 +29,154 @@ test('session help formats bracket keybindings as physical keys', () => {
|
||||
assert.equal(formatSessionHelpKeybinding('Shift+BracketRight'), 'Shift + ]');
|
||||
assert.equal(formatSessionHelpKeybinding('Shift+BracketLeft'), 'Shift + [');
|
||||
});
|
||||
|
||||
function createClassList(initialTokens: string[] = []) {
|
||||
const tokens = new Set(initialTokens);
|
||||
return {
|
||||
add: (...entries: string[]) => {
|
||||
for (const entry of entries) tokens.add(entry);
|
||||
},
|
||||
remove: (...entries: string[]) => {
|
||||
for (const entry of entries) tokens.delete(entry);
|
||||
},
|
||||
contains: (entry: string) => tokens.has(entry),
|
||||
};
|
||||
}
|
||||
|
||||
function createElementStub() {
|
||||
return {
|
||||
value: '',
|
||||
textContent: '',
|
||||
innerHTML: '',
|
||||
classList: createClassList(['hidden']),
|
||||
setAttribute: () => {},
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {},
|
||||
querySelectorAll: () => [],
|
||||
focus: () => {},
|
||||
select: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
test('modal-layer session help does not focus hidden main overlay and still closes', async () => {
|
||||
const globals = globalThis as typeof globalThis & {
|
||||
window?: unknown;
|
||||
document?: unknown;
|
||||
HTMLElement?: unknown;
|
||||
Element?: unknown;
|
||||
};
|
||||
const previousWindow = globals.window;
|
||||
const previousDocument = globals.document;
|
||||
const previousHTMLElement = globals.HTMLElement;
|
||||
const previousElement = globals.Element;
|
||||
const focusMainWindowCalls: number[] = [];
|
||||
const notifications: string[] = [];
|
||||
|
||||
try {
|
||||
class TestElement {}
|
||||
Object.defineProperty(globalThis, 'HTMLElement', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: TestElement,
|
||||
});
|
||||
Object.defineProperty(globalThis, 'Element', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: TestElement,
|
||||
});
|
||||
Object.defineProperty(globalThis, 'window', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: {
|
||||
electronAPI: {
|
||||
focusMainWindow: async () => {
|
||||
focusMainWindowCalls.push(1);
|
||||
},
|
||||
setIgnoreMouseEvents: () => {},
|
||||
notifyOverlayModalClosed: (modal: string) => {
|
||||
notifications.push(modal);
|
||||
},
|
||||
getKeybindings: async () => {
|
||||
throw new Error('mpv unavailable');
|
||||
},
|
||||
getSubtitleStyle: async () => ({}),
|
||||
getConfiguredShortcuts: async () => ({}),
|
||||
},
|
||||
focus: () => {},
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {},
|
||||
setTimeout: (callback: () => void) => setTimeout(callback, 0),
|
||||
},
|
||||
});
|
||||
Object.defineProperty(globalThis, 'document', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: {
|
||||
activeElement: null,
|
||||
addEventListener: () => {},
|
||||
removeEventListener: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const state = createRendererState();
|
||||
const modal = createSessionHelpModal(
|
||||
{
|
||||
state,
|
||||
platform: {
|
||||
overlayLayer: 'modal',
|
||||
isModalLayer: true,
|
||||
isLinuxPlatform: false,
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
shouldToggleMouseIgnore: false,
|
||||
},
|
||||
dom: {
|
||||
overlay: createElementStub(),
|
||||
sessionHelpModal: createElementStub(),
|
||||
sessionHelpFilter: createElementStub(),
|
||||
sessionHelpContent: createElementStub(),
|
||||
sessionHelpClose: createElementStub(),
|
||||
sessionHelpShortcut: createElementStub(),
|
||||
sessionHelpWarning: createElementStub(),
|
||||
sessionHelpStatus: createElementStub(),
|
||||
},
|
||||
} as never,
|
||||
{
|
||||
modalStateReader: { isAnyModalOpen: () => false },
|
||||
syncSettingsModalSubtitleSuppression: () => {},
|
||||
},
|
||||
);
|
||||
|
||||
modal.openSessionHelpModal({
|
||||
bindingKey: 'KeyH',
|
||||
fallbackUsed: false,
|
||||
fallbackUnavailable: false,
|
||||
});
|
||||
modal.closeSessionHelpModal();
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
assert.deepEqual(focusMainWindowCalls, []);
|
||||
assert.deepEqual(notifications, ['session-help']);
|
||||
} finally {
|
||||
Object.defineProperty(globalThis, 'window', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: previousWindow,
|
||||
});
|
||||
Object.defineProperty(globalThis, 'document', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: previousDocument,
|
||||
});
|
||||
Object.defineProperty(globalThis, 'HTMLElement', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: previousHTMLElement,
|
||||
});
|
||||
Object.defineProperty(globalThis, 'Element', {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: previousElement,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -450,7 +450,9 @@ export function createSessionHelpModal(
|
||||
}
|
||||
|
||||
function focusFallbackTarget(): boolean {
|
||||
void window.electronAPI.focusMainWindow();
|
||||
if (!ctx.platform.isModalLayer) {
|
||||
void window.electronAPI.focusMainWindow();
|
||||
}
|
||||
const items = getItems();
|
||||
const firstItem = items.find((item) => item.offsetParent !== null);
|
||||
if (firstItem) {
|
||||
@@ -526,7 +528,9 @@ export function createSessionHelpModal(
|
||||
}
|
||||
|
||||
function requestOverlayFocus(): void {
|
||||
void window.electronAPI.focusMainWindow();
|
||||
if (!ctx.platform.isModalLayer) {
|
||||
void window.electronAPI.focusMainWindow();
|
||||
}
|
||||
}
|
||||
|
||||
function addPointerFocusListener(): void {
|
||||
|
||||
Reference in New Issue
Block a user