Skip to content

Commit 4cf40a1

Browse files
authored
Merge pull request #131 from shotstack/derk/eng-721-canundo-canredo-getters
feat: expose canUndo/canRedo on the Edit class
2 parents 7560f02 + 8af2840 commit 4cf40a1

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

src/core/edit-session.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,16 @@ export class Edit {
10451045
}
10461046
});
10471047
}
1048+
/** True when there is a command to undo (the history pointer is not before the first command). */
1049+
public get canUndo(): boolean {
1050+
return this.commandIndex >= 0;
1051+
}
1052+
1053+
/** True when there is a command ahead to redo (the history pointer is not at the latest command). */
1054+
public get canRedo(): boolean {
1055+
return this.commandIndex < this.commandHistory.length - 1;
1056+
}
1057+
10481058
/** @internal */
10491059
public setUpdatedClip(clip: Player, initialClipConfig: ResolvedClip | null = null, finalClipConfig: ResolvedClip | null = null): void {
10501060
// Find track and clip indices

tests/edit-commands.test.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,61 @@ describe("Edit Command History", () => {
654654
});
655655
});
656656

657+
describe("canUndo / canRedo getters", () => {
658+
it("are both false on a freshly loaded edit (load is not a command)", () => {
659+
expect(getCommandState(edit).index).toBe(-1);
660+
expect(edit.canUndo).toBe(false);
661+
expect(edit.canRedo).toBe(false);
662+
});
663+
664+
it("canUndo turns true after a command; canRedo stays false", async () => {
665+
await edit.executeEditCommand(new TestCommand());
666+
expect(edit.canUndo).toBe(true);
667+
expect(edit.canRedo).toBe(false);
668+
});
669+
670+
it("undo turns canRedo on and, back at the start, canUndo off", async () => {
671+
await edit.executeEditCommand(new TestCommand());
672+
await edit.undo();
673+
expect(edit.canUndo).toBe(false);
674+
expect(edit.canRedo).toBe(true);
675+
});
676+
677+
it("redo turns canUndo back on and, at the end, canRedo off", async () => {
678+
await edit.executeEditCommand(new TestCommand());
679+
await edit.undo();
680+
await edit.redo();
681+
expect(edit.canUndo).toBe(true);
682+
expect(edit.canRedo).toBe(false);
683+
});
684+
685+
it("both are true mid-stack", async () => {
686+
await edit.executeEditCommand(new TestCommand());
687+
await edit.executeEditCommand(new TestCommand());
688+
await edit.undo();
689+
expect(edit.canUndo).toBe(true);
690+
expect(edit.canRedo).toBe(true);
691+
});
692+
693+
it("a new command after undo truncates redo (canRedo false)", async () => {
694+
await edit.executeEditCommand(new TestCommand());
695+
await edit.executeEditCommand(new TestCommand());
696+
await edit.undo();
697+
await edit.executeEditCommand(new TestCommand());
698+
expect(edit.canUndo).toBe(true);
699+
expect(edit.canRedo).toBe(false);
700+
});
701+
702+
it("track the underlying commandIndex bounds", async () => {
703+
await edit.executeEditCommand(new TestCommand());
704+
await edit.executeEditCommand(new TestCommand());
705+
await edit.undo();
706+
const { history, index } = getCommandState(edit);
707+
expect(edit.canUndo).toBe(index >= 0);
708+
expect(edit.canRedo).toBe(index < history.length - 1);
709+
});
710+
});
711+
657712
describe("state restoration", () => {
658713
it("undo restores previous state via command.undo()", async () => {
659714
// Use a command that tracks state changes

0 commit comments

Comments
 (0)