From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- .../editor/panels/timeline/audio-volume-line.tsx | 275 --------------------- 1 file changed, 275 deletions(-) delete mode 100644 apps/web/src/components/editor/panels/timeline/audio-volume-line.tsx (limited to 'apps/web/src/components/editor/panels/timeline/audio-volume-line.tsx') diff --git a/apps/web/src/components/editor/panels/timeline/audio-volume-line.tsx b/apps/web/src/components/editor/panels/timeline/audio-volume-line.tsx deleted file mode 100644 index 208f3beb..00000000 --- a/apps/web/src/components/editor/panels/timeline/audio-volume-line.tsx +++ /dev/null @@ -1,275 +0,0 @@ -"use client"; - -import { useCallback, useRef, useState } from "react"; -import { createPortal } from "react-dom"; -import { useEditor } from "@/hooks/use-editor"; -import { DEFAULTS } from "@/lib/timeline/defaults"; -import { - getDbFromLinePos, - getLinePosFromDb, -} from "@/lib/timeline/audio-display"; -import { VOLUME_DB_MAX, VOLUME_DB_MIN } from "@/lib/timeline/audio-constants"; -import { hasAnimatedVolume } from "@/lib/timeline/audio-state"; -import type { AudioElement } from "@/lib/timeline/types"; -import { - clamp, - formatNumberForDisplay, - getFractionDigitsForStep, - isNearlyEqual, - snapToStep, -} from "@/utils/math"; -import { cn } from "@/utils/ui"; - -const HIT_AREA_HEIGHT_PX = 14; -const TOOLTIP_OFFSET_PX = 10; -const VOLUME_STEP = 0.1; -const VOLUME_FRACTION_DIGITS = getFractionDigitsForStep({ step: VOLUME_STEP }); - -function clampVolume({ value }: { value: number }): number { - return clamp({ - value: snapToStep({ value, step: VOLUME_STEP }), - min: VOLUME_DB_MIN, - max: VOLUME_DB_MAX, - }); -} - -function getVolumeFromPointer({ - clientY, - rect, -}: { - clientY: number; - rect: DOMRect; -}): number { - const clampedOffset = clamp({ - value: clientY - rect.top, - min: 0, - max: rect.height, - }); - const progressPercent = - rect.height <= 0 ? 0 : (clampedOffset / rect.height) * 100; - return clampVolume({ value: getDbFromLinePos({ percent: progressPercent }) }); -} - -export function AudioVolumeLine({ - element, - trackId, -}: { - element: AudioElement; - trackId: string; -}) { - const editor = useEditor(); - const surfaceRef = useRef(null); - const activePointerIdRef = useRef(null); - const startVolumeRef = useRef(element.volume ?? DEFAULTS.element.volume); - const lastPreviewVolumeRef = useRef( - element.volume ?? DEFAULTS.element.volume, - ); - const hasChangedRef = useRef(false); - const [isDragging, setIsDragging] = useState(false); - const [tooltipClientPos, setTooltipClientPos] = useState<{ - x: number; - y: number; - } | null>(null); - - const hasAnimatedEnvelope = hasAnimatedVolume({ element }); - const currentVolume = element.volume ?? DEFAULTS.element.volume; - const lineTop = `${getLinePosFromDb({ db: currentVolume })}%`; - - const volumeLabel = `${formatNumberForDisplay({ - value: currentVolume, - fractionDigits: VOLUME_FRACTION_DIGITS, - })} dB`; - - const previewVolume = useCallback( - (nextVolume: number) => { - if ( - isNearlyEqual({ - leftValue: nextVolume, - rightValue: lastPreviewVolumeRef.current, - }) - ) { - return; - } - - editor.timeline.previewElements({ - updates: [ - { - trackId, - elementId: element.id, - updates: { volume: nextVolume }, - }, - ], - }); - lastPreviewVolumeRef.current = nextVolume; - hasChangedRef.current = !isNearlyEqual({ - leftValue: startVolumeRef.current, - rightValue: nextVolume, - }); - }, - [editor, element.id, trackId], - ); - - const finishDrag = useCallback( - ({ shouldCommit }: { shouldCommit: boolean }) => { - activePointerIdRef.current = null; - setIsDragging(false); - - if (shouldCommit && hasChangedRef.current) { - editor.timeline.commitPreview(); - } else { - editor.timeline.discardPreview(); - } - - hasChangedRef.current = false; - lastPreviewVolumeRef.current = startVolumeRef.current; - setTooltipClientPos(null); - }, - [editor], - ); - - const updateFromPointer = useCallback( - ({ clientX, clientY }: { clientX: number; clientY: number }) => { - const rect = surfaceRef.current?.getBoundingClientRect(); - if (!rect) { - return; - } - - setTooltipClientPos({ - x: clientX + TOOLTIP_OFFSET_PX, - y: clientY - TOOLTIP_OFFSET_PX, - }); - previewVolume(getVolumeFromPointer({ clientY, rect })); - }, - [previewVolume], - ); - - const handleClick = useCallback((event: React.MouseEvent) => { - event.preventDefault(); - event.stopPropagation(); - }, []); - - const handleMouseDown = useCallback((event: React.MouseEvent) => { - event.stopPropagation(); - }, []); - - const handlePointerDown = useCallback( - (event: React.PointerEvent) => { - if (event.button !== 0) { - return; - } - - event.preventDefault(); - event.stopPropagation(); - editor.selection.setSelectedElements({ - elements: [{ trackId, elementId: element.id }], - }); - activePointerIdRef.current = event.pointerId; - startVolumeRef.current = currentVolume; - lastPreviewVolumeRef.current = currentVolume; - hasChangedRef.current = false; - setIsDragging(true); - event.currentTarget.setPointerCapture(event.pointerId); - updateFromPointer({ - clientX: event.clientX, - clientY: event.clientY, - }); - }, - [currentVolume, editor.selection, element.id, trackId, updateFromPointer], - ); - - const handlePointerMove = useCallback( - (event: React.PointerEvent) => { - if (activePointerIdRef.current !== event.pointerId) { - return; - } - - event.preventDefault(); - updateFromPointer({ - clientX: event.clientX, - clientY: event.clientY, - }); - }, - [updateFromPointer], - ); - - const handlePointerUp = useCallback( - (event: React.PointerEvent) => { - if (activePointerIdRef.current !== event.pointerId) { - return; - } - - event.preventDefault(); - event.stopPropagation(); - finishDrag({ shouldCommit: true }); - }, - [finishDrag], - ); - - const handlePointerCancel = useCallback( - (event: React.PointerEvent) => { - if (activePointerIdRef.current !== event.pointerId) { - return; - } - - event.preventDefault(); - event.stopPropagation(); - finishDrag({ shouldCommit: false }); - }, - [finishDrag], - ); - - const handleLostPointerCapture = useCallback(() => { - if (activePointerIdRef.current === null) { - return; - } - - finishDrag({ shouldCommit: hasChangedRef.current }); - }, [finishDrag]); - - if (hasAnimatedEnvelope) { - return null; - } - - return ( -
-
-
- {/* biome-ignore lint/a11y/noStaticElementInteractions: timeline volume line is a pointer-only editing surface */} - {/* biome-ignore lint/a11y/useKeyWithClickEvents: timeline volume line is a pointer-only editing surface */} -
- {isDragging && - tooltipClientPos && - createPortal( -
- {volumeLabel} -
, - document.body, - )} -
-
- ); -} -- cgit v1.3.1