12 this.$undo = $("#undoBtn");
13 this.$undo.on('click', () => {CurrentDocument.undo();})
14 this.$redo = $("#redoBtn");
15 this.$redo.on('click', () => {CurrentDocument.redo();})
16 this.$stats = $("#undoStats");
21 this.$undo.prop('disabled', !this.canUndo);
22 this.$redo.prop('disabled', !this.canRedo);
23 this.$undo.attr('title', 'undo\n\n' + this.renderStats())
27 return this.stats.size / 1e6;
31 // Has the state actually changed?
32 if (state == this.materialize(this.position))
35 while (this.position) {
45 this.stats.size -= this.stack[0].length;
46 return this.stack.shift()
49 this.stack.unshift(state);
50 this.stats.size += state.length;
53 while (this.stack.length > this.maxItems) {
54 this.stats.size -= this.stack.pop().length;
62 if (!this.canUndo) return;
63 let val = this.materialize(++this.position);
69 if (!this.canRedo) return;
70 let val = this.materialize(--this.position);
76 return this.stack.length > this.position + 1;
80 return this.position > 0;
85 class TextUndo extends Undo {
97 if (Array.isArray(item)) {
100 diffChanges: item.length,
101 diffSize: JSON.stringify(item).length
106 textSize: item.length
111 for (let i in stats) {
112 this.stats[i] += stats[i]
116 for (let i in stats) {
117 this.stats[i] -= stats[i]
121 this.stats['Items'] = this.stats['textItems'] + this.stats['diffItems'];
122 this.stats['Size'] = this.stats['textSize'] + this.stats['diffSize'];
124 for (let k in this.stats) {
126 if (k.endsWith('Size')) {
133 v += ['B', 'kB', 'MB', 'GB'][level];
135 stats += k + ': ' + v + '\n';
142 if (this.stack.length) {
143 let tip = this.materialize(0);
144 this.subStats(this.statsFor(this.stack[0]))
145 this.stack[0] = $.wiki.diff(state, tip);
146 this.addStats(this.statsFor(this.stack[0]))
148 this.stack.unshift(state);
149 this.addStats(this.statsFor(state));
152 if (this.stack.length > 1) {
153 this.subStats(this.statsFor(this.stack[1]))
154 this.stack[1] = this.materialize(1);
155 this.addStats(this.statsFor(this.stack[1]))
157 this.subStats(this.statsFor(this.stack[0]))
158 return this.stack.shift();
161 while (this.stack.length > this.maxItems) {
162 this.subStats(this.statsFor(
169 if (n >= this.stack.length) return;
170 let state, base_i, i;
171 for (i = 0; i <= n; ++i) {
172 if (!Array.isArray(this.stack[i])) {
176 state = this.stack[base_i];
177 for (i = base_i + 1; i <= n; ++i) {
178 state = $.wiki.patch(state, this.stack[i]);
184 $.wiki.undo = new TextUndo();