Merge branch 'feature/plus-button-timeline' into staging

This commit is contained in:
Maze Winther
2025-07-15 16:28:08 +02:00
6 changed files with 179 additions and 62 deletions
@@ -24,6 +24,7 @@ import {
} from "@/components/ui/select";
import { DraggableMediaItem } from "@/components/ui/draggable-item";
import { useProjectStore } from "@/stores/project-store";
import { addMediaToTimeline } from "@/lib/timeline-utils";
export function MediaView() {
const { mediaItems, addMediaItem, removeMediaItem } = useMediaStore();
@@ -288,6 +289,7 @@ export function MediaView() {
name: item.name,
}}
showPlusOnDrag={false}
onAddToTimeline={(currentTime) => addMediaToTimeline(item, currentTime)}
rounded={false}
/>
</ContextMenuTrigger>
@@ -1,4 +1,30 @@
import { DraggableMediaItem } from "@/components/ui/draggable-item";
import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
import { addTextToTimeline } from "@/lib/timeline-utils";
import { type TextElement } from "@/types/timeline";
let textData: TextElement = {
id: "default-text",
type: "text",
name: "Default text",
content: "Default text",
fontSize: 48,
fontFamily: "Arial",
color: "#ffffff",
backgroundColor: "transparent",
textAlign: "center" as const,
fontWeight: "normal" as const,
fontStyle: "normal" as const,
textDecoration: "none" as const,
x: 0,
y: 0,
rotation: 0,
opacity: 1,
duration: TIMELINE_CONSTANTS.DEFAULT_TEXT_DURATION,
startTime: 0,
trimStart: 0,
trimEnd: 0,
};
export function TextView() {
return (
@@ -11,12 +37,13 @@ export function TextView() {
</div>
}
dragData={{
id: "default-text",
type: "text",
name: "Default text",
content: "Default text",
id: textData.id,
type: textData.type,
name: textData.name,
content: textData.content,
}}
aspectRatio={1}
onAddToTimeline={(currentTime) => addTextToTimeline(textData, currentTime)}
showLabel={false}
/>
</div>
+9 -55
View File
@@ -48,6 +48,7 @@ import { useSelectionBox } from "@/hooks/use-selection-box";
import { SnapIndicator } from "./snap-indicator";
import { SnapPoint } from "@/hooks/use-timeline-snapping";
import type { DragData, TimelineTrack } from "@/types/timeline";
import { addTextToNewTrack, addMediaToNewTrack } from "@/lib/timeline-utils";
import {
getTrackHeight,
getCumulativeHeightBefore,
@@ -228,7 +229,7 @@ export function Timeline() {
Math.min(
duration,
(mouseX + scrollLeft) /
(TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel)
(TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel)
)
);
@@ -376,29 +377,7 @@ export function Timeline() {
if (dragData.type === "text") {
// Always create new text track to avoid overlaps
const newTrackId = addTrack("text");
addElementToTrack(newTrackId, {
type: "text",
name: dragData.name || "Text",
content: dragData.content || "Default Text",
duration: TIMELINE_CONSTANTS.DEFAULT_TEXT_DURATION,
startTime: 0,
trimStart: 0,
trimEnd: 0,
fontSize: 48,
fontFamily: "Arial",
color: "#ffffff",
backgroundColor: "transparent",
textAlign: "center",
fontWeight: "normal",
fontStyle: "normal",
textDecoration: "none",
x: 0,
y: 0,
rotation: 0,
opacity: 1,
});
addTextToNewTrack(dragData);
} else {
// Handle media items
const mediaItem = mediaItems.find((item) => item.id === dragData.id);
@@ -407,19 +386,7 @@ export function Timeline() {
return;
}
const trackType = dragData.type === "audio" ? "audio" : "media";
let targetTrack = tracks.find((t) => t.type === trackType);
const newTrackId = targetTrack ? targetTrack.id : addTrack(trackType);
addElementToTrack(newTrackId, {
type: "media",
mediaId: mediaItem.id,
name: mediaItem.name,
duration: mediaItem.duration || 5,
startTime: 0,
trimStart: 0,
trimEnd: 0,
});
addMediaToNewTrack(mediaItem);
}
} catch (error) {
console.error("Error parsing dropped item data:", error);
@@ -447,18 +414,7 @@ export function Timeline() {
item.name === processedItem.name && item.url === processedItem.url
);
if (addedItem) {
const trackType =
processedItem.type === "audio" ? "audio" : "media";
const newTrackId = addTrack(trackType);
addElementToTrack(newTrackId, {
type: "media",
mediaId: addedItem.id,
name: addedItem.name,
duration: addedItem.duration || 5,
startTime: 0,
trimStart: 0,
trimEnd: 0,
});
addMediaToNewTrack(addedItem);
}
}
} catch (error) {
@@ -946,21 +902,19 @@ export function Timeline() {
return (
<div
key={i}
className={`absolute top-0 bottom-0 ${
isMainMarker
className={`absolute top-0 bottom-0 ${isMainMarker
? "border-l border-muted-foreground/40"
: "border-l border-muted-foreground/20"
}`}
}`}
style={{
left: `${time * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel}px`,
}}
>
<span
className={`absolute top-1 left-1 text-[0.6rem] ${
isMainMarker
className={`absolute top-1 left-1 text-[0.6rem] ${isMainMarker
? "text-muted-foreground font-medium"
: "text-muted-foreground/70"
}`}
}`}
>
{(() => {
const formatTime = (seconds: number) => {