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(); 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, }; }