summaryrefslogtreecommitdiff
path: root/apps/web/src/commands/timeline/element/shift-split-remainder.ts
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-07-26 22:13:01 +0200
committercashmere <cashmere@autistici.org>2026-07-26 22:13:01 +0200
commit12539fedf3020468fded3945d5dfc4c8396e7750 (patch)
treea2c4122bed6a8aa31e76d0598287afca45104541 /apps/web/src/commands/timeline/element/shift-split-remainder.ts
parent3fcf892dfa19e0fb2f1487b91971f48dcc26fc50 (diff)
downloadopencut-12539fedf3020468fded3945d5dfc4c8396e7750.tar.gz
feat: single undo step for freeze frame
The handler fired four separate commands (asset add, split, move, insert), producing four undo steps. It now builds one BatchCommand and executes it once. The new ShiftSplitRemainderCommand resolves the split's right-side elements lazily at execute() so it can be composed after the split in the batch, and rebuilds the inner move on redo since a re-executed split generates fresh element ids.
Diffstat (limited to 'apps/web/src/commands/timeline/element/shift-split-remainder.ts')
-rw-r--r--apps/web/src/commands/timeline/element/shift-split-remainder.ts50
1 files changed, 50 insertions, 0 deletions
diff --git a/apps/web/src/commands/timeline/element/shift-split-remainder.ts b/apps/web/src/commands/timeline/element/shift-split-remainder.ts
new file mode 100644
index 00000000..3799c8f9
--- /dev/null
+++ b/apps/web/src/commands/timeline/element/shift-split-remainder.ts
@@ -0,0 +1,50 @@
+import { Command, type CommandResult } from "@/commands/base-command";
+import type { MediaTime } from "@/wasm";
+import { MoveElementCommand } from "./move-elements";
+import type { SplitElementsCommand } from "./split-elements";
+
+/**
+ * Moves the right-side elements produced by a SplitElementsCommand to a new
+ * start time. Must run after the split inside a BatchCommand: the right-side
+ * element ids only exist once the split has executed. Rebuilds the inner move
+ * on every execute() so redo picks up the fresh ids a re-executed split
+ * generates.
+ */
+export class ShiftSplitRemainderCommand extends Command {
+ private inner: MoveElementCommand | null = null;
+
+ constructor({
+ split,
+ newStartTime,
+ }: {
+ split: SplitElementsCommand;
+ newStartTime: MediaTime;
+ }) {
+ super();
+ this.split = split;
+ this.newStartTime = newStartTime;
+ }
+
+ private readonly split: SplitElementsCommand;
+ private readonly newStartTime: MediaTime;
+
+ execute(): CommandResult | undefined {
+ const rightSideElements = this.split.getRightSideElements();
+ if (rightSideElements.length === 0) {
+ return undefined;
+ }
+ this.inner = new MoveElementCommand({
+ moves: rightSideElements.map((element) => ({
+ sourceTrackId: element.trackId,
+ targetTrackId: element.trackId,
+ elementId: element.elementId,
+ newStartTime: this.newStartTime,
+ })),
+ });
+ return this.inner.execute();
+ }
+
+ undo(): void {
+ this.inner?.undo();
+ }
+}