refactor: move element resize logic to react hook

This commit is contained in:
Maze Winther
2025-07-07 19:13:20 +02:00
parent bd0c7f2206
commit f3763b8465
2 changed files with 98 additions and 55 deletions

View File

@ -17,7 +17,8 @@ import { useTimelineStore } from "@/stores/timeline-store";
import { usePlaybackStore } from "@/stores/playback-store";
import AudioWaveform from "./audio-waveform";
import { toast } from "sonner";
import { TimelineElementProps, ResizeState, TrackType } from "@/types/timeline";
import { TimelineElementProps, TrackType } from "@/types/timeline";
import { useTimelineElementResize } from "@/hooks/use-timeline-element-resize";
import {
DropdownMenu,
DropdownMenuContent,
@ -49,9 +50,21 @@ export function TimelineElement({
} = useTimelineStore();
const { currentTime } = usePlaybackStore();
const [resizing, setResizing] = useState<ResizeState | null>(null);
const [elementMenuOpen, setElementMenuOpen] = useState(false);
const {
resizing,
isResizing,
handleResizeStart,
handleResizeMove,
handleResizeEnd,
} = useTimelineElementResize({
element,
track,
zoomLevel,
onUpdateTrim: updateElementTrim,
});
const effectiveDuration =
element.duration - element.trimStart - element.trimEnd;
const elementWidth = Math.max(80, effectiveDuration * 50 * zoomLevel);
@ -77,59 +90,6 @@ export function TimelineElement({
}
};
// Resize handles for trimming elements
const handleResizeStart = (
e: React.MouseEvent,
elementId: string,
side: "left" | "right"
) => {
e.stopPropagation();
e.preventDefault();
setResizing({
elementId,
side,
startX: e.clientX,
initialTrimStart: element.trimStart,
initialTrimEnd: element.trimEnd,
});
};
const updateTrimFromMouseMove = (e: { clientX: number }) => {
if (!resizing) return;
const deltaX = e.clientX - resizing.startX;
const deltaTime = deltaX / (50 * zoomLevel);
if (resizing.side === "left") {
const newTrimStart = Math.max(
0,
Math.min(
element.duration - element.trimEnd - 0.1,
resizing.initialTrimStart + deltaTime
)
);
updateElementTrim(track.id, element.id, newTrimStart, element.trimEnd);
} else {
const newTrimEnd = Math.max(
0,
Math.min(
element.duration - element.trimStart - 0.1,
resizing.initialTrimEnd - deltaTime
)
);
updateElementTrim(track.id, element.id, element.trimStart, newTrimEnd);
}
};
const handleResizeMove = (e: React.MouseEvent) => {
updateTrimFromMouseMove(e);
};
const handleResizeEnd = () => {
setResizing(null);
};
const handleDeleteElement = () => {
removeElementFromTrack(track.id, element.id);
setElementMenuOpen(false);

View File

@ -0,0 +1,83 @@
import { useState } from "react";
import { ResizeState, TimelineElement, TimelineTrack } from "@/types/timeline";
interface UseTimelineElementResizeProps {
element: TimelineElement;
track: TimelineTrack;
zoomLevel: number;
onUpdateTrim: (
trackId: string,
elementId: string,
trimStart: number,
trimEnd: number
) => void;
}
export function useTimelineElementResize({
element,
track,
zoomLevel,
onUpdateTrim,
}: UseTimelineElementResizeProps) {
const [resizing, setResizing] = useState<ResizeState | null>(null);
const handleResizeStart = (
e: React.MouseEvent,
elementId: string,
side: "left" | "right"
) => {
e.stopPropagation();
e.preventDefault();
setResizing({
elementId,
side,
startX: e.clientX,
initialTrimStart: element.trimStart,
initialTrimEnd: element.trimEnd,
});
};
const updateTrimFromMouseMove = (e: { clientX: number }) => {
if (!resizing) return;
const deltaX = e.clientX - resizing.startX;
const deltaTime = deltaX / (50 * zoomLevel);
if (resizing.side === "left") {
const newTrimStart = Math.max(
0,
Math.min(
element.duration - element.trimEnd - 0.1,
resizing.initialTrimStart + deltaTime
)
);
onUpdateTrim(track.id, element.id, newTrimStart, element.trimEnd);
} else {
const newTrimEnd = Math.max(
0,
Math.min(
element.duration - element.trimStart - 0.1,
resizing.initialTrimEnd - deltaTime
)
);
onUpdateTrim(track.id, element.id, element.trimStart, newTrimEnd);
}
};
const handleResizeMove = (e: React.MouseEvent) => {
updateTrimFromMouseMove(e);
};
const handleResizeEnd = () => {
setResizing(null);
};
return {
resizing,
isResizing: resizing !== null,
handleResizeStart,
handleResizeMove,
handleResizeEnd,
};
}