fix: restore controller modal shortcut opens

This commit is contained in:
2026-04-11 11:19:17 -07:00
parent ef41121774
commit f7fbffd4f5
4 changed files with 64 additions and 5 deletions

View File

@@ -4,3 +4,4 @@ area: overlay
- Added configurable overlay shortcuts for session help, controller select, and controller debug actions. - Added configurable overlay shortcuts for session help, controller select, and controller debug actions.
- Added mpv/plugin and CLI routing for session help, controller utilities, and subtitle sidebar toggling through the shared session-action path. - Added mpv/plugin and CLI routing for session help, controller utilities, and subtitle sidebar toggling through the shared session-action path.
- Improved dedicated overlay modal retry and focus handling for runtime options, Jimaku, session help, controller tools, and the playlist browser. - Improved dedicated overlay modal retry and focus handling for runtime options, Jimaku, session help, controller tools, and the playlist browser.
- Fixed controller configuration and controller debug shortcut opens so configured bindings bring up their modals again instead of tripping renderer recovery.

View File

@@ -326,6 +326,8 @@ function createKeyboardHandlerHarness() {
const testGlobals = installKeyboardTestGlobals(); const testGlobals = installKeyboardTestGlobals();
const subtitleRootClassList = createClassList(); const subtitleRootClassList = createClassList();
let controllerSelectKeydownCount = 0; let controllerSelectKeydownCount = 0;
let openControllerSelectCount = 0;
let openControllerDebugCount = 0;
let playlistBrowserKeydownCount = 0; let playlistBrowserKeydownCount = 0;
const createWordNode = (left: number) => ({ const createWordNode = (left: number) => ({
@@ -373,6 +375,12 @@ function createKeyboardHandlerHarness() {
}, },
handleSessionHelpKeydown: () => false, handleSessionHelpKeydown: () => false,
openSessionHelpModal: () => {}, openSessionHelpModal: () => {},
openControllerSelectModal: () => {
openControllerSelectCount += 1;
},
openControllerDebugModal: () => {
openControllerDebugCount += 1;
},
appendClipboardVideoToQueue: () => {}, appendClipboardVideoToQueue: () => {},
getPlaybackPaused: () => testGlobals.getPlaybackPaused(), getPlaybackPaused: () => testGlobals.getPlaybackPaused(),
}); });
@@ -382,6 +390,8 @@ function createKeyboardHandlerHarness() {
handlers, handlers,
testGlobals, testGlobals,
controllerSelectKeydownCount: () => controllerSelectKeydownCount, controllerSelectKeydownCount: () => controllerSelectKeydownCount,
openControllerSelectCount: () => openControllerSelectCount,
openControllerDebugCount: () => openControllerDebugCount,
playlistBrowserKeydownCount: () => playlistBrowserKeydownCount, playlistBrowserKeydownCount: () => playlistBrowserKeydownCount,
setWordCount: (count: number) => { setWordCount: (count: number) => {
wordNodes = Array.from({ length: count }, (_, index) => createWordNode(10 + index * 70)); wordNodes = Array.from({ length: count }, (_, index) => createWordNode(10 + index * 70));
@@ -735,8 +745,36 @@ test('keyboard mode: controller helpers dispatch popup audio play/cycle and scro
} }
}); });
test('keyboard mode: configured controller debug binding dispatches session action', async () => { test('keyboard mode: configured controller select binding opens locally without dispatching a session action', async () => {
const { testGlobals, handlers } = createKeyboardHandlerHarness(); const { testGlobals, handlers, openControllerSelectCount } = createKeyboardHandlerHarness();
try {
await handlers.setupMpvInputForwarding();
handlers.updateSessionBindings([
{
sourcePath: 'shortcuts.openControllerSelect',
originalKey: 'Alt+D',
key: { code: 'KeyD', modifiers: ['alt'] },
actionType: 'session-action',
actionId: 'openControllerSelect',
},
] as never);
testGlobals.dispatchKeydown({
key: 'd',
code: 'KeyD',
altKey: true,
});
assert.equal(openControllerSelectCount(), 1);
assert.deepEqual(testGlobals.sessionActions, []);
} finally {
testGlobals.restore();
}
});
test('keyboard mode: configured controller debug binding opens locally without dispatching a session action', async () => {
const { testGlobals, handlers, openControllerDebugCount } = createKeyboardHandlerHarness();
try { try {
await handlers.setupMpvInputForwarding(); await handlers.setupMpvInputForwarding();
@@ -757,14 +795,15 @@ test('keyboard mode: configured controller debug binding dispatches session acti
shiftKey: true, shiftKey: true,
}); });
assert.deepEqual(testGlobals.sessionActions, [{ actionId: 'openControllerDebug', payload: undefined }]); assert.equal(openControllerDebugCount(), 1);
assert.deepEqual(testGlobals.sessionActions, []);
} finally { } finally {
testGlobals.restore(); testGlobals.restore();
} }
}); });
test('keyboard mode: configured controller debug binding is not swallowed while popup is visible', async () => { test('keyboard mode: configured controller debug binding is not swallowed while popup is visible', async () => {
const { ctx, testGlobals, handlers } = createKeyboardHandlerHarness(); const { ctx, testGlobals, handlers, openControllerDebugCount } = createKeyboardHandlerHarness();
try { try {
await handlers.setupMpvInputForwarding(); await handlers.setupMpvInputForwarding();
@@ -787,7 +826,8 @@ test('keyboard mode: configured controller debug binding is not swallowed while
shiftKey: true, shiftKey: true,
}); });
assert.deepEqual(testGlobals.sessionActions, [{ actionId: 'openControllerDebug', payload: undefined }]); assert.equal(openControllerDebugCount(), 1);
assert.deepEqual(testGlobals.sessionActions, []);
} finally { } finally {
testGlobals.restore(); testGlobals.restore();
} }

View File

@@ -25,6 +25,8 @@ export function createKeyboardHandlers(
fallbackUsed: boolean; fallbackUsed: boolean;
fallbackUnavailable: boolean; fallbackUnavailable: boolean;
}) => void; }) => void;
openControllerSelectModal?: () => void;
openControllerDebugModal?: () => void;
appendClipboardVideoToQueue: () => void; appendClipboardVideoToQueue: () => void;
getPlaybackPaused: () => Promise<boolean | null>; getPlaybackPaused: () => Promise<boolean | null>;
toggleSubtitleSidebarModal?: () => void; toggleSubtitleSidebarModal?: () => void;
@@ -182,6 +184,16 @@ export function createKeyboardHandlers(
return; return;
} }
if (binding.actionType === 'session-action' && binding.actionId === 'openControllerSelect') {
options.openControllerSelectModal?.();
return;
}
if (binding.actionType === 'session-action' && binding.actionId === 'openControllerDebug') {
options.openControllerDebugModal?.();
return;
}
if (binding.actionType === 'mpv-command') { if (binding.actionType === 'mpv-command') {
dispatchConfiguredMpvCommand(binding.command); dispatchConfiguredMpvCommand(binding.command);
return; return;

View File

@@ -174,6 +174,12 @@ const keyboardHandlers = createKeyboardHandlers(ctx, {
handleControllerDebugKeydown: controllerDebugModal.handleControllerDebugKeydown, handleControllerDebugKeydown: controllerDebugModal.handleControllerDebugKeydown,
handleSessionHelpKeydown: sessionHelpModal.handleSessionHelpKeydown, handleSessionHelpKeydown: sessionHelpModal.handleSessionHelpKeydown,
openSessionHelpModal: sessionHelpModal.openSessionHelpModal, openSessionHelpModal: sessionHelpModal.openSessionHelpModal,
openControllerSelectModal: () => {
controllerSelectModal.openControllerSelectModal();
},
openControllerDebugModal: () => {
controllerDebugModal.openControllerDebugModal();
},
appendClipboardVideoToQueue: () => { appendClipboardVideoToQueue: () => {
void window.electronAPI.appendClipboardVideoToQueue(); void window.electronAPI.appendClipboardVideoToQueue();
}, },