summaryrefslogtreecommitdiff
path: root/apps/web/src/lib/timeline/group-move/build-group.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/lib/timeline/group-move/build-group.ts')
-rw-r--r--apps/web/src/lib/timeline/group-move/build-group.ts87
1 files changed, 87 insertions, 0 deletions
diff --git a/apps/web/src/lib/timeline/group-move/build-group.ts b/apps/web/src/lib/timeline/group-move/build-group.ts
new file mode 100644
index 00000000..16d720eb
--- /dev/null
+++ b/apps/web/src/lib/timeline/group-move/build-group.ts
@@ -0,0 +1,87 @@
+import type { ElementRef, SceneTracks } from "@/lib/timeline";
+import { findTrackInSceneTracks } from "@/lib/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,
+ };
+}