summaryrefslogtreecommitdiff
path: root/apps/web/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components')
-rw-r--r--apps/web/src/components/editor/timeline-track.tsx137
-rw-r--r--apps/web/src/components/landing/hero.tsx18
2 files changed, 71 insertions, 84 deletions
diff --git a/apps/web/src/components/editor/timeline-track.tsx b/apps/web/src/components/editor/timeline-track.tsx
index c3a16b9a..033b79a6 100644
--- a/apps/web/src/components/editor/timeline-track.tsx
+++ b/apps/web/src/components/editor/timeline-track.tsx
@@ -33,6 +33,7 @@ export function TimelineTrackContent({
const { mediaItems } = useMediaStore();
const {
tracks,
+ addTrack,
moveElementToTrack,
updateElementStartTime,
addElementToTrack,
@@ -495,6 +496,16 @@ export function TimelineTrackContent({
e.preventDefault();
e.stopPropagation();
+ // Debug logging
+ console.log(
+ JSON.stringify({
+ message: "Drop event started in timeline track",
+ dataTransferTypes: Array.from(e.dataTransfer.types),
+ trackId: track.id,
+ trackType: track.type,
+ })
+ );
+
// Reset all drag states
dragCounterRef.current = 0;
setIsDropping(false);
@@ -727,68 +738,28 @@ export function TimelineTrackContent({
// Handle position-aware track creation for media elements
if (!isCompatible || dropPosition !== "on") {
- const needsNewTrack = !isCompatible || dropPosition !== "on";
-
- if (needsNewTrack) {
- if (isVideoOrImage) {
- // For video/image, check if we need a main track or additional media track
- const mainTrack = getMainTrack(tracks);
-
- if (!mainTrack) {
- // No main track exists, create it
- const updatedTracks = ensureMainTrack(tracks);
- const newMainTrack = getMainTrack(updatedTracks);
- if (newMainTrack && newMainTrack.elements.length === 0) {
- targetTrackId = newMainTrack.id;
- targetTrack = newMainTrack;
- } else {
- // Main track was created but somehow has elements, create new media track
- const mainTrackIndex = updatedTracks.findIndex(
- (t) => t.id === newMainTrack?.id
- );
- targetTrackId = insertTrackAt("media", mainTrackIndex);
- const updatedTracksAfterInsert =
- useTimelineStore.getState().tracks;
- const newTargetTrack = updatedTracksAfterInsert.find(
- (t) => t.id === targetTrackId
- );
- if (!newTargetTrack) return;
- targetTrack = newTargetTrack;
- }
- } else if (
- mainTrack.elements.length === 0 &&
- dropPosition === "on"
- ) {
- // Main track exists and is empty, use it
- targetTrackId = mainTrack.id;
- targetTrack = mainTrack;
- } else {
- // Create new media track above main track
- const mainTrackIndex = tracks.findIndex(
- (t) => t.id === mainTrack.id
- );
- let insertIndex: number;
+ if (isVideoOrImage) {
+ // For video/image, check if we need a main track or additional media track
+ const mainTrack = getMainTrack(tracks);
- if (dropPosition === "above") {
- insertIndex = currentTrackIndex;
- } else if (dropPosition === "below") {
- insertIndex = currentTrackIndex + 1;
- } else {
- // Insert above main track
- insertIndex = mainTrackIndex;
- }
-
- targetTrackId = insertTrackAt("media", insertIndex);
- const updatedTracks = useTimelineStore.getState().tracks;
- const newTargetTrack = updatedTracks.find(
- (t) => t.id === targetTrackId
- );
- if (!newTargetTrack) return;
- targetTrack = newTargetTrack;
- }
- } else if (isAudio) {
- // Audio tracks go at the bottom
- const mainTrack = getMainTrack(tracks);
+ if (!mainTrack) {
+ // No main track exists, create it
+ targetTrackId = addTrack("media");
+ const updatedTracks = useTimelineStore.getState().tracks;
+ const newTargetTrack = updatedTracks.find(
+ (t) => t.id === targetTrackId
+ );
+ if (!newTargetTrack) return;
+ targetTrack = newTargetTrack;
+ } else if (
+ mainTrack.elements.length === 0 &&
+ dropPosition === "on"
+ ) {
+ // Main track exists and is empty, use it
+ targetTrackId = mainTrack.id;
+ targetTrack = mainTrack;
+ } else {
+ // Create new media track
let insertIndex: number;
if (dropPosition === "above") {
@@ -796,18 +767,14 @@ export function TimelineTrackContent({
} else if (dropPosition === "below") {
insertIndex = currentTrackIndex + 1;
} else {
- // Insert after main track (bottom area)
- if (mainTrack) {
- const mainTrackIndex = tracks.findIndex(
- (t) => t.id === mainTrack.id
- );
- insertIndex = mainTrackIndex + 1;
- } else {
- insertIndex = tracks.length; // Bottom of timeline
- }
+ // Insert above main track
+ const mainTrackIndex = tracks.findIndex(
+ (t) => t.id === mainTrack.id
+ );
+ insertIndex = mainTrackIndex;
}
- targetTrackId = insertTrackAt("audio", insertIndex);
+ targetTrackId = insertTrackAt("media", insertIndex);
const updatedTracks = useTimelineStore.getState().tracks;
const newTargetTrack = updatedTracks.find(
(t) => t.id === targetTrackId
@@ -815,6 +782,34 @@ export function TimelineTrackContent({
if (!newTargetTrack) return;
targetTrack = newTargetTrack;
}
+ } else if (isAudio) {
+ // Audio tracks go at the bottom
+ const mainTrack = getMainTrack(tracks);
+ let insertIndex: number;
+
+ if (dropPosition === "above") {
+ insertIndex = currentTrackIndex;
+ } else if (dropPosition === "below") {
+ insertIndex = currentTrackIndex + 1;
+ } else {
+ // Insert after main track (bottom area)
+ if (mainTrack) {
+ const mainTrackIndex = tracks.findIndex(
+ (t) => t.id === mainTrack.id
+ );
+ insertIndex = mainTrackIndex + 1;
+ } else {
+ insertIndex = tracks.length; // Bottom of timeline
+ }
+ }
+
+ targetTrackId = insertTrackAt("audio", insertIndex);
+ const updatedTracks = useTimelineStore.getState().tracks;
+ const newTargetTrack = updatedTracks.find(
+ (t) => t.id === targetTrackId
+ );
+ if (!newTargetTrack) return;
+ targetTrack = newTargetTrack;
}
}
diff --git a/apps/web/src/components/landing/hero.tsx b/apps/web/src/components/landing/hero.tsx
index 776cc654..01ad7e7e 100644
--- a/apps/web/src/components/landing/hero.tsx
+++ b/apps/web/src/components/landing/hero.tsx
@@ -5,7 +5,7 @@ import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { ArrowRight } from "lucide-react";
import { useState } from "react";
-import { useToast } from "@/hooks/use-toast";
+import { toast } from "sonner";
import Image from "next/image";
import { Handlebars } from "./handlebars";
@@ -17,16 +17,13 @@ interface HeroProps {
export function Hero({ signupCount }: HeroProps) {
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
- const { toast } = useToast();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!email.trim()) {
- toast({
- title: "Email required",
+ toast.error("Email required", {
description: "Please enter your email address.",
- variant: "destructive",
});
return;
}
@@ -45,25 +42,20 @@ export function Hero({ signupCount }: HeroProps) {
const data = (await response.json()) as { error: string };
if (response.ok) {
- toast({
- title: "Welcome to the waitlist! 🎉",
+ toast.success("Welcome to the waitlist! 🎉", {
description: "You'll be notified when we launch.",
});
setEmail("");
} else {
- toast({
- title: "Oops!",
+ toast.error("Oops!", {
description:
(data as { error: string }).error ||
"Something went wrong. Please try again.",
- variant: "destructive",
});
}
} catch (error) {
- toast({
- title: "Network error",
+ toast.error("Network error", {
description: "Please check your connection and try again.",
- variant: "destructive",
});
} finally {
setIsSubmitting(false);