From 0eb3cc11972f0f6bb9391332e5697e17566bb079 Mon Sep 17 00:00:00 2001 From: Alan Trebugeais Date: Fri, 8 May 2026 12:44:09 +0200 Subject: [PATCH] refactored most types into timelineTypes to avoid having types everywhere --- .../components/viewport/TimelineCanvas.tsx | 2 +- .../viewport/TimelineCanvasRows.tsx | 2 +- .../timeline/core/timelineTypes.ts | 39 +++++++++++++++++++ .../video-editor/timeline/dnd/engine.ts | 8 +--- .../timeline/hooks/timelineAudioPlacement.ts | 4 +- .../timeline/hooks/timelineHookTypes.ts | 9 ----- .../timeline/hooks/useTimelineAudioActions.ts | 4 +- .../timeline/hooks/useTimelineDndBindings.ts | 3 +- .../hooks/useTimelineEditorRuntime.ts | 25 ++++-------- .../hooks/useTimelineKeyboardShortcuts.ts | 11 +----- .../timeline/hooks/useTimelineSelection.ts | 15 +++---- .../timeline/model/timelineModel.ts | 21 +--------- 12 files changed, 63 insertions(+), 80 deletions(-) create mode 100644 src/components/video-editor/timeline/core/timelineTypes.ts delete mode 100644 src/components/video-editor/timeline/hooks/timelineHookTypes.ts diff --git a/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx b/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx index 0fd077c2..e02dfb1c 100644 --- a/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx +++ b/src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx @@ -8,8 +8,8 @@ import { TIMELINE_AXIS_HEIGHT_PX, } from "../../timelineLayout"; import type { AudioPeaksData } from "../../useAudioPeaks"; +import type { TimelineRenderItem } from "../../core/timelineTypes"; import { isAnnotationTrackRowId, isAudioTrackRowId } from "../../core/rows"; -import type { TimelineRenderItem } from "../../model/timelineModel"; import TimelineAxis from "../axis/TimelineAxis"; import PlaybackCursor from "../playhead/PlaybackCursor"; import { TimelineCanvasRows } from "./TimelineCanvasRows"; diff --git a/src/components/video-editor/timeline/components/viewport/TimelineCanvasRows.tsx b/src/components/video-editor/timeline/components/viewport/TimelineCanvasRows.tsx index ce8ccbb5..2e79633f 100644 --- a/src/components/video-editor/timeline/components/viewport/TimelineCanvasRows.tsx +++ b/src/components/video-editor/timeline/components/viewport/TimelineCanvasRows.tsx @@ -6,6 +6,7 @@ import glassStyles from "../../ItemGlass.module.css"; import Item from "../../Item"; import Row from "../../Row"; import { CLIP_ROW_ID, ZOOM_ROW_ID } from "../../core/constants"; +import type { TimelineRenderItem } from "../../core/timelineTypes"; import { getAnnotationTrackIndex, getAnnotationTrackRowId, @@ -14,7 +15,6 @@ import { isAnnotationTrackRowId, isAudioTrackRowId, } from "../../core/rows"; -import type { TimelineRenderItem } from "../../model/timelineModel"; import type { AudioPeaksData } from "../../useAudioPeaks"; import ClipMarkerOverlay from "../overlays/ClipMarkerOverlay"; diff --git a/src/components/video-editor/timeline/core/timelineTypes.ts b/src/components/video-editor/timeline/core/timelineTypes.ts new file mode 100644 index 00000000..ae5b1da8 --- /dev/null +++ b/src/components/video-editor/timeline/core/timelineTypes.ts @@ -0,0 +1,39 @@ +import type { ShortcutBinding } from "@/lib/shortcuts"; +import type { Span } from "dnd-timeline"; +import type { ZoomMode } from "../../types"; + +export interface TimelineRegionSpan { + id: string; + start: number; + end: number; + rowId: string; +} + +export interface TimelineRegion { + id: string; + startMs: number; + endMs: number; +} + +export interface TimelineAudioRegion extends TimelineRegion { + trackIndex?: number; +} + +export interface TimelineShortcutBindings { + addKeyframe: ShortcutBinding; + addZoom: ShortcutBinding; + splitClip: ShortcutBinding; + addAnnotation: ShortcutBinding; + deleteSelected: ShortcutBinding; +} + +export interface TimelineRenderItem { + id: string; + rowId: string; + span: Span; + label: string; + zoomDepth?: number; + zoomMode?: ZoomMode; + speedValue?: number; + variant: "zoom" | "trim" | "clip" | "annotation" | "speed" | "audio"; +} diff --git a/src/components/video-editor/timeline/dnd/engine.ts b/src/components/video-editor/timeline/dnd/engine.ts index fbe5a457..02be4523 100644 --- a/src/components/video-editor/timeline/dnd/engine.ts +++ b/src/components/video-editor/timeline/dnd/engine.ts @@ -1,11 +1,5 @@ import type { Range, Span } from "dnd-timeline"; - -export interface TimelineRegionSpan { - id: string; - start: number; - end: number; - rowId: string; -} +import type { TimelineRegionSpan } from "../core/timelineTypes"; export interface DndEngineConfig { totalMs: number; diff --git a/src/components/video-editor/timeline/hooks/timelineAudioPlacement.ts b/src/components/video-editor/timeline/hooks/timelineAudioPlacement.ts index a7316698..3a06d4da 100644 --- a/src/components/video-editor/timeline/hooks/timelineAudioPlacement.ts +++ b/src/components/video-editor/timeline/hooks/timelineAudioPlacement.ts @@ -1,8 +1,8 @@ import { spansOverlap } from "../core/spans"; -import type { AudioRegionLite } from "./timelineHookTypes"; +import type { TimelineAudioRegion } from "../core/timelineTypes"; interface ResolveAudioPlacementParams { - audioRegions: AudioRegionLite[]; + audioRegions: TimelineAudioRegion[]; startPos: number; totalMs: number; audioDurationMs: number; diff --git a/src/components/video-editor/timeline/hooks/timelineHookTypes.ts b/src/components/video-editor/timeline/hooks/timelineHookTypes.ts deleted file mode 100644 index 596a0be1..00000000 --- a/src/components/video-editor/timeline/hooks/timelineHookTypes.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface RegionIdLite { - id: string; - startMs: number; - endMs: number; -} - -export interface AudioRegionLite extends RegionIdLite { - trackIndex?: number; -} diff --git a/src/components/video-editor/timeline/hooks/useTimelineAudioActions.ts b/src/components/video-editor/timeline/hooks/useTimelineAudioActions.ts index 374ae4fb..18e332c9 100644 --- a/src/components/video-editor/timeline/hooks/useTimelineAudioActions.ts +++ b/src/components/video-editor/timeline/hooks/useTimelineAudioActions.ts @@ -1,7 +1,7 @@ import { useCallback, useMemo } from "react"; import { resolveMediaElementSource } from "@/lib/exporter/localMediaSource"; +import type { TimelineAudioRegion } from "../core/timelineTypes"; import { resolveAudioPlacement } from "./timelineAudioPlacement"; -import type { AudioRegionLite } from "./timelineHookTypes"; import { timelineNotifications } from "./timelineNotifications"; interface AudioFilePickerResult { @@ -22,7 +22,7 @@ interface UseTimelineAudioActionsParams { currentTimeMs: number; }; regions: { - audio: AudioRegionLite[]; + audio: TimelineAudioRegion[]; }; onAudioAdded?: (span: { start: number; end: number }, audioPath: string, trackIndex?: number) => void; deps?: Partial; diff --git a/src/components/video-editor/timeline/hooks/useTimelineDndBindings.ts b/src/components/video-editor/timeline/hooks/useTimelineDndBindings.ts index 7a9411b6..55ddc9ac 100644 --- a/src/components/video-editor/timeline/hooks/useTimelineDndBindings.ts +++ b/src/components/video-editor/timeline/hooks/useTimelineDndBindings.ts @@ -8,9 +8,10 @@ import type { TrimRegion, ZoomRegion, } from "../../types"; +import type { TimelineRenderItem } from "../core/timelineTypes"; import { getAnnotationTrackIndex, getAudioTrackIndex, isAnnotationTrackRowId, isAudioTrackRowId } from "../core/rows"; import { spansOverlap } from "../core/spans"; -import { buildAllRegionSpans, buildTimelineItems, resolveDropRowId, type TimelineRenderItem } from "../model/timelineModel"; +import { buildAllRegionSpans, buildTimelineItems, resolveDropRowId } from "../model/timelineModel"; interface UseTimelineDndBindingsParams { zoomRegions: ZoomRegion[]; diff --git a/src/components/video-editor/timeline/hooks/useTimelineEditorRuntime.ts b/src/components/video-editor/timeline/hooks/useTimelineEditorRuntime.ts index d4311eab..17cdb166 100644 --- a/src/components/video-editor/timeline/hooks/useTimelineEditorRuntime.ts +++ b/src/components/video-editor/timeline/hooks/useTimelineEditorRuntime.ts @@ -1,7 +1,7 @@ import type { Span } from "dnd-timeline"; import { useCallback, useImperativeHandle } from "react"; import type { ForwardedRef, RefObject } from "react"; -import type { ShortcutBinding } from "@/lib/shortcuts"; +import type { TimelineShortcutBindings } from "../core/timelineTypes"; import { useTimelineDndBindings } from "./useTimelineDndBindings"; import { useTimelineAnnotationsActions } from "./useTimelineAnnotationsActions"; import { useTimelineAudioActions } from "./useTimelineAudioActions"; @@ -61,13 +61,7 @@ interface UseTimelineEditorRuntimeParams { selectedAudioId?: string | null; onSelectAudio?: (id: string | null) => void; isMac: boolean; - keyShortcuts: { - addKeyframe: ShortcutBinding; - addZoom: ShortcutBinding; - splitClip: ShortcutBinding; - addAnnotation: ShortcutBinding; - deleteSelected: ShortcutBinding; - }; + keyShortcuts: TimelineShortcutBindings; isTimelineFocusedRef: RefObject; } @@ -187,13 +181,10 @@ export function useTimelineEditorRuntime({ const { defaultRegionDurationMs, canPlaceZoomAtMs, addZoomAtMs, handleAddZoom, handleSuggestZooms } = useTimelineZoomActions({ - videoDuration, - totalMs, - currentTimeMs, - zoomRegions, - clipRegions, + timeline: { videoDuration, totalMs, currentTimeMs }, + regions: { zoom: zoomRegions, clip: clipRegions }, cursorTelemetry, - disableSuggestedZooms, + options: { disableSuggestedZooms }, autoSuggestZoomsTrigger, onAutoSuggestZoomsConsumed, onZoomAdded, @@ -208,10 +199,8 @@ export function useTimelineEditorRuntime({ }, [videoDuration, totalMs, currentTimeMs, onClipSplit]); const { handleAddAudio } = useTimelineAudioActions({ - videoDuration, - totalMs, - currentTimeMs, - audioRegions, + timeline: { videoDuration, totalMs, currentTimeMs }, + regions: { audio: audioRegions }, onAudioAdded, }); diff --git a/src/components/video-editor/timeline/hooks/useTimelineKeyboardShortcuts.ts b/src/components/video-editor/timeline/hooks/useTimelineKeyboardShortcuts.ts index 434b3648..3c9c45a0 100644 --- a/src/components/video-editor/timeline/hooks/useTimelineKeyboardShortcuts.ts +++ b/src/components/video-editor/timeline/hooks/useTimelineKeyboardShortcuts.ts @@ -1,13 +1,6 @@ import { useEffect, type RefObject } from "react"; -import { matchesShortcut, type ShortcutBinding } from "@/lib/shortcuts"; - -interface TimelineShortcutBindings { - addKeyframe: ShortcutBinding; - addZoom: ShortcutBinding; - splitClip: ShortcutBinding; - addAnnotation: ShortcutBinding; - deleteSelected: ShortcutBinding; -} +import { matchesShortcut } from "@/lib/shortcuts"; +import type { TimelineShortcutBindings } from "../core/timelineTypes"; interface UseTimelineKeyboardShortcutsParams { isMac: boolean; diff --git a/src/components/video-editor/timeline/hooks/useTimelineSelection.ts b/src/components/video-editor/timeline/hooks/useTimelineSelection.ts index 2e682c72..2d78162e 100644 --- a/src/components/video-editor/timeline/hooks/useTimelineSelection.ts +++ b/src/components/video-editor/timeline/hooks/useTimelineSelection.ts @@ -1,19 +1,14 @@ import { useCallback, useMemo, useState } from "react"; import { v4 as uuidv4 } from "uuid"; - -interface RegionId { - id: string; - startMs: number; - endMs: number; -} +import type { TimelineRegion } from "../core/timelineTypes"; interface UseTimelineSelectionParams { totalMs: number; currentTimeMs: number; - zoomRegions: RegionId[]; - clipRegions: RegionId[]; - annotationRegions: (RegionId & { zIndex: number })[]; - audioRegions: RegionId[]; + zoomRegions: TimelineRegion[]; + clipRegions: TimelineRegion[]; + annotationRegions: (TimelineRegion & { zIndex: number })[]; + audioRegions: TimelineRegion[]; selectedZoomId: string | null; selectedClipId?: string | null; selectedAnnotationId?: string | null; diff --git a/src/components/video-editor/timeline/model/timelineModel.ts b/src/components/video-editor/timeline/model/timelineModel.ts index ceca3eea..0981b85c 100644 --- a/src/components/video-editor/timeline/model/timelineModel.ts +++ b/src/components/video-editor/timeline/model/timelineModel.ts @@ -1,11 +1,10 @@ -import type { Span } from "dnd-timeline"; import type { AnnotationRegion, AudioRegion, ClipRegion, - ZoomMode, ZoomRegion, } from "../../types"; +import type { TimelineRegionSpan, TimelineRenderItem } from "../core/timelineTypes"; import { CLIP_ROW_ID, ZOOM_ROW_ID } from "../core/constants"; import { getAnnotationTrackIndex, @@ -16,24 +15,6 @@ import { isAudioTrackRowId, } from "../core/rows"; -export interface TimelineRenderItem { - id: string; - rowId: string; - span: Span; - label: string; - zoomDepth?: number; - zoomMode?: ZoomMode; - speedValue?: number; - variant: "zoom" | "trim" | "clip" | "annotation" | "speed" | "audio"; -} - -export interface TimelineRegionSpan { - id: string; - start: number; - end: number; - rowId: string; -} - export function getAnnotationLabel(region: AnnotationRegion): string { if (region.type === "text") { const preview = region.content.trim() || "Empty text";