mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
feat: masks, properties refactor, shaders, storage migrations, and more
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
export type TPlatformLayout =
|
||||
| "tiktok"
|
||||
| "instagram"
|
||||
| "youtube"
|
||||
| "snapchat";
|
||||
|
||||
export const PREVIEW_ZOOM_PRESETS = [25, 50, 75, 100, 150, 200];
|
||||
|
||||
export const PREVIEW_ZOOM = {
|
||||
min: 0.25,
|
||||
max: 16,
|
||||
step: 1.25,
|
||||
};
|
||||
|
||||
export const PANEL_CONFIG = {
|
||||
panels: {
|
||||
tools: 25,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ExportOptions } from "@/types/export";
|
||||
import type { ExportOptions } from "@/lib/export";
|
||||
|
||||
export const DEFAULT_EXPORT_OPTIONS = {
|
||||
format: "mp4",
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
export const DEFAULT_FONT = "Arial";
|
||||
|
||||
export const SYSTEM_FONTS = new Set([
|
||||
"Arial",
|
||||
"Helvetica",
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export const GRID_MIN = 1;
|
||||
export const GRID_MAX = 24;
|
||||
|
||||
export const DEFAULT_GRID_CONFIG = { rows: 3, cols: 3 } as const;
|
||||
@@ -9,3 +9,6 @@ export const LANGUAGES = [
|
||||
{ code: "ja", name: "Japanese" },
|
||||
{ code: "zh", name: "Chinese" },
|
||||
] as const;
|
||||
|
||||
export type Language = (typeof LANGUAGES)[number];
|
||||
export type LanguageCode = Language["code"];
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export const MAX_FEATHER = 1000;
|
||||
export const FEATHER_HANDLE_SCALE = 0.11;
|
||||
export const DEFAULT_SHAPE_MASK_SHORT_SIDE_RATIO = 0.6;
|
||||
export const MIN_MASK_DIMENSION = 0.01;
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { TCanvasSize } from "@/types/project";
|
||||
import type { TCanvasSize } from "@/lib/project/types";
|
||||
|
||||
export const DEFAULT_CANVAS_PRESETS: TCanvasSize[] = [
|
||||
{ width: 1920, height: 1080 },
|
||||
@@ -16,12 +16,12 @@ export const FPS_PRESETS = [
|
||||
] as const;
|
||||
|
||||
export const BLUR_INTENSITY_PRESETS: { label: string; value: number }[] = [
|
||||
{ label: "Light", value: 4 },
|
||||
{ label: "Medium", value: 8 },
|
||||
{ label: "Heavy", value: 18 },
|
||||
{ label: "Light", value: 10 },
|
||||
{ label: "Medium", value: 50 },
|
||||
{ label: "Heavy", value: 100 },
|
||||
] as const;
|
||||
|
||||
export const DEFAULT_CANVAS_SIZE: TCanvasSize = { width: 1920, height: 1080 };
|
||||
export const DEFAULT_FPS = 30;
|
||||
export const DEFAULT_BLUR_INTENSITY = 8;
|
||||
export const DEFAULT_BLUR_INTENSITY = 10;
|
||||
export const DEFAULT_COLOR = "#000000";
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
export const DEFAULT_RETIME_RATE = 1;
|
||||
export const MIN_RETIME_RATE = 0.01;
|
||||
export const MAX_RETIME_RATE = 5;
|
||||
export const MAX_PITCH_PRESERVE_RATE = 10;
|
||||
|
||||
export function clampRetimeRate({ rate }: { rate: number }): number {
|
||||
if (!Number.isFinite(rate) || rate <= 0) {
|
||||
return DEFAULT_RETIME_RATE;
|
||||
}
|
||||
|
||||
return Math.min(Math.max(rate, MIN_RETIME_RATE), MAX_RETIME_RATE);
|
||||
}
|
||||
|
||||
export function canMaintainPitch({ rate }: { rate: number }): boolean {
|
||||
if (!Number.isFinite(rate) || rate <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return clampRetimeRate({ rate }) <= MAX_PITCH_PRESERVE_RATE;
|
||||
}
|
||||
|
||||
export function shouldMaintainPitch({
|
||||
rate,
|
||||
maintainPitch,
|
||||
}: {
|
||||
rate: number;
|
||||
maintainPitch?: boolean;
|
||||
}): boolean {
|
||||
return maintainPitch === true && canMaintainPitch({ rate });
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
export const STICKER_INTRINSIC_SIZE_FALLBACK = 200;
|
||||
|
||||
export const STICKER_CATEGORIES = {
|
||||
all: "All",
|
||||
logos: "Logos",
|
||||
icons: "Icons",
|
||||
emoji: "Emoji",
|
||||
flags: "Flags",
|
||||
shapes: "Shapes",
|
||||
};
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
import type { TextElement } from "@/types/timeline";
|
||||
import {
|
||||
DEFAULT_OPACITY,
|
||||
DEFAULT_TRANSFORM,
|
||||
TIMELINE_CONSTANTS,
|
||||
} from "./timeline-constants";
|
||||
|
||||
export const MIN_FONT_SIZE = 5;
|
||||
export const MAX_FONT_SIZE = 300;
|
||||
|
||||
@@ -14,40 +7,5 @@ export const MAX_FONT_SIZE = 300;
|
||||
*/
|
||||
export const FONT_SIZE_SCALE_REFERENCE = 90;
|
||||
|
||||
export const DEFAULT_LETTER_SPACING = 0;
|
||||
export const DEFAULT_LINE_HEIGHT = 1.2;
|
||||
|
||||
export const CORNER_RADIUS_MIN = 0;
|
||||
export const CORNER_RADIUS_MAX = 100;
|
||||
|
||||
export const DEFAULT_TEXT_BACKGROUND = {
|
||||
enabled: false,
|
||||
color: "#000000",
|
||||
cornerRadius: 0,
|
||||
paddingX: 30,
|
||||
paddingY: 42,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
};
|
||||
|
||||
export const DEFAULT_TEXT_ELEMENT: Omit<TextElement, "id"> = {
|
||||
type: "text",
|
||||
name: "Text",
|
||||
content: "Default text",
|
||||
fontSize: 15,
|
||||
fontFamily: "Arial",
|
||||
color: "#ffffff",
|
||||
background: DEFAULT_TEXT_BACKGROUND,
|
||||
textAlign: "center",
|
||||
fontWeight: "normal",
|
||||
fontStyle: "normal",
|
||||
textDecoration: "none",
|
||||
letterSpacing: DEFAULT_LETTER_SPACING,
|
||||
lineHeight: DEFAULT_LINE_HEIGHT,
|
||||
duration: TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION,
|
||||
startTime: 0,
|
||||
trimStart: 0,
|
||||
trimEnd: 0,
|
||||
transform: DEFAULT_TRANSFORM,
|
||||
opacity: DEFAULT_OPACITY,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import type { ElementType, TrackType } from "@/lib/timeline";
|
||||
|
||||
export const TRACK_CONFIG: Record<
|
||||
TrackType,
|
||||
{
|
||||
height: number;
|
||||
defaultName: string;
|
||||
}
|
||||
> = {
|
||||
video: {
|
||||
height: 65,
|
||||
defaultName: "Video track",
|
||||
},
|
||||
text: {
|
||||
height: 25,
|
||||
defaultName: "Text track",
|
||||
},
|
||||
audio: {
|
||||
height: 50,
|
||||
defaultName: "Audio track",
|
||||
},
|
||||
graphic: {
|
||||
height: 25,
|
||||
defaultName: "Graphic track",
|
||||
},
|
||||
effect: {
|
||||
height: 25,
|
||||
defaultName: "Effect track",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const ELEMENT_TYPE_CONFIG: Record<
|
||||
TrackType,
|
||||
{
|
||||
background: string;
|
||||
waveformColor?: string;
|
||||
}
|
||||
> = {
|
||||
video: { background: "transparent" },
|
||||
text: { background: "bg-[#5DBAA0]" },
|
||||
audio: {
|
||||
background: "bg-[#8F5DBA]",
|
||||
waveformColor: "rgba(255, 255, 255, 0.5)",
|
||||
},
|
||||
graphic: { background: "bg-[#BA5D7A]" },
|
||||
effect: { background: "bg-[#5d93ba]" },
|
||||
} as const;
|
||||
|
||||
export const ELEMENT_TRACK_MAP: Record<ElementType, TrackType> = {
|
||||
audio: "audio",
|
||||
text: "text",
|
||||
sticker: "graphic",
|
||||
graphic: "graphic",
|
||||
effect: "effect",
|
||||
video: "video",
|
||||
image: "video",
|
||||
};
|
||||
|
||||
export const TRACK_GAP = 6;
|
||||
export const TRACK_LABELS_WIDTH_PX = 112;
|
||||
|
||||
export const TIMELINE_RULER_HEIGHT = 22;
|
||||
export const TIMELINE_BOOKMARK_ROW_HEIGHT = 16;
|
||||
|
||||
export const DEFAULT_BOOKMARK_COLOR = "#009dff";
|
||||
export const DRAG_THRESHOLD_PX = 5;
|
||||
export const TIMELINE_SCROLLBAR_SIZE_PX = 12;
|
||||
export const TIMELINE_LAYERS = {
|
||||
trackContent: 10,
|
||||
dragLine: 20,
|
||||
playhead: 30,
|
||||
snapIndicator: 40,
|
||||
} as const;
|
||||
|
||||
export const TIMELINE_CONSTANTS = {
|
||||
PIXELS_PER_SECOND: 50,
|
||||
DEFAULT_ELEMENT_DURATION: 5,
|
||||
PADDING_TOP_PX: 2,
|
||||
HORIZONTAL_WHEEL_STEP_PX: 40,
|
||||
ZOOM_MIN: 0.1,
|
||||
ZOOM_MAX: 100,
|
||||
ZOOM_BUTTON_FACTOR: 1.7,
|
||||
ZOOM_ANCHOR_PLAYHEAD_THRESHOLD: 0.15,
|
||||
TRACK_SELECTED_BG: "bg-accent/50",
|
||||
} as const;
|
||||
@@ -1,102 +0,0 @@
|
||||
import type { TTimelineViewState } from "@/types/project";
|
||||
import type { BlendMode } from "@/types/rendering";
|
||||
import type { TrackType, Transform } from "@/types/timeline";
|
||||
import {
|
||||
Happy01Icon,
|
||||
MagicWand05Icon,
|
||||
MusicNote03Icon,
|
||||
TextIcon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { OcVideoIcon } from "@opencut/ui/icons";
|
||||
|
||||
export const DEFAULT_TRANSFORM: Transform = {
|
||||
scale: 1,
|
||||
position: { x: 0, y: 0 },
|
||||
rotate: 0,
|
||||
};
|
||||
|
||||
export const DEFAULT_OPACITY = 1;
|
||||
export const DEFAULT_BLEND_MODE: BlendMode = "normal";
|
||||
export const DEFAULT_BOOKMARK_COLOR = "#009dff";
|
||||
|
||||
export const TRACK_CONFIG: Record<
|
||||
TrackType,
|
||||
{
|
||||
background: string;
|
||||
height: number;
|
||||
defaultName: string;
|
||||
icon: React.ReactNode;
|
||||
}
|
||||
> = {
|
||||
video: {
|
||||
background: "transparent",
|
||||
height: 60,
|
||||
defaultName: "Video track",
|
||||
icon: <OcVideoIcon className="text-muted-foreground size-4 shrink-0" />,
|
||||
},
|
||||
text: {
|
||||
background: "bg-[#5DBAA0]",
|
||||
height: 25,
|
||||
defaultName: "Text track",
|
||||
icon: (
|
||||
<HugeiconsIcon
|
||||
icon={TextIcon}
|
||||
className="text-muted-foreground size-4 shrink-0"
|
||||
/>
|
||||
),
|
||||
},
|
||||
audio: {
|
||||
background: "bg-[#8F5DBA]",
|
||||
height: 50,
|
||||
defaultName: "Audio track",
|
||||
icon: (
|
||||
<HugeiconsIcon
|
||||
icon={MusicNote03Icon}
|
||||
className="text-muted-foreground size-4 shrink-0"
|
||||
/>
|
||||
),
|
||||
},
|
||||
sticker: {
|
||||
background: "bg-[#BA5D7A]",
|
||||
height: 50,
|
||||
defaultName: "Sticker track",
|
||||
icon: (
|
||||
<HugeiconsIcon
|
||||
icon={Happy01Icon}
|
||||
className="text-muted-foreground size-4 shrink-0"
|
||||
/>
|
||||
),
|
||||
},
|
||||
effect: {
|
||||
background: "bg-[#5d93ba]",
|
||||
height: 25,
|
||||
defaultName: "Effect track",
|
||||
icon: (
|
||||
<HugeiconsIcon
|
||||
icon={MagicWand05Icon}
|
||||
className="text-muted-foreground size-4 shrink-0"
|
||||
/>
|
||||
),
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const TRACK_GAP = 4;
|
||||
|
||||
export const DRAG_THRESHOLD_PX = 5;
|
||||
|
||||
export const TIMELINE_CONSTANTS = {
|
||||
PIXELS_PER_SECOND: 50,
|
||||
DEFAULT_ELEMENT_DURATION: 5,
|
||||
PADDING_TOP_PX: 0,
|
||||
ZOOM_MIN: 0.1,
|
||||
ZOOM_MAX: 100,
|
||||
ZOOM_BUTTON_FACTOR: 1.7,
|
||||
ZOOM_ANCHOR_PLAYHEAD_THRESHOLD: 0.15,
|
||||
} as const;
|
||||
|
||||
export const DEFAULT_TIMELINE_VIEW_STATE: TTimelineViewState = {
|
||||
zoomLevel: 1,
|
||||
scrollLeft: 0,
|
||||
playheadTime: 0,
|
||||
};
|
||||
@@ -2,8 +2,8 @@ import { LANGUAGES } from "@/constants/language-constants";
|
||||
import type {
|
||||
TranscriptionModel,
|
||||
TranscriptionModelId,
|
||||
} from "@/types/transcription";
|
||||
import type { LanguageCode } from "@/types/language";
|
||||
} from "@/lib/transcription/types";
|
||||
import type { LanguageCode } from "@/constants/language-constants";
|
||||
|
||||
const SUPPORTED_TRANSCRIPTION_LANGS: ReadonlyArray<LanguageCode> = [
|
||||
"en",
|
||||
|
||||
Reference in New Issue
Block a user