fix: migrate commands to CommandResult selection contract

This commit is contained in:
Maze Winther
2026-04-18 16:01:35 +02:00
parent 0387bd4c80
commit 8bdc894690
6 changed files with 51 additions and 19 deletions
+14
View File
@@ -1,9 +1,23 @@
import type { EditorSelectionPatch } from "@/lib/selection/editor-selection"; import type { EditorSelectionPatch } from "@/lib/selection/editor-selection";
import type { ElementRef } from "@/lib/timeline/types";
export interface CommandResult { export interface CommandResult {
selection?: EditorSelectionPatch; selection?: EditorSelectionPatch;
} }
export function createElementSelectionResult(
selectedElements: ElementRef[],
): CommandResult {
return {
selection: {
selectedElements,
selectedKeyframes: [],
keyframeSelectionAnchor: null,
selectedMaskPoints: null,
},
};
}
export abstract class Command { export abstract class Command {
abstract execute(): CommandResult | undefined; abstract execute(): CommandResult | undefined;
+2 -2
View File
@@ -10,7 +10,7 @@ export class BatchCommand extends Command {
for (const command of this.commands) { for (const command of this.commands) {
const result = command.execute(); const result = command.execute();
if (result?.select !== undefined) { if (result?.selection !== undefined) {
latestSelectionResult = result; latestSelectionResult = result;
} }
} }
@@ -29,7 +29,7 @@ export class BatchCommand extends Command {
for (const command of this.commands) { for (const command of this.commands) {
const result = command.redo(); const result = command.redo();
if (result?.select !== undefined) { if (result?.selection !== undefined) {
latestSelectionResult = result; latestSelectionResult = result;
} }
} }
@@ -1,9 +1,17 @@
import { Command, type CommandResult } from "@/lib/commands/base-command"; import {
Command,
createElementSelectionResult,
type CommandResult,
} from "@/lib/commands/base-command";
import { EditorCore } from "@/core"; import { EditorCore } from "@/core";
import type { SceneTracks, TimelineElement } from "@/lib/timeline"; import type { SceneTracks, TimelineElement } from "@/lib/timeline";
import type { ElementClipboardItem } from "@/lib/clipboard"; import type { ElementClipboardItem } from "@/lib/clipboard";
import { generateUUID } from "@/utils/id"; import { generateUUID } from "@/utils/id";
import { applyPlacement, resolveTrackPlacement, enforceMainTrackStart } from "@/lib/timeline/placement"; import {
applyPlacement,
resolveTrackPlacement,
enforceMainTrackStart,
} from "@/lib/timeline/placement";
import { cloneAnimations } from "@/lib/animation"; import { cloneAnimations } from "@/lib/animation";
export class PasteCommand extends Command { export class PasteCommand extends Command {
@@ -122,7 +130,7 @@ export class PasteCommand extends Command {
editor.timeline.updateTracks(updatedTracks); editor.timeline.updateTracks(updatedTracks);
if (this.pastedElements.length > 0) { if (this.pastedElements.length > 0) {
return { select: this.pastedElements }; return createElementSelectionResult(this.pastedElements);
} }
return undefined; return undefined;
} }
@@ -183,4 +191,3 @@ function buildPastedElements({
return elementsToAdd; return elementsToAdd;
} }
@@ -1,8 +1,15 @@
import { Command, type CommandResult } from "@/lib/commands/base-command"; import {
Command,
createElementSelectionResult,
type CommandResult,
} from "@/lib/commands/base-command";
import type { SceneTracks, TimelineElement } from "@/lib/timeline"; import type { SceneTracks, TimelineElement } from "@/lib/timeline";
import { generateUUID } from "@/utils/id"; import { generateUUID } from "@/utils/id";
import { EditorCore } from "@/core"; import { EditorCore } from "@/core";
import { applyPlacement, resolveTrackPlacement } from "@/lib/timeline/placement"; import {
applyPlacement,
resolveTrackPlacement,
} from "@/lib/timeline/placement";
import { cloneAnimations } from "@/lib/animation"; import { cloneAnimations } from "@/lib/animation";
interface DuplicateElementsParams { interface DuplicateElementsParams {
@@ -91,9 +98,7 @@ export class DuplicateElementsCommand extends Command {
editor.timeline.updateTracks(updatedTracks); editor.timeline.updateTracks(updatedTracks);
if (this.duplicatedElements.length > 0) { if (this.duplicatedElements.length > 0) {
return { return createElementSelectionResult(this.duplicatedElements);
select: this.duplicatedElements,
};
} }
return undefined; return undefined;
} }
@@ -1,4 +1,8 @@
import { Command, type CommandResult } from "@/lib/commands/base-command"; import {
Command,
createElementSelectionResult,
type CommandResult,
} from "@/lib/commands/base-command";
import { EditorCore } from "@/core"; import { EditorCore } from "@/core";
import type { import type {
SceneTracks, SceneTracks,
@@ -114,12 +118,12 @@ export class MoveElementCommand extends Command {
}); });
editor.timeline.updateTracks(updatedTracks); editor.timeline.updateTracks(updatedTracks);
return { return createElementSelectionResult(
select: this.moves.map(({ elementId, targetTrackId }) => ({ this.moves.map(({ elementId, targetTrackId }) => ({
trackId: targetTrackId, trackId: targetTrackId,
elementId, elementId,
})), })),
}; );
} }
undo(): void { undo(): void {
@@ -1,4 +1,8 @@
import { Command, type CommandResult } from "@/lib/commands/base-command"; import {
Command,
createElementSelectionResult,
type CommandResult,
} from "@/lib/commands/base-command";
import type { SceneTracks, TimelineElement } from "@/lib/timeline"; import type { SceneTracks, TimelineElement } from "@/lib/timeline";
import { generateUUID } from "@/utils/id"; import { generateUUID } from "@/utils/id";
import { EditorCore } from "@/core"; import { EditorCore } from "@/core";
@@ -164,9 +168,7 @@ export class SplitElementsCommand extends Command {
editor.timeline.updateTracks(updatedTracks); editor.timeline.updateTracks(updatedTracks);
if (this.rightSideElements.length > 0) { if (this.rightSideElements.length > 0) {
return { return createElementSelectionResult(this.rightSideElements);
select: this.rightSideElements,
};
} }
return undefined; return undefined;
} }