-
-
Save fprochazka/5bc3cd99e7266b1dabba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Kefir from 'kefir'; | |
import {List, Stack} from 'immutable'; | |
import {comp, filter, map} from 'transducers-js'; | |
function register(stream, messageType, handler) { | |
let xform = comp( | |
filter(x => x.first() === messageType), | |
map(x => x.rest())); | |
stream.transduce(xform).onValue(handler); | |
} | |
class Application { | |
constructor(initialData, view) { | |
this.view = view; | |
this.state = initialData; | |
this.history = new Stack(); | |
this.future = new Stack(); | |
this.stream = Kefir.emitter(); | |
// for debugging | |
// this.stream.map(x => x.toJS()).log('stream'); | |
this.on('update', x => this.updateData(x.first())); | |
this.on('state-changed', () => this.render()); | |
} | |
get canUndo() { | |
return this.history.some(() => true); | |
} | |
get canRedo() { | |
return this.future.some(() => true); | |
} | |
on(eventName, handler) { | |
register(this.stream, eventName, handler); | |
} | |
emit() { | |
this.stream.emit(new List(arguments)); | |
} | |
updateData(data) { | |
this.future = new Stack(); | |
this.history = this.history.push(this.state); | |
this.state = data; | |
this.emit('state-changed', 'updateData', this.state); | |
} | |
undo() { | |
if (!this.canUndo) { | |
return; | |
} | |
this.future = this.future.push(this.state); | |
this.state = this.history.peek(); | |
this.history = this.history.pop(); | |
this.emit('state-changed', 'undo', this.state); | |
} | |
redo() { | |
if (!this.canRedo) { | |
return; | |
} | |
this.history = this.history.push(this.state); | |
this.state = this.future.peek(); | |
this.future = this.future.pop(); | |
this.emit('state-changed', 'redo', this.state); | |
} | |
render() { | |
this.view.setProps({ | |
data: this.state, | |
messages: { | |
emit: this.emit.bind(this), | |
on: this.on.bind(this) | |
}, | |
history: { | |
canUndo: this.canUndo, | |
undo: () => this.undo(), | |
canRedo: this.canRedo, | |
redo: () => this.redo() | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cursor from 'immutable/contrib/cursor'; | |
import {Component} from 'react'; | |
class ApplicationView extends Component { | |
cursorFor(keyPath) { | |
let update = x => this.props.messages.emit('update', x); | |
return Cursor.from(this.props.data, keyPath, update); | |
} | |
render() { | |
return ( | |
<SubComponent data={this.cursorFor(['path', 'to', 'nested', 'data'])} /> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment