fix(renderer): keep controller input active with sidebar open

This commit is contained in:
2026-03-24 00:23:00 -07:00
parent 5feed360ca
commit 6f56a0bcf6
4 changed files with 123 additions and 1 deletions

View File

@@ -0,0 +1,36 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { isControllerInteractionBlocked } from './controller-interaction-blocking.js';
test('subtitle sidebar stays controller-passive while other modals block controller input', () => {
assert.equal(
isControllerInteractionBlocked({
controllerSelectModalOpen: false,
controllerDebugModalOpen: false,
jimakuModalOpen: false,
kikuModalOpen: false,
runtimeOptionsModalOpen: false,
subsyncModalOpen: false,
youtubePickerModalOpen: false,
sessionHelpModalOpen: false,
subtitleSidebarModalOpen: true,
}),
false,
);
assert.equal(
isControllerInteractionBlocked({
controllerSelectModalOpen: false,
controllerDebugModalOpen: false,
jimakuModalOpen: false,
kikuModalOpen: false,
runtimeOptionsModalOpen: true,
subsyncModalOpen: false,
youtubePickerModalOpen: false,
sessionHelpModalOpen: false,
subtitleSidebarModalOpen: false,
}),
true,
);
});

View File

@@ -0,0 +1,24 @@
type ControllerInteractionModalState = {
controllerSelectModalOpen: boolean;
controllerDebugModalOpen: boolean;
jimakuModalOpen: boolean;
kikuModalOpen: boolean;
runtimeOptionsModalOpen: boolean;
subsyncModalOpen: boolean;
youtubePickerModalOpen: boolean;
sessionHelpModalOpen: boolean;
subtitleSidebarModalOpen: boolean;
};
export function isControllerInteractionBlocked(state: ControllerInteractionModalState): boolean {
return (
state.controllerSelectModalOpen ||
state.controllerDebugModalOpen ||
state.jimakuModalOpen ||
state.kikuModalOpen ||
state.runtimeOptionsModalOpen ||
state.subsyncModalOpen ||
state.youtubePickerModalOpen ||
state.sessionHelpModalOpen
);
}

View File

@@ -35,6 +35,7 @@ import { createJimakuModal } from './modals/jimaku.js';
import { createKikuModal } from './modals/kiku.js';
import { createSessionHelpModal } from './modals/session-help.js';
import { createSubtitleSidebarModal } from './modals/subtitle-sidebar.js';
import { isControllerInteractionBlocked } from './controller-interaction-blocking.js';
import { createRuntimeOptionsModal } from './modals/runtime-options.js';
import { createSubsyncModal } from './modals/subsync.js';
import { createYoutubeTrackPickerModal } from './modals/youtube-track-picker.js';
@@ -88,6 +89,10 @@ function isAnyModalOpen(): boolean {
);
}
function isControllerInputBlocked(): boolean {
return isControllerInteractionBlocked(ctx.state);
}
function syncSettingsModalSubtitleSuppression(): void {
const suppressSubtitles = isAnySettingsModalOpen();
document.body.classList.toggle('settings-modal-open', suppressSubtitles);
@@ -323,7 +328,7 @@ function startControllerPolling(): void {
},
getKeyboardModeEnabled: () => ctx.state.keyboardDrivenModeEnabled,
getLookupWindowOpen: () => ctx.state.yomitanPopupVisible || isYomitanPopupVisible(document),
getInteractionBlocked: () => isAnyModalOpen(),
getInteractionBlocked: () => isControllerInputBlocked(),
toggleKeyboardMode: () => keyboardHandlers.handleKeyboardModeToggleRequested(),
toggleLookup: () => keyboardHandlers.handleLookupWindowToggleRequested(),
closeLookup: () => {