feat(sidebar): add dialogue selection and copying (#238)

This commit is contained in:
2026-09-07 14:03:54 -07:00
committed by GitHub
parent c14c690875
commit 1e5d7747b4
24 changed files with 624 additions and 3 deletions
+1
View File
@@ -89,6 +89,7 @@ function createControllerConfigFixture() {
function createSubtitleSidebarSnapshotFixture(): SubtitleSidebarSnapshot {
return {
sourceKey: 'test-subtitles',
cues: [],
currentSubtitle: { text: '', startTime: null, endTime: null },
config: {
@@ -37,6 +37,15 @@ export function handleOverlayWindowBeforeInputEvent(options: {
if (options.kind === 'modal') return false;
if (!options.windowVisible) return false;
// The renderer decides whether Copy targets selected sidebar text or the live cue.
if (
(options.input.control || options.input.meta) &&
!options.input.alt &&
!options.input.shift &&
(options.input.code === 'KeyC' || options.input.key.toLowerCase() === 'c')
)
return false;
if (isKeyboardModeToggleInput(options.input)) {
options.preventDefault();
options.sendKeyboardModeToggleRequested();
+29
View File
@@ -85,6 +85,35 @@ test('handleOverlayWindowBeforeInputEvent leaves modal Tab handling alone', () =
assert.deepEqual(calls, []);
});
test('native Copy reaches the renderer before the current-subtitle fallback', () => {
for (const modifier of [{ control: true }, { meta: true }]) {
const handled = handleOverlayWindowBeforeInputEvent({
kind: 'visible',
windowVisible: true,
input: {
type: 'keyDown',
key: 'c',
code: 'KeyC',
isAutoRepeat: false,
isComposing: false,
shift: false,
control: false,
alt: false,
meta: false,
location: 0,
modifiers: [],
...modifier,
},
preventDefault: () => assert.fail('Copy must reach Chromium'),
sendKeyboardModeToggleRequested: () => assert.fail('Unexpected mode toggle'),
sendLookupWindowToggleRequested: () => assert.fail('Unexpected lookup toggle'),
tryHandleOverlayShortcutLocalFallback: () => assert.fail('Renderer owns Copy'),
forwardTabToMpv: () => assert.fail('Unexpected mpv input'),
});
assert.equal(handled, false);
}
});
test('handleOverlayWindowBlurred skips visible overlay restacking after manual hide', () => {
const calls: string[] = [];