feat(overlay): add optional subtitle selection modal (#265)

This commit is contained in:
sudacode authored and GitHub committed 2026-09-22 18:30:26 -07:00
1 parent a7a302bdd0
commit b0fb39a8f5
54 files changed
+1397 -52

No files matched your search

+36 -1
View File
@@ -15,6 +15,7 @@ export function createKeyboardHandlers(
handleRuntimeOptionsKeydown: (e: KeyboardEvent) => boolean;
handleCharacterDictionaryKeydown: (e: KeyboardEvent) => boolean;
handleSubsyncKeydown: (e: KeyboardEvent) => boolean;
handleSubtitleSelectionKeydown?: (e: KeyboardEvent) => boolean;
handleSubtitleGenerationKeydown?: (e: KeyboardEvent) => boolean;
handleKikuKeydown: (e: KeyboardEvent) => boolean;
handleJimakuKeydown: (e: KeyboardEvent) => boolean;
@@ -133,7 +134,10 @@ export function createKeyboardHandlers(
updateConfiguredShortcuts(shortcuts, statsToggleKey, markWatchedKey);
}
let pendingSequence: { prefix: string; expires: number } | null = null;
function updateSessionBindings(bindings: CompiledSessionBinding[]): void {
pendingSequence = null;
ctx.state.sessionBindings = bindings;
ctx.state.sessionBindingMap = new Map(
bindings.map((binding) => [keyEventToStringFromBinding(binding), binding]),
@@ -1049,7 +1053,10 @@ export function createKeyboardHandlers(
window.addEventListener('focus', () => {
void importedMpvBindings.refresh();
});
window.addEventListener('blur', importedMpvBindings.releaseAll);
window.addEventListener('blur', () => {
pendingSequence = null;
importedMpvBindings.releaseAll();
});
window.addEventListener('beforeunload', () => {
clearTimeout(lateScriptRefresh);
importedMpvBindings.dispose();
@@ -1103,6 +1110,13 @@ export function createKeyboardHandlers(
);
document.addEventListener('keydown', (e: KeyboardEvent) => {
const sequence = pendingSequence;
pendingSequence = null;
if (ctx.state.subtitleSelectionModalOpen) {
pendingSequence = null;
options.handleSubtitleSelectionKeydown?.(e);
return;
}
if (ctx.state.subtitleGenerationModalOpen) {
options.handleSubtitleGenerationKeydown?.(e);
return;
@@ -1187,6 +1201,7 @@ export function createKeyboardHandlers(
}
if (isTextEntryTarget(e.target)) {
pendingSequence = null;
return;
}
@@ -1194,6 +1209,16 @@ export function createKeyboardHandlers(
return;
}
const sequenceKey = keyEventToString(e);
if (sequence && !ctx.state.chordPending && Date.now() <= sequence.expires && !e.repeat) {
const binding = ctx.state.sessionBindingMap.get(`${sequence.prefix}-${sequenceKey}`);
if (binding) {
e.preventDefault();
dispatchSessionBinding(binding);
return;
}
}
if (isStatsOverlayToggle(e)) {
e.preventDefault();
window.electronAPI.toggleStatsOverlay();
@@ -1276,6 +1301,16 @@ export function createKeyboardHandlers(
dispatchSessionBinding(binding);
return;
}
if (
!e.repeat &&
ctx.state.sessionBindings.some((binding) =>
keyEventToStringFromBinding(binding).startsWith(`${sequenceKey}-`),
)
) {
pendingSequence = { prefix: sequenceKey, expires: Date.now() + 1000 };
e.preventDefault();
return;
}
if (
keyboardConfigLoaded &&
!ctx.state.playlistBrowserModalOpen &&