Merge branch 'fix-issue-#131'
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -31,4 +31,5 @@ node_modules
|
|||||||
|
|
||||||
# cursor
|
# cursor
|
||||||
|
|
||||||
.cursor/
|
.cursor/
|
||||||
|
bun.lockb
|
@ -68,4 +68,4 @@
|
|||||||
"tsx": "^4.7.1",
|
"tsx": "^4.7.1",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Button } from "../ui/button";
|
|
||||||
import { AspectRatio } from "../ui/aspect-ratio";
|
|
||||||
import { DragOverlay } from "../ui/drag-overlay";
|
|
||||||
import { useMediaStore, type MediaItem } from "@/stores/media-store";
|
|
||||||
import { processMediaFiles } from "@/lib/media-processing";
|
|
||||||
import { Plus, Image, Video, Music, Trash2, Upload } from "lucide-react";
|
|
||||||
import { useDragDrop } from "@/hooks/use-drag-drop";
|
import { useDragDrop } from "@/hooks/use-drag-drop";
|
||||||
|
import { processMediaFiles } from "@/lib/media-processing";
|
||||||
|
import { useMediaStore, type MediaItem } from "@/stores/media-store";
|
||||||
|
import { useTimelineStore } from "@/stores/timeline-store";
|
||||||
|
import { Image, Music, Plus, Trash2, Upload, Video } from "lucide-react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import { AspectRatio } from "../ui/aspect-ratio";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { DragOverlay } from "../ui/drag-overlay";
|
||||||
|
|
||||||
// MediaPanel lets users add, view, and drag media (images, videos, audio) into the project.
|
// MediaPanel lets users add, view, and drag media (images, videos, audio) into the project.
|
||||||
// You can upload files or drag them from your computer. Dragging from here to the timeline adds them to your video project.
|
// You can upload files or drag them from your computer. Dragging from here to the timeline adds them to your video project.
|
||||||
@ -58,6 +59,21 @@ export function MediaPanel() {
|
|||||||
const handleRemove = (e: React.MouseEvent, id: string) => {
|
const handleRemove = (e: React.MouseEvent, id: string) => {
|
||||||
// Remove a media item from the store
|
// Remove a media item from the store
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
|
||||||
|
// Remove tracks automatically when delete media
|
||||||
|
const { tracks, removeTrack } = useTimelineStore.getState();
|
||||||
|
tracks.forEach((track) => {
|
||||||
|
const clipsToRemove = track.clips.filter((clip) => clip.mediaId === id);
|
||||||
|
clipsToRemove.forEach((clip) => {
|
||||||
|
useTimelineStore.getState().removeClipFromTrack(track.id, clip.id);
|
||||||
|
});
|
||||||
|
// Only remove track if it becomes empty and has no other clips
|
||||||
|
const updatedTrack = useTimelineStore.getState().tracks.find(t => t.id === track.id);
|
||||||
|
if (updatedTrack && updatedTrack.clips.length === 0) {
|
||||||
|
removeTrack(track.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
removeMediaItem(id);
|
removeMediaItem(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1631,36 +1631,6 @@ function TimelineTrackContent({
|
|||||||
onDragEnd={handleClipDragEnd}
|
onDragEnd={handleClipDragEnd}
|
||||||
>
|
>
|
||||||
{renderClipContent(clip)}
|
{renderClipContent(clip)}
|
||||||
{/* Clip options menu */}
|
|
||||||
<div className="absolute top-1 right-1 z-10">
|
|
||||||
<Button
|
|
||||||
variant="text"
|
|
||||||
size="icon"
|
|
||||||
className="opacity-0 group-hover:opacity-100 transition-opacity"
|
|
||||||
onClick={() => setClipMenuOpen(clip.id)}
|
|
||||||
>
|
|
||||||
<MoreVertical className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
{clipMenuOpen === clip.id && (
|
|
||||||
<div className="absolute right-0 mt-2 w-32 bg-white text-black border rounded shadow z-50">
|
|
||||||
<button
|
|
||||||
className="flex items-center w-full px-3 py-2 text-sm hover:bg-muted/30"
|
|
||||||
onClick={() => {
|
|
||||||
handleSplitClip(clip);
|
|
||||||
setClipMenuOpen(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Scissors className="h-4 w-4 mr-2" /> Split
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="flex items-center w-full px-3 py-2 text-sm text-red-600 hover:bg-red-50"
|
|
||||||
onClick={() => handleDeleteClip(clip.id)}
|
|
||||||
>
|
|
||||||
<Trash2 className="h-4 w-4 mr-2" /> Delete
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/* Right trim handle */}
|
{/* Right trim handle */}
|
||||||
<div
|
<div
|
||||||
|
Reference in New Issue
Block a user