From 25549b8be23ddb8b91dda47fffb3a04e4901b060 Mon Sep 17 00:00:00 2001 From: hevink Date: Sat, 16 May 2026 13:14:59 +0530 Subject: [PATCH 1/2] fix: resolve TypeScript build errors - Add missing isShortcutKey type guard to keybinding.ts - Add missing isActionWithOptionalArgs and isAction type guards to types.ts - Fix IndexedDBAdapter constructor calls to use object params instead of positional args (runner.ts, v1-to-v2.ts) - Fix StickersRegistry.register call to use object param { key, definition } --- apps/web/src/actions/keybinding.ts | 16 ++++++++++ apps/web/src/actions/types.ts | 17 +++++++++++ .../src/services/storage/migrations/runner.ts | 12 ++++---- .../services/storage/migrations/v1-to-v2.ts | 30 +++++++++---------- apps/web/src/stickers/providers/index.ts | 2 +- 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/apps/web/src/actions/keybinding.ts b/apps/web/src/actions/keybinding.ts index aeec2fd6d..fc9a17ae2 100644 --- a/apps/web/src/actions/keybinding.ts +++ b/apps/web/src/actions/keybinding.ts @@ -38,6 +38,22 @@ export type SingleCharacterShortcutKey = `${Key}`; export type ShortcutKey = ModifierBasedShortcutKey | SingleCharacterShortcutKey; +const MODIFIER_KEYS_SET: ReadonlySet = new Set([ + "ctrl", "alt", "shift", + "ctrl+shift", "alt+shift", "ctrl+alt", "ctrl+alt+shift", +]); + +export function isShortcutKey(value: string): value is ShortcutKey { + // Single key (e.g. "a", "enter") + if (isKey(value)) return true; + // Modifier+key (e.g. "ctrl+s", "ctrl+shift+z") + const lastPlus = value.lastIndexOf("+"); + if (lastPlus === -1) return false; + const modifier = value.slice(0, lastPlus); + const key = value.slice(lastPlus + 1); + return MODIFIER_KEYS_SET.has(modifier) && isKey(key); +} + export type KeybindingConfig = { [key in ShortcutKey]?: TActionWithOptionalArgs; }; diff --git a/apps/web/src/actions/types.ts b/apps/web/src/actions/types.ts index 38627b957..7cc14d46b 100644 --- a/apps/web/src/actions/types.ts +++ b/apps/web/src/actions/types.ts @@ -1,5 +1,6 @@ import type { MutableRefObject } from "react"; import type { TAction } from "./definitions"; +import { ACTIONS } from "./definitions"; export type { TAction }; @@ -24,6 +25,22 @@ export type TActionWithOptionalArgs = export type TActionWithNoArgs = Exclude; +const ACTION_KEYS_SET: ReadonlySet = new Set(Object.keys(ACTIONS)); + +export function isAction(value: string): value is TAction { + return ACTION_KEYS_SET.has(value); +} + +export function isActionWithOptionalArgs(value: string): value is TActionWithOptionalArgs { + if (!isAction(value)) return false; + // Actions that require mandatory (non-undefined) args cannot be used as keybindings + const ACTIONS_WITH_REQUIRED_ARGS: ReadonlySet = new Set([ + "remove-media-asset", + "remove-media-assets", + ]); + return !ACTIONS_WITH_REQUIRED_ARGS.has(value); +} + export type TArgOfAction = A extends TActionWithArgs ? TActionArgsMap[A] : undefined; diff --git a/apps/web/src/services/storage/migrations/runner.ts b/apps/web/src/services/storage/migrations/runner.ts index eed8071f8..162db8ca9 100644 --- a/apps/web/src/services/storage/migrations/runner.ts +++ b/apps/web/src/services/storage/migrations/runner.ts @@ -38,11 +38,11 @@ export async function runStorageMigrations({ hasCleanedUpMetaDb = true; } - const projectsAdapter = new IndexedDBAdapter( - "video-editor-projects", - "projects", - 1, - ); + const projectsAdapter = new IndexedDBAdapter({ + dbName: "video-editor-projects", + storeName: "projects", + version: 1, + }); const projects = await projectsAdapter.getAll(); @@ -95,7 +95,7 @@ export async function runStorageMigrations({ break; } - await projectsAdapter.set(projectId, result.project); + await projectsAdapter.set({ key: projectId, value: result.project }); migratedCount++; currentVersion = migration.to; projectRecord = result.project; diff --git a/apps/web/src/services/storage/migrations/v1-to-v2.ts b/apps/web/src/services/storage/migrations/v1-to-v2.ts index a87b4a86f..601e47975 100644 --- a/apps/web/src/services/storage/migrations/v1-to-v2.ts +++ b/apps/web/src/services/storage/migrations/v1-to-v2.ts @@ -121,20 +121,20 @@ async function loadLegacyTracksForScene({ const sceneDbName = `video-editor-timelines-${projectId}-${sceneId}`; const projectDbName = `video-editor-timelines-${projectId}`; - const adapter = new IndexedDBAdapter( - sceneDbName, - "timeline", - 1, - ); + const adapter = new IndexedDBAdapter({ + dbName: sceneDbName, + storeName: "timeline", + version: 1, + }); let data = await adapter.get("timeline"); if (!data && isMain) { - const projectAdapter = new IndexedDBAdapter( - projectDbName, - "timeline", - 1, - ); + const projectAdapter = new IndexedDBAdapter({ + dbName: projectDbName, + storeName: "timeline", + version: 1, + }); data = await projectAdapter.get("timeline"); } @@ -157,11 +157,11 @@ async function loadMediaTypesById({ return {}; } - const mediaMetadataAdapter = new IndexedDBAdapter( - `video-editor-media-${projectId}`, - "media-metadata", - 1, - ); + const mediaMetadataAdapter = new IndexedDBAdapter({ + dbName: `video-editor-media-${projectId}`, + storeName: "media-metadata", + version: 1, + }); const mediaEntries = await Promise.all( mediaIds.map(async (mediaId) => { diff --git a/apps/web/src/stickers/providers/index.ts b/apps/web/src/stickers/providers/index.ts index 56b3f6cb6..b0ea6efc1 100644 --- a/apps/web/src/stickers/providers/index.ts +++ b/apps/web/src/stickers/providers/index.ts @@ -19,6 +19,6 @@ export function registerDefaultStickerProviders({ if (stickersRegistry.has(provider.id)) { continue; } - stickersRegistry.register(provider.id, provider); + stickersRegistry.register({ key: provider.id, definition: provider }); } } From 589e8f68a13e9e6c8d93025af8a3339689829a9e Mon Sep 17 00:00:00 2001 From: hevink Date: Sat, 16 May 2026 13:19:49 +0530 Subject: [PATCH 2/2] refactor: move ACTIONS_WITH_REQUIRED_ARGS to module scope Per CodeRabbit review: avoid recreating the Set on every function call by declaring it as a module-level constant, consistent with the pattern used for MODIFIER_KEYS_SET and ACTION_KEYS_SET. --- apps/web/src/actions/types.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/web/src/actions/types.ts b/apps/web/src/actions/types.ts index 7cc14d46b..9a59f8717 100644 --- a/apps/web/src/actions/types.ts +++ b/apps/web/src/actions/types.ts @@ -27,6 +27,11 @@ export type TActionWithNoArgs = Exclude; const ACTION_KEYS_SET: ReadonlySet = new Set(Object.keys(ACTIONS)); +const ACTIONS_WITH_REQUIRED_ARGS: ReadonlySet = new Set([ + "remove-media-asset", + "remove-media-assets", +]); + export function isAction(value: string): value is TAction { return ACTION_KEYS_SET.has(value); } @@ -34,10 +39,6 @@ export function isAction(value: string): value is TAction { export function isActionWithOptionalArgs(value: string): value is TActionWithOptionalArgs { if (!isAction(value)) return false; // Actions that require mandatory (non-undefined) args cannot be used as keybindings - const ACTIONS_WITH_REQUIRED_ARGS: ReadonlySet = new Set([ - "remove-media-asset", - "remove-media-assets", - ]); return !ACTIONS_WITH_REQUIRED_ARGS.has(value); }