diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-03-31 23:23:36 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-03-31 23:23:36 +0200 |
| commit | f1d5932c54178c4f8eac61d3d3e0e4a30101780f (patch) | |
| tree | 73ebf833517b1f0a9925151a703f335bedf49216 /apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx | |
| parent | d23be079cce6108482fc3e85401cccf949087174 (diff) | |
| download | opencut-f1d5932c54178c4f8eac61d3d3e0e4a30101780f.tar.gz | |
feat: separate audio from elements
Diffstat (limited to 'apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx')
| -rw-r--r-- | apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx b/apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx index f398264c..abe36f88 100644 --- a/apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx +++ b/apps/web/src/components/editor/panels/timeline/timeline-toolbar.tsx @@ -1,4 +1,5 @@ import { useEditor } from "@/hooks/use-editor"; +import { useElementSelection } from "@/hooks/timeline/element/use-element-selection"; import { TooltipProvider, Tooltip, @@ -6,7 +7,6 @@ import { TooltipContent, } from "@/components/ui/tooltip"; import { Button } from "@/components/ui/button"; -import { SplitSquareHorizontal } from "lucide-react"; import { SplitButton, SplitButtonLeft, @@ -18,6 +18,12 @@ import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; import { sliderToZoom, zoomToSlider } from "@/lib/timeline/zoom-utils"; import { ScenesView } from "@/components/editor/scenes-view"; import { type TActionWithOptionalArgs, invokeAction } from "@/lib/actions"; +import { + canToggleSourceAudio, + getSourceAudioActionLabel, + isSourceAudioSeparated, +} from "@/lib/timeline/audio-separation"; +import { hasMediaId } from "@/lib/timeline"; import { cn } from "@/utils/ui"; import { useTimelineStore } from "@/stores/timeline-store"; import { ScrollArea } from "@/components/ui/scroll-area"; @@ -33,8 +39,10 @@ import { Copy01Icon, AlignLeftIcon, AlignRightIcon, + Link02Icon, Layers01Icon, Chart03Icon, + Unlink02Icon, } from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/react"; import { OcRippleIcon } from "@/components/icons"; @@ -78,9 +86,47 @@ export function TimelineToolbar({ } function ToolbarLeftSection() { + const editor = useEditor(); + const mediaAssets = useEditor((currentEditor) => currentEditor.media.getAssets()); + const { selectedElements } = useElementSelection(); const isCurrentlyBookmarked = useEditor((e) => e.scenes.isBookmarked({ time: e.playback.getCurrentTime() }), ); + const selectedElement = + selectedElements.length === 1 + ? (editor.timeline.getElementsWithTracks({ + elements: selectedElements, + })[0] ?? null) + : null; + const selectedMediaAsset = (() => { + if (!selectedElement) { + return null; + } + + const { element } = selectedElement; + if (!hasMediaId(element)) { + return null; + } + + return mediaAssets.find((asset) => asset.id === element.mediaId) ?? null; + })(); + const canToggleSelectedSourceAudio = + !!selectedElement && + canToggleSourceAudio({ + element: selectedElement.element, + mediaAsset: selectedMediaAsset, + }); + const sourceAudioLabel = + selectedElement?.element.type === "video" + ? getSourceAudioActionLabel({ + element: selectedElement.element, + }) + : "Extract audio"; + const isSelectedSourceAudioSeparated = + selectedElement?.element.type === "video" && + isSourceAudioSeparated({ + element: selectedElement.element, + }); const handleAction = ({ action, @@ -117,10 +163,16 @@ function ToolbarLeftSection() { /> <ToolbarButton - icon={<SplitSquareHorizontal />} - tooltip="Separate audio (coming soon)" - disabled={true} - onClick={({ event: _event }) => {}} + icon={ + <HugeiconsIcon + icon={isSelectedSourceAudioSeparated ? Unlink02Icon : Link02Icon} + /> + } + tooltip={sourceAudioLabel} + disabled={!canToggleSelectedSourceAudio} + onClick={({ event }) => + handleAction({ action: "toggle-source-audio", event }) + } /> <ToolbarButton @@ -275,6 +327,7 @@ function ToolbarButton({ <Button variant={isActive ? "secondary" : "text"} size="icon" + disabled={disabled} onClick={(event) => onClick({ event })} className={cn( "rounded-sm", |
