Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit e59239f

Browse files
committed
[ADD] History: add 'undo' and 'redo' command that uses memory
1 parent 1fc2c7a commit e59239f

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

packages/bundle-basic-editor/BasicEditor.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { BackgroundColor } from '../../packages/plugin-backgroundcolor/src/Backg
3333
import { Layout } from '../../packages/plugin-layout/src/Layout';
3434
import { DomLayout } from '../../packages/plugin-dom-layout/src/DomLayout';
3535
import { DomEditable } from '../../packages/plugin-dom-editable/src/DomEditable';
36+
import { History } from '../../packages/plugin-history/src/History';
3637
import { VNode } from '../../packages/core/src/VNodes/VNode';
3738
import { Input } from '../../packages/plugin-input/src/Input';
3839
import { Dialog } from '../../packages/plugin-dialog/src/Dialog';
@@ -65,6 +66,7 @@ export class BasicEditor extends JWEditor {
6566
[Html],
6667
[DomLayout],
6768
[DomEditable],
69+
[History],
6870
[Inline],
6971
[Char],
7072
[LineBreak],
@@ -150,6 +152,7 @@ export class BasicEditor extends JWEditor {
150152
['LinkButton', 'UnlinkButton'],
151153
['TableButton'],
152154
['CodeButton'],
155+
['UndoButton', 'RedoButton'],
153156
],
154157
});
155158
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { JWPlugin, JWPluginConfig } from '../../core/src/JWPlugin';
2+
import { JWEditor, Loadables } from '../../core/src/JWEditor';
3+
import { Keymap } from '../../plugin-keymap/src/Keymap';
4+
import { Layout } from '../../plugin-layout/src/Layout';
5+
import { ActionableNode } from '../../plugin-layout/src/ActionableNode';
6+
import { Attributes } from '../../plugin-xml/src/Attributes';
7+
8+
export class History<T extends JWPluginConfig = JWPluginConfig> extends JWPlugin<T> {
9+
readonly loadables: Loadables<Keymap & Layout> = {
10+
shortcuts: [
11+
{
12+
pattern: 'CTRL+Z',
13+
commandId: 'undo',
14+
},
15+
{
16+
pattern: 'CTRL+SHIFT+Z',
17+
commandId: 'redo',
18+
},
19+
{
20+
pattern: 'CTRL+Y',
21+
commandId: 'redo',
22+
},
23+
],
24+
components: [
25+
{
26+
id: 'UndoButton',
27+
render: async (): Promise<ActionableNode[]> => {
28+
const button = new ActionableNode({
29+
name: 'undo',
30+
label: 'History undo',
31+
commandId: 'undo',
32+
enabled: (): boolean => this._memoryStep > 0,
33+
modifiers: [new Attributes({ class: 'fa fa-undo fa-fw' })],
34+
});
35+
return [button];
36+
},
37+
},
38+
{
39+
id: 'RedoButton',
40+
render: async (): Promise<ActionableNode[]> => {
41+
const button = new ActionableNode({
42+
name: 'redo',
43+
label: 'History redo',
44+
commandId: 'redo',
45+
enabled: (): boolean => this._memoryKeys.length - 1 > this._memoryStep,
46+
modifiers: [new Attributes({ class: 'fa fa-redo fa-fw' })],
47+
});
48+
return [button];
49+
},
50+
},
51+
],
52+
componentZones: [
53+
['UndoButton', ['actionables']],
54+
['RedoButton', ['actionables']],
55+
],
56+
};
57+
commands = {
58+
undo: {
59+
handler: this.undo,
60+
},
61+
redo: {
62+
handler: this.redo,
63+
},
64+
};
65+
commandHooks = {
66+
'@commit': this._registerMemoryKey,
67+
};
68+
69+
constructor(editor: JWEditor) {
70+
super(editor);
71+
this.loadables.components.push();
72+
}
73+
74+
private _memoryKeys: string[] = [];
75+
private _memoryCommands: string[][] = [];
76+
private _memoryStep = -1;
77+
78+
undo(): void {
79+
this._memoryStep--;
80+
if (this._memoryStep < 0) {
81+
this._memoryStep = 0;
82+
}
83+
this.editor.memory.switchTo(this._memoryKeys[this._memoryStep]);
84+
}
85+
redo(): void {
86+
this._memoryStep++;
87+
const max = this._memoryKeys.length - 1;
88+
if (this._memoryStep > max) {
89+
this._memoryStep = max;
90+
}
91+
this.editor.memory.switchTo(this._memoryKeys[this._memoryStep]);
92+
}
93+
private _registerMemoryKey(): void {
94+
const sliceKey = this.editor.memory.sliceKey;
95+
if (!this._memoryKeys.includes(sliceKey)) {
96+
const commands = this.editor.memoryInfo.commandNames;
97+
if (commands.length === 1 && commands[0] === 'setSelection') {
98+
if (this._memoryStep > this._memoryKeys.length - 1) {
99+
// After an undo, don't replace history for setSelection.
100+
return;
101+
}
102+
const prevCommand = this._memoryCommands[this._memoryStep];
103+
if (prevCommand && prevCommand.length === 1 && prevCommand[0] === 'setSelection') {
104+
// Concat setSelection.
105+
this._memoryKeys[this._memoryStep] = sliceKey;
106+
return;
107+
}
108+
}
109+
110+
this._memoryStep++;
111+
this._memoryKeys.splice(this._memoryStep, Infinity, sliceKey);
112+
this._memoryCommands.splice(this._memoryStep, Infinity, [
113+
...this.editor.memoryInfo.commandNames,
114+
]);
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)