Skip to content

Instantly share code, notes, and snippets.

@mattmccray
Last active July 3, 2016 22:37
Show Gist options
  • Select an option

  • Save mattmccray/3ce55fb4f0a68dce57f626786f8daf6d to your computer and use it in GitHub Desktop.

Select an option

Save mattmccray/3ce55fb4f0a68dce57f626786f8daf6d to your computer and use it in GitHub Desktop.
“You get undo for free!” and Other Lies… Snippets
/**
* A simple command example that updates a todo's name.
*
* @param todoId {number}
* @param newName {string}
* @param context {MadeUpBackendAPI}
*/
function UpdateTodoName(todoId, newName, context) {
// Get current name so we can revert back to it, if needed:
const prevName = context.getObjectOfTye('todo', todoId).name
return {
execute() {
context.updateObjectOfType('todo', todoId, { name:newName })
},
revert() {
context.updateObjectOfType('todo', todoId, { name:prevName })
}
}
}
/**
* A little more complex command example that creates a todo, but also
* tries to reuse the same todoId on any 'redo' calls.
*
* @param todoData {*}
* @param context {MadeUpBackendAPI}
*/
function CreateTodo(todoData, context) {
let todoId;
return {
execute() {
if (!todoId) {
// When first executed, save the ID.
todoId = context.createObjectOfType('todo', todoData)
}
else {
// When run as a 'redo', re-use the same ID so any future commands
// on the redo stack will still work.
context.createObjectOfTypeWithId('todo', todoId, todoData)
}
},
revert() {
context.removeObjectOfType('todo', todoId)
}
}
}
/**
* Potential example usage:
* app.runCommand(CreateTodo, { name:'test', isComplete:false })
*/
class CommandManager {
undoStack = []
redoState = []
run(command) {
command.execute()
this.undoStack.push(command)
this.redoStack.length = 0
}
undo() {
if (this.undoStack.length) {
const command = this.undoStack.pop()
command.revert()
this.redoStack.push(command)
}
}
redo() {
if (this.redoStack.length) {
const command = this.redoStack.pop()
command.execute()
this.undoStack.push(command)
}
}
}
class Application {
commands = new CommandManager()
backend = new MadeUpBackendAPI()
runCommand(command, ...params) {
params.push(this.backend)
this.commands.run(command.apply(null, params))
}
get canUndo() {
return this.commands.undoStack.length > 0
}
get canRedo() {
return this.commands.redoStack.length > 0
}
undo() {
this.commands.undo()
}
redo() {
this.commands.redo()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment