fix: scope studio playback shortcuts

This commit is contained in:
Miguel Ángel
2026-04-28 22:32:23 -04:00
parent a45f900af7
commit 9dc17ae30d
4 changed files with 142 additions and 2 deletions
@@ -0,0 +1,38 @@
import { describe, expect, it } from "vitest";
import { shouldHandleCaptionNudgeKey } from "./CaptionOverlay";
function mockKeyboardEvent(
key: string,
overrides: Partial<Pick<KeyboardEvent, "altKey" | "ctrlKey" | "metaKey">> = {},
): Pick<KeyboardEvent, "altKey" | "ctrlKey" | "metaKey" | "key"> {
return {
altKey: false,
ctrlKey: false,
metaKey: false,
key,
...overrides,
};
}
describe("shouldHandleCaptionNudgeKey", () => {
it("handles plain and Shift-modified arrow keys for caption nudging", () => {
expect(shouldHandleCaptionNudgeKey(mockKeyboardEvent("ArrowLeft"))).toBe(true);
expect(shouldHandleCaptionNudgeKey(mockKeyboardEvent("ArrowRight"))).toBe(true);
});
it("ignores browser and app shortcut chords", () => {
expect(shouldHandleCaptionNudgeKey(mockKeyboardEvent("ArrowLeft", { altKey: true }))).toBe(
false,
);
expect(shouldHandleCaptionNudgeKey(mockKeyboardEvent("ArrowRight", { ctrlKey: true }))).toBe(
false,
);
expect(shouldHandleCaptionNudgeKey(mockKeyboardEvent("ArrowRight", { metaKey: true }))).toBe(
false,
);
});
it("ignores non-arrow keys", () => {
expect(shouldHandleCaptionNudgeKey(mockKeyboardEvent("KeyL"))).toBe(false);
});
});
@@ -251,6 +251,14 @@ function syncToStore(segmentId: string, el: HTMLElement, iframeWin: Window) {
const HANDLE = 8;
const ROTATION_OFFSET = 20; // px above the selection box
const CAPTION_NUDGE_KEYS = new Set(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
type CaptionNudgeKeyEvent = Pick<KeyboardEvent, "altKey" | "ctrlKey" | "metaKey" | "key">;
export function shouldHandleCaptionNudgeKey(event: CaptionNudgeKeyEvent): boolean {
if (event.metaKey || event.ctrlKey || event.altKey) return false;
return CAPTION_NUDGE_KEYS.has(event.key);
}
export const CaptionOverlay = memo(function CaptionOverlay({ iframeRef }: CaptionOverlayProps) {
const isEditMode = useCaptionStore((s) => s.isEditMode);
@@ -329,7 +337,7 @@ export const CaptionOverlay = memo(function CaptionOverlay({ iframeRef }: Captio
const { selectedSegmentIds: sel, model: m } = useCaptionStore.getState();
if (sel.size === 0 || !m) return;
const arrow = e.key;
if (!["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(arrow)) return;
if (!shouldHandleCaptionNudgeKey(e)) return;
e.preventDefault();
const step = e.shiftKey ? 10 : 1;