diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2026-01-31 00:20:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-31 00:20:04 +0100 |
| commit | 7bf0984698e43b9aa2dd879f65951318ed410390 (patch) | |
| tree | ccf2cd590a47d550152afc07129cb55c71a9ec35 /apps/web/src/types | |
| parent | 0173db99448d1c4c6415dcf15272e17551b48b04 (diff) | |
| download | opencut-7bf0984698e43b9aa2dd879f65951318ed410390.tar.gz | |
codebase overhaul (#697)
Diffstat (limited to 'apps/web/src/types')
| -rw-r--r-- | apps/web/src/types/assets.ts | 9 | ||||
| -rw-r--r-- | apps/web/src/types/blog.ts | 92 | ||||
| -rw-r--r-- | apps/web/src/types/drag.ts | 21 | ||||
| -rw-r--r-- | apps/web/src/types/editor.ts | 29 | ||||
| -rw-r--r-- | apps/web/src/types/export.ts | 33 | ||||
| -rw-r--r-- | apps/web/src/types/keybinding.ts | 124 | ||||
| -rw-r--r-- | apps/web/src/types/language.ts | 4 | ||||
| -rw-r--r-- | apps/web/src/types/media.ts | 17 | ||||
| -rw-r--r-- | apps/web/src/types/playback.ts | 21 | ||||
| -rw-r--r-- | apps/web/src/types/post.ts | 92 | ||||
| -rw-r--r-- | apps/web/src/types/project.ts | 74 | ||||
| -rw-r--r-- | apps/web/src/types/sounds.ts | 62 | ||||
| -rw-r--r-- | apps/web/src/types/stickers.ts | 3 | ||||
| -rw-r--r-- | apps/web/src/types/time.ts | 1 | ||||
| -rw-r--r-- | apps/web/src/types/timeline.ts | 286 | ||||
| -rw-r--r-- | apps/web/src/types/transcription.ts | 47 |
16 files changed, 491 insertions, 424 deletions
diff --git a/apps/web/src/types/assets.ts b/apps/web/src/types/assets.ts new file mode 100644 index 00000000..c8dddfc7 --- /dev/null +++ b/apps/web/src/types/assets.ts @@ -0,0 +1,9 @@ +import type { MediaAssetData } from "@/services/storage/types"; + +export type MediaType = "image" | "video" | "audio"; + +export interface MediaAsset + extends Omit<MediaAssetData, "size" | "lastModified"> { + file: File; + url?: string; +} diff --git a/apps/web/src/types/blog.ts b/apps/web/src/types/blog.ts new file mode 100644 index 00000000..16795b02 --- /dev/null +++ b/apps/web/src/types/blog.ts @@ -0,0 +1,92 @@ +export type Post = { + id: string; + slug: string; + title: string; + content: string; + description: string; + coverImage: string; + publishedAt: Date; + updatedAt: Date; + authors: { + id: string; + name: string; + image: string; + }[]; + category: { + id: string; + slug: string; + name: string; + }; + tags: { + id: string; + slug: string; + name: string; + }[]; + attribution: { + author: string; + url: string; + } | null; +}; + +export type Pagination = { + limit: number; + currpage: number; + nextPage: number | null; + prevPage: number | null; + totalItems: number; + totalPages: number; +}; + +export type MarblePostList = { + posts: Post[]; + pagination: Pagination; +}; + +export type MarblePost = { + post: Post; +}; + +export type Tag = { + id: string; + name: string; + slug: string; +}; + +export type MarbleTag = { + tag: Tag; +}; + +export type MarbleTagList = { + tags: Tag[]; + pagination: Pagination; +}; + +export type Category = { + id: string; + name: string; + slug: string; +}; + +export type MarbleCategory = { + category: Category; +}; + +export type MarbleCategoryList = { + categories: Category[]; + pagination: Pagination; +}; + +export type Author = { + id: string; + name: string; + image: string; +}; + +export type MarbleAuthor = { + author: Author; +}; + +export type MarbleAuthorList = { + authors: Author[]; + pagination: Pagination; +}; diff --git a/apps/web/src/types/drag.ts b/apps/web/src/types/drag.ts new file mode 100644 index 00000000..e6e5daba --- /dev/null +++ b/apps/web/src/types/drag.ts @@ -0,0 +1,21 @@ +interface BaseDragData { + id: string; + name: string; +} + +export interface MediaDragData extends BaseDragData { + type: "media"; + mediaType: "image" | "video" | "audio"; +} + +export interface TextDragData extends BaseDragData { + type: "text"; + content: string; +} + +export interface StickerDragData extends BaseDragData { + type: "sticker"; + iconName: string; +} + +export type TimelineDragData = MediaDragData | TextDragData | StickerDragData; diff --git a/apps/web/src/types/editor.ts b/apps/web/src/types/editor.ts index 6cbc6a6a..0413b208 100644 --- a/apps/web/src/types/editor.ts +++ b/apps/web/src/types/editor.ts @@ -1,28 +1 @@ -export type BackgroundType = "blur" | "mirror" | "color"; - -export type CanvasMode = "preset" | "original" | "custom"; - -export interface CanvasSize { - width: number; - height: number; -} - -export interface CanvasPreset { - name: string; - width: number; - height: number; -} - -export interface TextElementDragState { - isDragging: boolean; - elementId: string | null; - trackId: string | null; - startX: number; - startY: number; - initialElementX: number; - initialElementY: number; - currentX: number; - currentY: number; - elementWidth: number; - elementHeight: number; -} +export type TPlatformLayout = "tiktok"; diff --git a/apps/web/src/types/export.ts b/apps/web/src/types/export.ts index 093268ce..351f5fc4 100644 --- a/apps/web/src/types/export.ts +++ b/apps/web/src/types/export.ts @@ -1,18 +1,27 @@ -export type ExportFormat = "mp4" | "webm"; -export type ExportQuality = "low" | "medium" | "high" | "very_high"; +export const EXPORT_QUALITY_VALUES = [ + "low", + "medium", + "high", + "very_high", +] as const; + +export const EXPORT_FORMAT_VALUES = ["mp4", "webm"] as const; + +export type ExportFormat = (typeof EXPORT_FORMAT_VALUES)[number]; +export type ExportQuality = (typeof EXPORT_QUALITY_VALUES)[number]; export interface ExportOptions { - format: ExportFormat; - quality: ExportQuality; - fps?: number; - includeAudio?: boolean; - onProgress?: (progress: number) => void; - onCancel?: () => boolean; + format: ExportFormat; + quality: ExportQuality; + fps?: number; + includeAudio?: boolean; + onProgress?: ({ progress }: { progress: number }) => void; + onCancel?: () => boolean; } export interface ExportResult { - success: boolean; - buffer?: ArrayBuffer; - error?: string; - cancelled?: boolean; + success: boolean; + buffer?: ArrayBuffer; + error?: string; + cancelled?: boolean; } diff --git a/apps/web/src/types/keybinding.ts b/apps/web/src/types/keybinding.ts index 831f3abd..f9b84e31 100644 --- a/apps/web/src/types/keybinding.ts +++ b/apps/web/src/types/keybinding.ts @@ -1,73 +1,71 @@ -import { ActionWithOptionalArgs } from "@/constants/actions"; +import type { TActionWithOptionalArgs } from "@/lib/actions"; /** * Alt is also regarded as macOS OPTION (⌥) key * Ctrl is also regarded as macOS COMMAND (⌘) key (NOTE: this differs from HTML Keyboard spec where COMMAND is Meta key!) */ export type ModifierKeys = - | "ctrl" - | "alt" - | "shift" - | "ctrl+shift" - | "alt+shift" - | "ctrl+alt" - | "ctrl+alt+shift"; + | "ctrl" + | "alt" + | "shift" + | "ctrl+shift" + | "alt+shift" + | "ctrl+alt" + | "ctrl+alt+shift"; -/* eslint-disable prettier/prettier */ -// prettier-ignore export type Key = - | "a" - | "b" - | "c" - | "d" - | "e" - | "f" - | "g" - | "h" - | "i" - | "j" - | "k" - | "l" - | "m" - | "n" - | "o" - | "p" - | "q" - | "r" - | "s" - | "t" - | "u" - | "v" - | "w" - | "x" - | "y" - | "z" - | "0" - | "1" - | "2" - | "3" - | "4" - | "5" - | "6" - | "7" - | "8" - | "9" - | "up" - | "down" - | "left" - | "right" - | "/" - | "?" - | "." - | "enter" - | "tab" - | "space" - | "escape" - | "esc" - | "backspace" - | "delete" - | "home" - | "end"; + | "a" + | "b" + | "c" + | "d" + | "e" + | "f" + | "g" + | "h" + | "i" + | "j" + | "k" + | "l" + | "m" + | "n" + | "o" + | "p" + | "q" + | "r" + | "s" + | "t" + | "u" + | "v" + | "w" + | "x" + | "y" + | "z" + | "0" + | "1" + | "2" + | "3" + | "4" + | "5" + | "6" + | "7" + | "8" + | "9" + | "up" + | "down" + | "left" + | "right" + | "/" + | "?" + | "." + | "enter" + | "tab" + | "space" + | "escape" + | "esc" + | "backspace" + | "delete" + | "home" + | "end"; /* eslint-enable */ export type ModifierBasedShortcutKey = `${ModifierKeys}+${Key}`; @@ -77,5 +75,5 @@ export type SingleCharacterShortcutKey = `${Key}`; export type ShortcutKey = ModifierBasedShortcutKey | SingleCharacterShortcutKey; export type KeybindingConfig = { - [key in ShortcutKey]?: ActionWithOptionalArgs; + [key in ShortcutKey]?: TActionWithOptionalArgs; }; diff --git a/apps/web/src/types/language.ts b/apps/web/src/types/language.ts new file mode 100644 index 00000000..a3f527c8 --- /dev/null +++ b/apps/web/src/types/language.ts @@ -0,0 +1,4 @@ +import type { LANGUAGES } from "@/constants/language-constants"; + +export type Language = (typeof LANGUAGES)[number]; +export type LanguageCode = Language["code"]; diff --git a/apps/web/src/types/media.ts b/apps/web/src/types/media.ts deleted file mode 100644 index 6e94fcff..00000000 --- a/apps/web/src/types/media.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type MediaType = "image" | "video" | "audio";
-
-// What's stored in media library
-export interface MediaFile {
- id: string;
- name: string;
- type: MediaType;
- file: File;
- url?: string; // Object URL for preview
- thumbnailUrl?: string; // For video thumbnails
- duration?: number; // For video/audio duration
- width?: number; // For video/image width
- height?: number; // For video/image height
- fps?: number; // For video frame rate
- // Ephemeral items are used by timeline directly and should not appear in the media library or be persisted
- ephemeral?: boolean;
-}
diff --git a/apps/web/src/types/playback.ts b/apps/web/src/types/playback.ts deleted file mode 100644 index 8758ea03..00000000 --- a/apps/web/src/types/playback.ts +++ /dev/null @@ -1,21 +0,0 @@ -export interface PlaybackState { - isPlaying: boolean; - currentTime: number; - duration: number; - volume: number; - speed: number; - muted: boolean; - previousVolume?: number; -} - -export interface PlaybackControls { - play: () => void; - pause: () => void; - seek: (time: number) => void; - setVolume: (volume: number) => void; - setSpeed: (speed: number) => void; - toggle: () => void; - mute: () => void; - unmute: () => void; - toggleMute: () => void; -} diff --git a/apps/web/src/types/post.ts b/apps/web/src/types/post.ts deleted file mode 100644 index fbee239e..00000000 --- a/apps/web/src/types/post.ts +++ /dev/null @@ -1,92 +0,0 @@ -export type Post = { - id: string; - slug: string; - title: string; - content: string; - description: string; - coverImage: string; - publishedAt: Date; - updatedAt: Date; - authors: { - id: string; - name: string; - image: string; - }[]; - category: { - id: string; - slug: string; - name: string; - }; - tags: { - id: string; - slug: string; - name: string; - }[]; - attribution: { - author: string; - url: string; - } | null; -}; - -export type Pagination = { - limit: number; - currpage: number; - nextPage: number | null; - prevPage: number | null; - totalItems: number; - totalPages: number; -}; - -export type MarblePostList = { - posts: Post[]; - pagination: Pagination; -}; - -export type MarblePost = { - post: Post; -}; - -export type Tag = { - id: string; - name: string; - slug: string; -}; - -export type MarbleTag = { - tag: Tag; -}; - -export type MarbleTagList = { - tags: Tag[]; - pagination: Pagination; -}; - -export type Category = { - id: string; - name: string; - slug: string; -}; - -export type MarbleCategory = { - category: Category; -}; - -export type MarbleCategoryList = { - categories: Category[]; - pagination: Pagination; -}; - -export type Author = { - id: string; - name: string; - image: string; -}; - -export type MarbleAuthor = { - author: Author; -}; - -export type MarbleAuthorList = { - authors: Author[]; - pagination: Pagination; -}; diff --git a/apps/web/src/types/project.ts b/apps/web/src/types/project.ts index f182653d..c8074c26 100644 --- a/apps/web/src/types/project.ts +++ b/apps/web/src/types/project.ts @@ -1,35 +1,51 @@ -import { CanvasSize } from "./editor"; +import type { TScene } from "./timeline"; -export type BlurIntensity = 4 | 8 | 18; +export type TBackground = + | { + type: "color"; + color: string; + } + | { + type: "blur"; + blurIntensity: number; + }; -export interface Scene { - id: string; - name: string; - isMain: boolean; - createdAt: Date; - updatedAt: Date; +export interface TCanvasSize { + width: number; + height: number; +} + +export interface TProjectMetadata { + id: string; + name: string; + thumbnail?: string; + duration: number; + createdAt: Date; + updatedAt: Date; +} + +export interface TProjectSettings { + fps: number; + canvasSize: TCanvasSize; + originalCanvasSize?: TCanvasSize | null; + background: TBackground; +} + +export interface TTimelineViewState { + zoomLevel: number; + scrollLeft: number; + playheadTime: number; } export interface TProject { - id: string; - name: string; - thumbnail: string; - createdAt: Date; - updatedAt: Date; - scenes: Scene[]; - currentSceneId: string; - mediaItems?: string[]; - backgroundColor?: string; - backgroundType?: "color" | "blur"; - blurIntensity?: BlurIntensity; - fps?: number; - bookmarks?: number[]; - canvasSize: CanvasSize; - /** - * Tracks how the canvas size was set: - * - "preset": User selected a standard preset (e.g. 16:9, 9:16) - * - "original": Using the first media item's dimensions - * - "custom": User set a custom aspect ratio or dimensions - */ - canvasMode: "preset" | "original" | "custom"; + metadata: TProjectMetadata; + scenes: TScene[]; + currentSceneId: string; + settings: TProjectSettings; + version: number; + timelineViewState?: TTimelineViewState; } + +export type TProjectSortKey = "createdAt" | "updatedAt" | "name" | "duration"; +export type TSortOrder = "asc" | "desc"; +export type TProjectSortOption = `${TProjectSortKey}-${TSortOrder}`; diff --git a/apps/web/src/types/sounds.ts b/apps/web/src/types/sounds.ts index faa485eb..f7526846 100644 --- a/apps/web/src/types/sounds.ts +++ b/apps/web/src/types/sounds.ts @@ -1,39 +1,39 @@ export interface SoundEffect {
- id: number;
- name: string;
- description: string;
- url: string;
- previewUrl?: string;
- downloadUrl?: string;
- duration: number;
- filesize: number;
- type: string;
- channels: number;
- bitrate: number;
- bitdepth: number;
- samplerate: number;
- username: string;
- tags: string[];
- license: string;
- created: string;
- downloads: number;
- rating: number;
- ratingCount: number;
+ id: number;
+ name: string;
+ description: string;
+ url: string;
+ previewUrl?: string;
+ downloadUrl?: string;
+ duration: number;
+ filesize: number;
+ type: string;
+ channels: number;
+ bitrate: number;
+ bitdepth: number;
+ samplerate: number;
+ username: string;
+ tags: string[];
+ license: string;
+ created: string;
+ downloads: number;
+ rating: number;
+ ratingCount: number;
}
export interface SavedSound {
- id: number; // freesound id
- name: string;
- username: string;
- previewUrl?: string;
- downloadUrl?: string;
- duration: number;
- tags: string[];
- license: string;
- savedAt: string; // iso date string
+ id: number; // freesound id
+ name: string;
+ username: string;
+ previewUrl?: string;
+ downloadUrl?: string;
+ duration: number;
+ tags: string[];
+ license: string;
+ savedAt: string; // iso date string
}
export interface SavedSoundsData {
- sounds: SavedSound[];
- lastModified: string;
+ sounds: SavedSound[];
+ lastModified: string;
}
diff --git a/apps/web/src/types/stickers.ts b/apps/web/src/types/stickers.ts new file mode 100644 index 00000000..c6adfd7a --- /dev/null +++ b/apps/web/src/types/stickers.ts @@ -0,0 +1,3 @@ +import type { STICKER_CATEGORIES } from "@/constants/stickers-constants"; + +export type StickerCategory = (typeof STICKER_CATEGORIES)[number]; diff --git a/apps/web/src/types/time.ts b/apps/web/src/types/time.ts new file mode 100644 index 00000000..4009a1e1 --- /dev/null +++ b/apps/web/src/types/time.ts @@ -0,0 +1 @@ +export type TTimeCode = "MM:SS" | "HH:MM:SS" | "HH:MM:SS:CS" | "HH:MM:SS:FF"; diff --git a/apps/web/src/types/timeline.ts b/apps/web/src/types/timeline.ts index 61ba6af0..69d40518 100644 --- a/apps/web/src/types/timeline.ts +++ b/apps/web/src/types/timeline.ts @@ -1,166 +1,190 @@ -import { MediaType } from "@/types/media"; -import { generateUUID } from "@/lib/utils"; +export interface TScene { + id: string; + name: string; + isMain: boolean; + tracks: TimelineTrack[]; + bookmarks: number[]; + createdAt: Date; + updatedAt: Date; +} -export type TrackType = "media" | "text" | "audio"; +export type TrackType = "video" | "text" | "audio" | "sticker"; -// Base element properties -interface BaseTimelineElement { - id: string; - name: string; - duration: number; - startTime: number; - trimStart: number; - trimEnd: number; - hidden?: boolean; +interface BaseTrack { + id: string; + name: string; } -// Media element that references MediaStore -export interface MediaElement extends BaseTimelineElement { - type: "media"; - mediaId: string; - muted?: boolean; +export interface VideoTrack extends BaseTrack { + type: "video"; + elements: (VideoElement | ImageElement)[]; + isMain: boolean; + muted: boolean; + hidden: boolean; } -// Text element with embedded text data -export interface TextElement extends BaseTimelineElement { - type: "text"; - content: string; - fontSize: number; - fontFamily: string; - color: string; - backgroundColor: string; - textAlign: "left" | "center" | "right"; - fontWeight: "normal" | "bold"; - fontStyle: "normal" | "italic"; - textDecoration: "none" | "underline" | "line-through"; - x: number; // Position relative to canvas center - y: number; // Position relative to canvas center - rotation: number; // in degrees - opacity: number; // 0-1 +export interface TextTrack extends BaseTrack { + type: "text"; + elements: TextElement[]; + hidden: boolean; } -// Typed timeline elements -export type TimelineElement = MediaElement | TextElement; +export interface AudioTrack extends BaseTrack { + type: "audio"; + elements: AudioElement[]; + muted: boolean; +} -// Creation types (without id, for addElementToTrack) -export type CreateMediaElement = Omit<MediaElement, "id">; -export type CreateTextElement = Omit<TextElement, "id">; -export type CreateTimelineElement = CreateMediaElement | CreateTextElement; +export interface StickerTrack extends BaseTrack { + type: "sticker"; + elements: StickerElement[]; + hidden: boolean; +} + +export type TimelineTrack = VideoTrack | TextTrack | AudioTrack | StickerTrack; -export interface TimelineElementProps { - element: TimelineElement; - track: TimelineTrack; - zoomLevel: number; - isSelected: boolean; - onElementMouseDown: (e: React.MouseEvent, element: TimelineElement) => void; - onElementClick: (e: React.MouseEvent, element: TimelineElement) => void; +export interface Transform { + scale: number; + position: { + x: number; + y: number; + }; + rotate: number; } -export interface ResizeState { - elementId: string; - side: "left" | "right"; - startX: number; - initialTrimStart: number; - initialTrimEnd: number; +interface BaseAudioElement extends BaseTimelineElement { + type: "audio"; + volume: number; + muted?: boolean; + buffer?: AudioBuffer; } -// Drag data types for type-safe drag and drop -export interface MediaItemDragData { - id: string; - type: MediaType; - name: string; +export interface UploadAudioElement extends BaseAudioElement { + sourceType: "upload"; + mediaId: string; } -export interface TextItemDragData { - id: string; - type: "text"; - name: string; - content: string; +export interface LibraryAudioElement extends BaseAudioElement { + sourceType: "library"; + sourceUrl: string; } -export type DragData = MediaItemDragData | TextItemDragData; +export type AudioElement = UploadAudioElement | LibraryAudioElement; -export interface TimelineTrack { - id: string; - name: string; - type: TrackType; - elements: TimelineElement[]; - muted?: boolean; - isMain?: boolean; +interface BaseTimelineElement { + id: string; + name: string; + duration: number; + startTime: number; + trimStart: number; + trimEnd: number; } -export function sortTracksByOrder(tracks: TimelineTrack[]): TimelineTrack[] { - return [...tracks].sort((a, b) => { - // Text tracks always go to the top - if (a.type === "text" && b.type !== "text") return -1; - if (b.type === "text" && a.type !== "text") return 1; - - // Audio tracks always go to bottom - if (a.type === "audio" && b.type !== "audio") return 1; - if (b.type === "audio" && a.type !== "audio") return -1; +export interface VideoElement extends BaseTimelineElement { + type: "video"; + mediaId: string; + muted?: boolean; + hidden?: boolean; + transform: Transform; + opacity: number; +} - // Main track goes above audio but below text tracks - if (a.isMain && !b.isMain && b.type !== "audio" && b.type !== "text") - return 1; - if (b.isMain && !a.isMain && a.type !== "audio" && a.type !== "text") - return -1; +export interface ImageElement extends BaseTimelineElement { + type: "image"; + mediaId: string; + hidden?: boolean; + transform: Transform; + opacity: number; +} - // Within same category, maintain creation order - return 0; - }); +export interface TextElement extends BaseTimelineElement { + type: "text"; + content: string; + fontSize: number; + fontFamily: string; + color: string; + backgroundColor: string; + textAlign: "left" | "center" | "right"; + fontWeight: "normal" | "bold"; + fontStyle: "normal" | "italic"; + textDecoration: "none" | "underline" | "line-through"; + hidden?: boolean; + transform: Transform; + opacity: number; } -export function getMainTrack(tracks: TimelineTrack[]): TimelineTrack | null { - return tracks.find((track) => track.isMain) || null; +export interface StickerElement extends BaseTimelineElement { + type: "sticker"; + iconName: string; + hidden?: boolean; + transform: Transform; + opacity: number; + color?: string; } -export function ensureMainTrack(tracks: TimelineTrack[]): TimelineTrack[] { - const hasMainTrack = tracks.some((track) => track.isMain); +export type TimelineElement = + | AudioElement + | VideoElement + | ImageElement + | TextElement + | StickerElement; - if (!hasMainTrack) { - // Create main track if it doesn't exist - const mainTrack: TimelineTrack = { - id: generateUUID(), - name: "Main Track", - type: "media", - elements: [], - muted: false, - isMain: true, - }; - return [mainTrack, ...tracks]; - } +export type ElementType = TimelineElement["type"]; - return tracks; -} +export type CreateUploadAudioElement = Omit<UploadAudioElement, "id">; +export type CreateLibraryAudioElement = Omit<LibraryAudioElement, "id">; +export type CreateAudioElement = + | CreateUploadAudioElement + | CreateLibraryAudioElement; +export type CreateVideoElement = Omit<VideoElement, "id">; +export type CreateImageElement = Omit<ImageElement, "id">; +export type CreateTextElement = Omit<TextElement, "id">; +export type CreateStickerElement = Omit<StickerElement, "id">; +export type CreateTimelineElement = + | CreateAudioElement + | CreateVideoElement + | CreateImageElement + | CreateTextElement + | CreateStickerElement; -// Timeline validation utilities -export function canElementGoOnTrack( - elementType: "text" | "media", - trackType: TrackType -): boolean { - if (elementType === "text") { - return trackType === "text"; - } - if (elementType === "media") { - return trackType === "media" || trackType === "audio"; - } - return false; -} +// ---- Drag State ---- -export function validateElementTrackCompatibility( - element: { type: "text" | "media" }, - track: { type: TrackType } -): { isValid: boolean; errorMessage?: string } { - const isValid = canElementGoOnTrack(element.type, track.type); +export interface ElementDragState { + isDragging: boolean; + elementId: string | null; + trackId: string | null; + startMouseX: number; + startMouseY: number; + startElementTime: number; + clickOffsetTime: number; + currentTime: number; + currentMouseY: number; +} - if (!isValid) { - const errorMessage = - element.type === "text" - ? "Text elements can only be placed on text tracks" - : "Media elements can only be placed on media or audio tracks"; +export interface DropTarget { + trackIndex: number; + isNewTrack: boolean; + insertPosition: "above" | "below" | null; + xPosition: number; +} - return { isValid: false, errorMessage }; - } +export interface ComputeDropTargetParams { + elementType: ElementType; + mouseX: number; + mouseY: number; + tracks: TimelineTrack[]; + playheadTime: number; + isExternalDrop: boolean; + elementDuration: number; + pixelsPerSecond: number; + zoomLevel: number; + verticalDragDirection?: "up" | "down" | null; + startTimeOverride?: number; + excludeElementId?: string; +} - return { isValid: true }; +export interface ClipboardItem { + trackId: string; + trackType: TrackType; + element: CreateTimelineElement; } diff --git a/apps/web/src/types/transcription.ts b/apps/web/src/types/transcription.ts new file mode 100644 index 00000000..f189c6c9 --- /dev/null +++ b/apps/web/src/types/transcription.ts @@ -0,0 +1,47 @@ +import type { LanguageCode } from "./language"; + +export type TranscriptionLanguage = LanguageCode | "auto"; + +export interface TranscriptionSegment { + text: string; + start: number; + end: number; +} + +export interface TranscriptionResult { + text: string; + segments: TranscriptionSegment[]; + language: string; +} + +export type TranscriptionStatus = + | "idle" + | "loading-model" + | "transcribing" + | "complete" + | "error"; + +export interface TranscriptionProgress { + status: TranscriptionStatus; + progress: number; + message?: string; +} + +export type TranscriptionModelId = + | "whisper-tiny" + | "whisper-small" + | "whisper-medium" + | "whisper-large-v3-turbo"; + +export interface TranscriptionModel { + id: TranscriptionModelId; + name: string; + huggingFaceId: string; + description: string; +} + +export interface CaptionChunk { + text: string; + startTime: number; + duration: number; +} |
