summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/editor')
-rw-r--r--apps/web/src/components/editor/panels/assets/views/captions.tsx2
-rw-r--r--apps/web/src/components/editor/panels/preview/index.tsx4
-rw-r--r--apps/web/src/components/editor/panels/properties/index.tsx2
-rw-r--r--apps/web/src/components/editor/panels/properties/tabs/masks-tab.tsx4
-rw-r--r--apps/web/src/components/editor/panels/timeline/drop-target.ts16
-rw-r--r--apps/web/src/components/editor/panels/timeline/graph-editor/session.ts8
-rw-r--r--apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts3
-rw-r--r--apps/web/src/components/editor/panels/timeline/index.tsx38
8 files changed, 56 insertions, 21 deletions
diff --git a/apps/web/src/components/editor/panels/assets/views/captions.tsx b/apps/web/src/components/editor/panels/assets/views/captions.tsx
index f22c0211..c89e587b 100644
--- a/apps/web/src/components/editor/panels/assets/views/captions.tsx
+++ b/apps/web/src/components/editor/panels/assets/views/captions.tsx
@@ -59,7 +59,7 @@ export function Captions() {
setProcessingStep("Extracting audio...");
const audioBlob = await extractTimelineAudio({
- tracks: editor.timeline.getTracks(),
+ tracks: editor.scenes.getActiveScene().tracks,
mediaAssets: editor.media.getAssets(),
totalDuration: editor.timeline.getTotalDuration(),
});
diff --git a/apps/web/src/components/editor/panels/preview/index.tsx b/apps/web/src/components/editor/panels/preview/index.tsx
index 786d9a46..369d854c 100644
--- a/apps/web/src/components/editor/panels/preview/index.tsx
+++ b/apps/web/src/components/editor/panels/preview/index.tsx
@@ -73,7 +73,9 @@ export function PreviewPanel() {
function RenderTreeController() {
const editor = useEditor();
- const tracks = useEditor((e) => e.timeline.getRenderTracks());
+ const tracks = useEditor(
+ (e) => e.timeline.getPreviewTracks() ?? e.scenes.getActiveScene().tracks,
+ );
const mediaAssets = useEditor((e) => e.media.getAssets());
const activeProject = useEditor((e) => e.project.getActive());
diff --git a/apps/web/src/components/editor/panels/properties/index.tsx b/apps/web/src/components/editor/panels/properties/index.tsx
index 3f3ff1f3..75319ef3 100644
--- a/apps/web/src/components/editor/panels/properties/index.tsx
+++ b/apps/web/src/components/editor/panels/properties/index.tsx
@@ -17,7 +17,7 @@ import { EmptyView } from "./empty-view";
export function PropertiesPanel() {
const editor = useEditor();
- useEditor((e) => e.timeline.getTracks());
+ useEditor((e) => e.scenes.getActiveSceneOrNull());
useEditor((e) => e.media.getAssets());
const { selectedElements } = useElementSelection();
const { activeTabPerType, setActiveTab } = usePropertiesStore();
diff --git a/apps/web/src/components/editor/panels/properties/tabs/masks-tab.tsx b/apps/web/src/components/editor/panels/properties/tabs/masks-tab.tsx
index 9b0ffc88..8148b457 100644
--- a/apps/web/src/components/editor/panels/properties/tabs/masks-tab.tsx
+++ b/apps/web/src/components/editor/panels/properties/tabs/masks-tab.tsx
@@ -87,7 +87,9 @@ export function MasksTab({ element, trackId }: MasksTabProps) {
fallback: element,
});
const maskDefs = masksRegistry.getAll();
- const tracks = useEditor((e) => e.timeline.getRenderTracks());
+ const tracks = useEditor(
+ (e) => e.timeline.getPreviewTracks() ?? e.scenes.getActiveScene().tracks,
+ );
const currentTime = useEditor((e) => e.playback.getCurrentTime());
const mediaAssets = useEditor((e) => e.media.getAssets());
const canvasSize = useEditor(
diff --git a/apps/web/src/components/editor/panels/timeline/drop-target.ts b/apps/web/src/components/editor/panels/timeline/drop-target.ts
index dbd4efaf..f65170fe 100644
--- a/apps/web/src/components/editor/panels/timeline/drop-target.ts
+++ b/apps/web/src/components/editor/panels/timeline/drop-target.ts
@@ -105,6 +105,8 @@ export function computeDropTarget({
excludeElementId,
targetElementTypes,
}: ComputeDropTargetParams): DropTarget {
+ const orderedTracks = [...tracks.overlay, tracks.main, ...tracks.audio];
+ const mainTrackIndex = tracks.overlay.length;
const xPosition =
typeof startTimeOverride === "number"
? startTimeOverride
@@ -112,7 +114,7 @@ export function computeDropTarget({
? playheadTime
: Math.max(0, mouseX / (pixelsPerSecond * zoomLevel));
- if (tracks.length === 0) {
+ if (orderedTracks.length === 0) {
const placementResult = resolveTrackPlacement({
tracks,
elementType,
@@ -139,7 +141,11 @@ export function computeDropTarget({
};
}
- const trackAtMouse = getTrackAtY({ mouseY, tracks, verticalDragDirection });
+ const trackAtMouse = getTrackAtY({
+ mouseY,
+ tracks: orderedTracks,
+ verticalDragDirection,
+ });
if (!trackAtMouse) {
const isAboveAllTracks = mouseY < 0;
@@ -150,7 +156,7 @@ export function computeDropTarget({
timeSpans: [{ startTime: xPosition, duration: elementDuration, excludeElementId }],
strategy: {
type: "preferIndex",
- trackIndex: isAboveAllTracks ? 0 : tracks.length - 1,
+ trackIndex: isAboveAllTracks ? 0 : orderedTracks.length - 1,
hoverDirection: isAboveAllTracks ? "above" : "below",
createNewTrackOnly: true,
},
@@ -171,12 +177,12 @@ export function computeDropTarget({
}
const { trackIndex, relativeY } = trackAtMouse;
- const track = tracks[trackIndex];
+ const track = orderedTracks[trackIndex];
if (targetElementTypes && targetElementTypes.length > 0) {
const targetElement = findElementAtPosition({
mouseX,
- tracks,
+ tracks: orderedTracks,
trackIndex,
targetElementTypes,
pixelsPerSecond,
diff --git a/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts b/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts
index e16690e5..15657bfb 100644
--- a/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts
+++ b/apps/web/src/components/editor/panels/timeline/graph-editor/session.ts
@@ -13,7 +13,7 @@ import type {
ScalarGraphKeyframeContext,
SelectedKeyframeRef,
} from "@/lib/animation/types";
-import type { TimelineElement, TimelineTrack } from "@/lib/timeline";
+import type { SceneTracks, TimelineElement } from "@/lib/timeline";
const GRAPH_LINEAR_CURVE: NormalizedCubicBezier = [0, 0, 1, 1];
const FLAT_VALUE_EPSILON = 1e-6;
@@ -91,10 +91,10 @@ function findElementByKeyframe({
tracks,
keyframe,
}: {
- tracks: TimelineTrack[];
+ tracks: SceneTracks;
keyframe: SelectedKeyframeRef;
}): { element: TimelineElement; trackId: string; elementId: string } | null {
- for (const track of tracks) {
+ for (const track of [...tracks.overlay, tracks.main, ...tracks.audio]) {
if (track.id !== keyframe.trackId) {
continue;
}
@@ -180,7 +180,7 @@ export function resolveGraphEditorSelectionState({
selectedKeyframes,
preferredComponentKey,
}: {
- tracks: TimelineTrack[];
+ tracks: SceneTracks;
selectedKeyframes: SelectedKeyframeRef[];
preferredComponentKey?: string | null;
}): GraphEditorSelectionState {
diff --git a/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts b/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts
index 41df702f..d0303b6f 100644
--- a/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts
+++ b/apps/web/src/components/editor/panels/timeline/graph-editor/use-controller.ts
@@ -15,7 +15,8 @@ import {
export function useGraphEditorController() {
const editor = useEditor();
const renderTracks = useEditor((currentEditor) =>
- currentEditor.timeline.getRenderTracks(),
+ currentEditor.timeline.getPreviewTracks() ??
+ currentEditor.scenes.getActiveScene().tracks,
);
const { selectedKeyframes } = useKeyframeSelection();
const [open, setOpen] = useState(false);
diff --git a/apps/web/src/components/editor/panels/timeline/index.tsx b/apps/web/src/components/editor/panels/timeline/index.tsx
index 11abfd68..883011d1 100644
--- a/apps/web/src/components/editor/panels/timeline/index.tsx
+++ b/apps/web/src/components/editor/panels/timeline/index.tsx
@@ -58,7 +58,6 @@ import {
} from "./track-layout";
import { SELECTED_TRACK_ROW_CLASS } from "./theme";
import { TIMELINE_HORIZONTAL_WHEEL_STEP_PX } from "./interaction";
-import { isMainTrack } from "@/lib/timeline/placement";
import { TimelineToolbar } from "./timeline-toolbar";
import { useElementSelection } from "@/hooks/timeline/element/use-element-selection";
import { useTimelineSeek } from "@/hooks/timeline/use-timeline-seek";
@@ -112,7 +111,15 @@ export function Timeline() {
} = useElementSelection();
const editor = useEditor();
const timeline = editor.timeline;
- const tracks = useEditor((editor) => editor.timeline.getTracks());
+ const scene = useEditor((currentEditor) => currentEditor.scenes.getActiveSceneOrNull());
+ const tracks = useMemo<TimelineTrack[]>(
+ () =>
+ scene
+ ? [...scene.tracks.overlay, scene.tracks.main, ...scene.tracks.audio]
+ : [],
+ [scene],
+ );
+ const mainTrackId = scene?.tracks.main.id ?? null;
const seek = (time: number) => editor.playback.seek({ time });
const timelineRef = useRef<HTMLDivElement>(null);
@@ -424,13 +431,13 @@ export function Timeline() {
/>
<DragLine
dropTarget={dropTarget}
- tracks={timeline.getTracks()}
+ tracks={tracks}
isVisible={isDragOver && !dropTarget?.targetElement}
headerHeight={timelineHeaderHeight}
/>
<DragLine
dropTarget={dragDropTarget}
- tracks={timeline.getTracks()}
+ tracks={tracks}
isVisible={dragState.isDragging}
headerHeight={timelineHeaderHeight}
/>
@@ -508,6 +515,7 @@ export function Timeline() {
{tracks.length > 0 && (
<TimelineTrackRows
dragElementId={dragState.elementId}
+ mainTrackId={mainTrackId}
zoomLevel={zoomLevel}
dragState={dragState}
tracksScrollRef={tracksScrollRef}
@@ -574,7 +582,14 @@ function TrackLabelsPanel({
hasHorizontalScrollbar: boolean;
}) {
const editor = useEditor();
- const tracks = useEditor((e) => e.timeline.getTracks());
+ const scene = useEditor((e) => e.scenes.getActiveSceneOrNull());
+ const tracks = useMemo<TimelineTrack[]>(
+ () =>
+ scene
+ ? [...scene.tracks.overlay, scene.tracks.main, ...scene.tracks.audio]
+ : [],
+ [scene],
+ );
const { selectedElements } = useElementSelection();
const tracksWithSelection = useMemo(
() => new Set(selectedElements.map((el) => el.trackId)),
@@ -650,6 +665,7 @@ function TrackLabelsPanel({
function TimelineTrackRows({
dragElementId,
+ mainTrackId,
zoomLevel,
dragState,
tracksScrollRef,
@@ -665,6 +681,7 @@ function TimelineTrackRows({
dropTarget,
}: {
dragElementId: string | null;
+ mainTrackId: string | null;
zoomLevel: number;
dragState: ElementDragState;
tracksScrollRef: React.RefObject<HTMLDivElement | null>;
@@ -684,7 +701,14 @@ function TimelineTrackRows({
dropTarget: DropTarget | null;
}) {
const timeline = useEditor((e) => e.timeline);
- const tracks = useEditor((e) => e.timeline.getTracks());
+ const scene = useEditor((e) => e.scenes.getActiveSceneOrNull());
+ const tracks = useMemo<TimelineTrack[]>(
+ () =>
+ scene
+ ? [...scene.tracks.overlay, scene.tracks.main, ...scene.tracks.audio]
+ : [],
+ [scene],
+ );
const { selectedElements } = useElementSelection();
const tracksWithSelection = useMemo(
() => new Set(selectedElements.map((el) => el.trackId)),
@@ -779,7 +803,7 @@ function TimelineTrackRows({
? "Show track"
: "Hide track"}
</ContextMenuItem>
- {!isMainTrack(track) && (
+ {track.id !== mainTrackId && (
<ContextMenuItem
icon={<HugeiconsIcon icon={Delete02Icon} />}
onClick={(event: React.MouseEvent) => {