Skip to content

Commit d41b1aa

Browse files
committed
undo/redo has been refined with throttle and ignored categories
1 parent 1c7604e commit d41b1aa

File tree

3 files changed

+46
-15
lines changed

3 files changed

+46
-15
lines changed

package-lock.json

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"localforage": "^1.7.3",
2626
"lodash": ">=4.17.13",
2727
"lodash.isequal": "^4.5.0",
28+
"lodash.throttle": "^4.1.1",
2829
"mousetrap": "^1.6.3",
2930
"prismjs": "^1.16.0",
3031
"quasar": "^1.0.0",

src/App.vue

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,19 @@
88
import { SET_ACTIVE_COMPONENT } from './store/types'
99
const deepEqual = require('lodash.isequal')
1010
const cloneDeep = require('lodash.clonedeep')
11+
const throttle = require('lodash.throttle')
1112
import { defaultState } from './store/state/index.js'
1213
14+
15+
//use this to make sure these actions don't count as things you "undo"
16+
const ignoredActions = new Set([
17+
"setActiveComponent",
18+
"setActiveLayer",
19+
"upOneLayer",
20+
"setActiveHTML"
21+
])
22+
23+
1324
let redoMixin = {
1425
data () {
1526
return {
@@ -47,19 +58,24 @@ let redoMixin = {
4758
},
4859
4960
mounted () {
61+
62+
const throttledUndo = throttle(this.undo,300)
63+
const throttledRedo = throttle(this.redo,300)
64+
5065
window.addEventListener('keydown', event => {
5166
if (event.ctrlKey && event.key === 'z') {
5267
event.preventDefault()
53-
this.undo()
68+
throttledUndo()
5469
}
5570
})
5671
window.addEventListener('keydown', event => {
5772
if (event.ctrlKey && event.key === 'y') {
5873
event.preventDefault()
59-
this.redo()
74+
throttledRedo()
6075
}
6176
})
6277
78+
// commented code for hotkeys for debuging///////////////////////
6379
// window.addEventListener('keydown', event => {
6480
// if (event.ctrlKey && event.key === 'a') {
6581
// event.preventDefault()
@@ -76,6 +92,7 @@ let redoMixin = {
7692
// }
7793
// }
7894
// });
95+
//////////////////////////////////////////////////////////////////////
7996
8097
// console.log("do we want this? or this.$store.state?", this.$store.state)
8198
this.initialState = defaultState(this.$store.state)
@@ -85,49 +102,63 @@ let redoMixin = {
85102
undo: function () {
86103
// do {
87104
// console.log("How far back?")
105+
if(this.doneAction.length ===0){
106+
return
107+
}
88108
89109
this.isTimetraveling = true
90110
91111
let undone = this.doneAction.pop()
92112
113+
// assuming we have have something to undo, we check if we are undoing an action that has no feedback
114+
// like say changing active elements or active components or going up and down a layer since these can be obscured from immediate feedback
115+
// will just feel bad to undo (Imagine someone just clicking around out of boredom and then deciding to undo
116+
// will force them to have to undo the 30 highlights they just did instead of the last "Real" action)
117+
// if this happens we keep popping the doneAction queue and building up the redo queue.
93118
if (undone !== undefined) {
94119
this.undoneAction.push(undone)
95-
if (undone.type === 'setActiveComponent') {
96-
console.log('We did something useless!')
97-
do {
120+
if (ignoredActions.has(undone.type)) {
121+
// console.log('We did something useless!')
122+
while (this.doneAction[this.doneAction.length - 1] &&
123+
ignoredActions.has(this.doneAction[this.doneAction.length - 1].type)){
98124
this.undoneAction.push(this.doneAction.pop())
99125
}
100-
while (this.doneAction[this.doneAction.length - 1] &&
101-
(this.doneAction[this.doneAction.length - 1].type === 'setActiveComponent'))
126+
let finalPop = this.doneAction.pop()
127+
if(finalPop !== undefined){
128+
this.undoneAction.push(finalPop)
129+
}
102130
}
131+
// if we get here, that means we have undone all "useless" actions
132+
// so we have to do one more final pop and push, have to make sure it isn't null though
133+
103134
}
104135
105-
// while (this.doneAction[this.doneAction.length-1] &&
106-
// (this.doneAction[this.doneAction.length - 1].type === "setActiveComponent" ||
107-
// this.doneAction[this.doneAction.length - 1].type === "updateComponentPosition" ))
108136
let payload = {
109137
initialState: this.initialState,
110138
store: this.$store
111139
}
112140
this.$store.commit('EMPTY_STATE', payload)
113141
console.log(this.$store)
114142
this.doneAction.forEach(action => {
115-
console.log('In the loop', this.$store)
143+
//console.log('In the loop', this.$store)
116144
// this.$store.commit(`${mutation.type}`, mutation.payload);
117145
this.$store.dispatch(action.type, cloneDeep(action.payload))
118146
this.doneAction.pop()
119147
})
120148
this.isTimetraveling = false
121149
},
150+
122151
redo: function () {
123152
let action = this.undoneAction.pop()
153+
154+
//we have to set timeTraveling to true to preserve the undoneAction array while we make changes
124155
this.isTimetraveling = true
125156
if (action) {
126157
this.$store.dispatch(action.type, cloneDeep(action.payload))
127158
}
128159
this.isTimetraveling = false
129-
if (action && (action.type === 'setActiveComponent')) {
130-
console.log('WE GOTTA DO MORE')
160+
if (action && ignoredActions.has(action.type)) {
161+
//console.log('WE GOTTA DO MORE')
131162
this.redo()
132163
}
133164
}

0 commit comments

Comments
 (0)