what am i doing

This commit is contained in:
Maze Winther
2026-01-21 14:54:12 +01:00
parent afdf7d22cf
commit f3c91d5cb4
29 changed files with 1881 additions and 2326 deletions
@@ -11,7 +11,7 @@ import { Loader2 } from "lucide-react";
import type { TranscriptionProgress } from "@/types/transcription";
import { transcriptionService } from "@/services/transcription";
import { decodeAudioToFloat32 } from "@/lib/media/audio";
import { buildCaptionChunks } from "@/lib/utils/caption-utils";
import { buildCaptionChunks } from "@/lib/transcription/caption";
export function Captions() {
const [selectedLanguage, setSelectedLanguage] = useState("auto");
@@ -35,7 +35,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { DraggableItem } from "@/components/ui/draggable-item";
import { DraggableItem } from "@/components/editor/draggable-item";
import {
Tooltip,
TooltipContent,
@@ -33,7 +33,7 @@ import {
} from "@/lib/iconify-api";
import { cn } from "@/utils/ui";
import Image from "next/image";
import { DraggableItem } from "@/components/ui/draggable-item";
import { DraggableItem } from "@/components/editor/draggable-item";
import { InputWithBack } from "@/components/ui/input-with-back";
import type { StickerCategory } from "@/types/stickers";
import { STICKER_CATEGORIES } from "@/constants/stickers-constants";
@@ -208,17 +208,17 @@ function StickersContentView({ category }: { category: StickerCategory }) {
const collection = collections[c.prefix];
return collection
? {
prefix: c.prefix,
name: c.name,
total: collection.total,
}
prefix: c.prefix,
name: c.name,
total: collection.total,
}
: null;
})
.filter(Boolean) as Array<{
prefix: string;
name: string;
total: number;
}>;
prefix: string;
name: string;
total: number;
}>;
}, [collections, category]);
const { scrollAreaRef, handleScroll } = useInfiniteScroll({
@@ -531,10 +531,10 @@ function StickerItem({
hostIndex === 0
? getIconSvgUrl(iconName, { width: 64, height: 64 })
: buildIconSvgUrl(
ICONIFY_HOSTS[Math.min(hostIndex, ICONIFY_HOSTS.length - 1)],
iconName,
{ width: 64, height: 64 },
)
ICONIFY_HOSTS[Math.min(hostIndex, ICONIFY_HOSTS.length - 1)],
iconName,
{ width: 64, height: 64 },
)
}
alt={displayName}
width={64}
@@ -543,9 +543,9 @@ function StickerItem({
style={
capSize
? {
maxWidth: "var(--sticker-max, 160px)",
maxHeight: "var(--sticker-max, 160px)",
}
maxWidth: "var(--sticker-max, 160px)",
maxHeight: "var(--sticker-max, 160px)",
}
: undefined
}
onError={() => {
@@ -1,4 +1,4 @@
import { DraggableItem } from "@/components/ui/draggable-item";
import { DraggableItem } from "@/components/editor/draggable-item";
import { PanelBaseView as BaseView } from "@/components/editor/panel-base-view";
import { useEditor } from "@/hooks/use-editor";
import { DEFAULT_TEXT_ELEMENT } from "@/constants/text-constants";
@@ -19,7 +19,7 @@ import {
} from "../ui/dropdown-menu";
import Link from "next/link";
import { RenameProjectDialog } from "../rename-project-dialog";
import { DeleteProjectDialog } from "../delete-project-dialog";
import { DeleteProjectDialog } from "./delete-project-dialog";
import { useRouter } from "next/navigation";
import { FaDiscord } from "react-icons/fa6";
import { ExportButton } from "./export-button";
@@ -9,7 +9,7 @@ import { RadioGroup, RadioGroupItem } from "../ui/radio-group";
import { Progress } from "../ui/progress";
import { Checkbox } from "../ui/checkbox";
import { cn } from "@/utils/ui";
import { getExportMimeType, getExportFileExtension } from "@/utils/export";
import { getExportMimeType, getExportFileExtension } from "@/lib/export";
import { Check, Copy, Download, RotateCcw, X } from "lucide-react";
import {
EXPORT_FORMAT_VALUES,
@@ -108,7 +108,6 @@ function ExportPopover({
setExportResult(result);
if (result.success && result.buffer) {
// Download the file
const mimeType = getExportMimeType({ format });
const extension = getExportFileExtension({ format });
const blob = new Blob([result.buffer], { type: mimeType });
@@ -36,13 +36,12 @@ import {
getTotalTracksHeight,
canTracktHaveAudio,
canTrackBeHidden,
isMainTrack,
getTimelineZoomMin,
} from "@/lib/timeline";
import { TimelineToolbar } from "./timeline-toolbar";
import { useScrollSync } from "@/hooks/timeline/use-scroll-sync";
import { useElementSelection } from "@/hooks/timeline/element/use-element-selection";
import { useTimelineInteractions } from "@/hooks/timeline/use-timeline-interactions";
import { useTimelineSeek } from "@/hooks/timeline/use-timeline-seek";
import { useTimelineDragDrop } from "@/hooks/timeline/use-timeline-drag-drop";
import { TimelineRuler } from "./timeline-ruler";
import { TimelineBookmarksRow } from "./bookmarks";
@@ -162,7 +161,7 @@ export function Timeline() {
handleTracksClick,
handleRulerMouseDown,
handleRulerClick,
} = useTimelineInteractions({
} = useTimelineSeek({
playheadRef,
trackLabelsRef,
rulerScrollRef,
@@ -33,7 +33,7 @@ import {
import { Slider } from "@/components/ui/slider";
import { formatTimeCode } from "@/lib/time";
import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
import { EditableTimecode } from "@/components/ui/editable-timecode";
import { EditableTimecode } from "@/components/editor/editable-timecode";
import { ScenesView } from "../scenes-view";
import { type TAction, invokeAction } from "@/lib/actions";
import { cn } from "@/utils/ui";
-132
View File
@@ -1,132 +0,0 @@
"use client";
import { useEditor } from "@/hooks/use-editor";
import { useRef, useEffect } from "react";
interface AudioPlayerProps {
src: string;
className?: string;
clipStartTime: number;
trimStart: number;
trimEnd: number;
clipDuration: number;
trackMuted?: boolean;
}
export function AudioPlayer({
src,
className = "",
clipStartTime,
trimStart,
trimEnd,
clipDuration,
trackMuted = false,
}: AudioPlayerProps) {
const audioRef = useRef<HTMLAudioElement>(null);
const editor = useEditor();
const currentTime = editor.playback.getCurrentTime();
const isPlaying = editor.playback.getIsPlaying();
const volume = editor.playback.getVolume();
const muted = editor.playback.isMuted();
const speed = editor.playback.getSpeed();
// Calculate if we're within this clip's timeline range
const clipEndTime = clipStartTime + (clipDuration - trimStart - trimEnd);
const isInClipRange =
currentTime >= clipStartTime && currentTime < clipEndTime;
// Sync playback events
useEffect(() => {
const audio = audioRef.current;
if (!audio || !isInClipRange) return;
const handleSeekEvent = (e: CustomEvent) => {
// Always update audio time, even if outside clip range
const timelineTime = e.detail.time;
const audioTime = Math.max(
trimStart,
Math.min(
clipDuration - trimEnd,
timelineTime - clipStartTime + trimStart,
),
);
audio.currentTime = audioTime;
};
const handleUpdateEvent = (e: CustomEvent) => {
// Always update audio time, even if outside clip range
const timelineTime = e.detail.time;
const targetTime = Math.max(
trimStart,
Math.min(
clipDuration - trimEnd,
timelineTime - clipStartTime + trimStart,
),
);
if (Math.abs(audio.currentTime - targetTime) > 0.5) {
audio.currentTime = targetTime;
}
};
const handleSpeed = (e: CustomEvent) => {
audio.playbackRate = e.detail.speed;
};
window.addEventListener("playback-seek", handleSeekEvent as EventListener);
window.addEventListener(
"playback-update",
handleUpdateEvent as EventListener,
);
window.addEventListener("playback-speed", handleSpeed as EventListener);
return () => {
window.removeEventListener(
"playback-seek",
handleSeekEvent as EventListener,
);
window.removeEventListener(
"playback-update",
handleUpdateEvent as EventListener,
);
window.removeEventListener(
"playback-speed",
handleSpeed as EventListener,
);
};
}, [clipStartTime, trimStart, trimEnd, clipDuration, isInClipRange]);
// Sync playback state
useEffect(() => {
const audio = audioRef.current;
if (!audio) return;
if (isPlaying && isInClipRange && !trackMuted) {
audio.play().catch(() => {});
} else {
audio.pause();
}
}, [isPlaying, isInClipRange, trackMuted]);
// Sync volume and speed
useEffect(() => {
const audio = audioRef.current;
if (!audio) return;
audio.volume = volume;
audio.muted = muted || trackMuted;
audio.playbackRate = speed;
}, [volume, speed, muted, trackMuted]);
return (
<audio
ref={audioRef}
src={src}
className={className}
preload="auto"
controls={false}
style={{ display: "none" }} // Audio elements don't need visual representation
onContextMenu={(e) => e.preventDefault()}
/>
);
}