summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/timeline-track.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/editor/timeline-track.tsx')
-rw-r--r--apps/web/src/components/editor/timeline-track.tsx37
1 files changed, 28 insertions, 9 deletions
diff --git a/apps/web/src/components/editor/timeline-track.tsx b/apps/web/src/components/editor/timeline-track.tsx
index 7e2e93e0..c3a16b9a 100644
--- a/apps/web/src/components/editor/timeline-track.tsx
+++ b/apps/web/src/components/editor/timeline-track.tsx
@@ -17,7 +17,11 @@ import type {
TimelineElement as TimelineElementType,
DragData,
} from "@/types/timeline";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import {
+ snapTimeToFrame,
+ TIMELINE_CONSTANTS,
+} from "@/constants/timeline-constants";
+import { useProjectStore } from "@/stores/project-store";
export function TimelineTrackContent({
track,
@@ -80,7 +84,10 @@ export function TimelineTrackContent({
mouseX / (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel)
);
const adjustedTime = Math.max(0, mouseTime - dragState.clickOffsetTime);
- const snappedTime = Math.round(adjustedTime * 10) / 10;
+ // Use frame snapping if project has FPS, otherwise use decimal snapping
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ const snappedTime = snapTimeToFrame(adjustedTime, projectFps);
updateDragTime(snappedTime);
};
@@ -342,7 +349,9 @@ export function TimelineTrackContent({
if (dragData.type === "text") {
// Text elements have default duration of 5 seconds
const newElementDuration = 5;
- const snappedTime = Math.round(dropTime * 10) / 10;
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ const snappedTime = snapTimeToFrame(dropTime, projectFps);
const newElementEnd = snappedTime + newElementDuration;
wouldOverlap = track.elements.some((existingElement) => {
@@ -361,7 +370,9 @@ export function TimelineTrackContent({
);
if (mediaItem) {
const newElementDuration = mediaItem.duration || 5;
- const snappedTime = Math.round(dropTime * 10) / 10;
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ const snappedTime = snapTimeToFrame(dropTime, projectFps);
const newElementEnd = snappedTime + newElementDuration;
wouldOverlap = track.elements.some((existingElement) => {
@@ -401,7 +412,9 @@ export function TimelineTrackContent({
movingElement.duration -
movingElement.trimStart -
movingElement.trimEnd;
- const snappedTime = Math.round(dropTime * 10) / 10;
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ const snappedTime = snapTimeToFrame(dropTime, projectFps);
const movingElementEnd = snappedTime + movingElementDuration;
wouldOverlap = track.elements.some((existingElement) => {
@@ -428,13 +441,17 @@ export function TimelineTrackContent({
if (wouldOverlap) {
e.dataTransfer.dropEffect = "none";
setWouldOverlap(true);
- setDropPosition(Math.round(dropTime * 10) / 10);
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ setDropPosition(snapTimeToFrame(dropTime, projectFps));
return;
}
e.dataTransfer.dropEffect = hasTimelineElement ? "move" : "copy";
setWouldOverlap(false);
- setDropPosition(Math.round(dropTime * 10) / 10);
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ setDropPosition(snapTimeToFrame(dropTime, projectFps));
};
const handleTrackDragEnter = (e: React.DragEvent) => {
@@ -502,7 +519,9 @@ export function TimelineTrackContent({
const mouseY = e.clientY - rect.top; // Get Y position relative to this track
const newStartTime =
mouseX / (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel);
- const snappedTime = Math.round(newStartTime * 10) / 10;
+ const projectStore = useProjectStore.getState();
+ const projectFps = projectStore.activeProject?.fps || 30;
+ const snappedTime = snapTimeToFrame(newStartTime, projectFps);
// Calculate drop position relative to tracks
const currentTrackIndex = tracks.findIndex((t) => t.id === track.id);
@@ -548,7 +567,7 @@ export function TimelineTrackContent({
const adjustedStartTime = snappedTime - clickOffsetTime;
const finalStartTime = Math.max(
0,
- Math.round(adjustedStartTime * 10) / 10
+ snapTimeToFrame(adjustedStartTime, projectFps)
);
// Check for overlaps with existing elements (excluding the moving element itself)