Skip to content

Instantly share code, notes, and snippets.

@fprochazka
Forked from rarous/Application.js
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fprochazka/5bc3cd99e7266b1dabba to your computer and use it in GitHub Desktop.
Save fprochazka/5bc3cd99e7266b1dabba to your computer and use it in GitHub Desktop.
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()
}
});
}
}
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