mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
* refactor: split useTimelinePlayer.ts and hyperframes-player.ts into focused modules (<500 LOC each) * fix(ci): scope 500 LOC check to packages/studio, add allowlist for grandfathered files * feat(cli): Linux ARM64 support — auto-install Chromium on DGX Spark / GB10 / Jetson Chrome Headless Shell has no Linux ARM64 binary. On arm64 Linux: - Detects the platform automatically - Tries to auto-install system Chromium via apt-get (works on Ubuntu/Debian ARM) - Falls back to clear manual instructions with exact commands - 'hyperframes browser ensure' guides through the setup interactively - After setup, all render commands work without any flags * fix(ci): disable Windows Defender real-time monitoring to prevent EPERM builds Path exclusions are insufficient — Defender re-scans new files created during bun install before the exclusion takes effect. Disable real-time monitoring for the entire job duration instead (standard CI practice). * refactor(studio): split all files >500 LOC + extract useToast, delete allowlist All 11 large files split into focused modules under 500 LOC. App.tsx extracted toast logic into useToast hook (493 LOC now). .filesize-allowlist deleted — no longer needed. * fix: remove unused imports from split files, extract useToast from App.tsx App.tsx: 504 → 493 lines (toast logic extracted to useToast hook) timelineDOM.ts: remove unused imports from re-export pattern MotionPanel.tsx: remove unused clampStudioCustomEasePoints import studioMotionOps.ts: remove unused StudioGsapMotionDirection import * fix(ci): use Set-MpPreference to fully disable Windows Defender (both jobs) * fix(producer): use node --experimental-strip-types instead of tsx for build:fonts Eliminates the tsx binary dependency that Windows Defender locks during bun install, causing EPERM errors. Node 22.6+ strips TypeScript types natively with no external binary. * chore: remove .filesize-allowlist — App.tsx is now 493 lines (<500) * fix(ci): disable Windows Defender before checkout to prevent all EPERM races * fix(producer): skip build:fonts if fontData.generated.ts already exists The generated file is tracked in git, so CI doesn't need to regenerate it. This avoids @fontsource/inter node_modules access on Windows which triggers EPERM from Defender scanning during bun install.
69 lines
1.9 KiB
TypeScript
69 lines
1.9 KiB
TypeScript
/**
|
||
* Keyboard shortcut filtering logic for playback controls.
|
||
*
|
||
* Determines whether a keydown event should be handled as a playback shortcut
|
||
* or ignored (e.g. when focus is in an input field, or when caption edit mode
|
||
* is active and the user is navigating caption segments).
|
||
*/
|
||
|
||
const PLAYBACK_FRAME_STEP_CODES = new Set(["ArrowLeft", "ArrowRight"]);
|
||
|
||
const PLAYBACK_SHORTCUT_IGNORED_SELECTOR = [
|
||
"input",
|
||
"textarea",
|
||
"select",
|
||
"button",
|
||
"a[href]",
|
||
"[contenteditable='true']",
|
||
"[role='button']",
|
||
"[role='checkbox']",
|
||
"[role='combobox']",
|
||
"[role='menuitem']",
|
||
"[role='radio']",
|
||
"[role='slider']",
|
||
"[role='spinbutton']",
|
||
"[role='switch']",
|
||
"[role='textbox']",
|
||
].join(",");
|
||
|
||
export function shouldIgnorePlaybackShortcutTarget(target: EventTarget | null): boolean {
|
||
if (!target || typeof target !== "object") return false;
|
||
const candidate = target as { closest?: unknown };
|
||
if (typeof candidate.closest !== "function") return false;
|
||
return (
|
||
(candidate.closest as (selector: string) => Element | null).call(
|
||
target,
|
||
PLAYBACK_SHORTCUT_IGNORED_SELECTOR,
|
||
) !== null
|
||
);
|
||
}
|
||
|
||
interface PlaybackShortcutCaptionState {
|
||
isCaptionEditMode: boolean;
|
||
selectedCaptionSegmentCount: number;
|
||
}
|
||
|
||
type PlaybackShortcutEvent = Pick<
|
||
KeyboardEvent,
|
||
"altKey" | "ctrlKey" | "metaKey" | "code" | "target"
|
||
>;
|
||
|
||
export function shouldIgnorePlaybackShortcutEvent(
|
||
event: PlaybackShortcutEvent,
|
||
captionState: PlaybackShortcutCaptionState = {
|
||
isCaptionEditMode: false,
|
||
selectedCaptionSegmentCount: 0,
|
||
},
|
||
): boolean {
|
||
if (event.metaKey || event.ctrlKey || event.altKey) return true;
|
||
if (shouldIgnorePlaybackShortcutTarget(event.target)) return true;
|
||
return (
|
||
PLAYBACK_FRAME_STEP_CODES.has(event.code) &&
|
||
captionState.isCaptionEditMode &&
|
||
captionState.selectedCaptionSegmentCount > 0
|
||
);
|
||
}
|
||
|
||
/** JKL shuttle speeds (×1, ×2, ×4). */
|
||
export const SHUTTLE_SPEEDS = [1, 2, 4] as const;
|