summaryrefslogtreecommitdiff
path: root/apps/web/src/timeline/group-move/build-group.ts
blob: 00f39d55a7062cbfef1767888b0d25dedcfa74f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import type { ElementRef, SceneTracks } from "@/timeline";
import { findTrackInSceneTracks } from "@/timeline/track-element-update";
import type { GroupMember, MoveGroup } from "./types";
import { getTrackPlacementById } from "./track-placement";

export function buildMoveGroup({
	anchorRef,
	selectedElements,
	tracks,
}: {
	anchorRef: ElementRef;
	selectedElements: ElementRef[];
	tracks: SceneTracks;
}): MoveGroup | null {
	const anchorTrack = findTrackInSceneTracks({
		tracks,
		trackId: anchorRef.trackId,
	});
	const anchorElement = anchorTrack?.elements.find(
		(element) => element.id === anchorRef.elementId,
	);
	const anchorPlacement = getTrackPlacementById({
		tracks,
		trackId: anchorRef.trackId,
	});
	if (!anchorTrack || !anchorElement || !anchorPlacement) {
		return null;
	}

	const seen = new Set<string>();
	const orderedRefs = [anchorRef, ...selectedElements].filter((elementRef) => {
		if (seen.has(elementRef.elementId)) {
			return false;
		}

		seen.add(elementRef.elementId);
		return true;
	});

	const members = orderedRefs.flatMap((elementRef): GroupMember[] => {
		const track = findTrackInSceneTracks({
			tracks,
			trackId: elementRef.trackId,
		});
		const element = track?.elements.find(
			(trackElement) => trackElement.id === elementRef.elementId,
		);
		const placement = getTrackPlacementById({
			tracks,
			trackId: elementRef.trackId,
		});
		if (!track || !element || !placement) {
			return [];
		}

		return [
			{
				trackId: track.id,
				elementId: element.id,
				elementType: element.type,
				duration: element.duration,
				timeOffset: element.startTime - anchorElement.startTime,
				trackSection: placement.section,
				sectionIndex: placement.sectionIndex,
				displayIndex: placement.displayIndex,
			},
		];
	});

	if (members.length === 0) {
		return null;
	}

	const anchor = members.find(
		(member) =>
			member.trackId === anchorRef.trackId &&
			member.elementId === anchorRef.elementId,
	);
	if (!anchor) {
		return null;
	}

	return {
		anchor,
		members,
	};
}