2019-03-20 18:33:13 -05:00
|
|
|
import * as I from 'immutable';
|
|
|
|
import immutablediff from 'immutablediff';
|
|
|
|
|
|
|
|
export class StateSynchronizer {
|
|
|
|
|
|
|
|
constructor(statefuls) {
|
|
|
|
this._state = I.Map();
|
|
|
|
this._statefuls = statefuls;
|
2019-03-28 02:09:46 -05:00
|
|
|
this.tick();
|
2019-03-20 18:33:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
acceptStateChange(change) {
|
|
|
|
for (const key in change) {
|
|
|
|
const stateful = this._statefuls[key];
|
|
|
|
if (!stateful) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
stateful.acceptStateChange(change[key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-28 02:09:46 -05:00
|
|
|
diff(previousState) {
|
|
|
|
const state = this._state;
|
2019-03-20 18:33:13 -05:00
|
|
|
const diff = {};
|
|
|
|
for (const key in this._statefuls) {
|
2019-03-28 02:09:46 -05:00
|
|
|
if (previousState.get(key) !== state.get(key)) {
|
2019-03-20 18:33:13 -05:00
|
|
|
diff[key] = this.diffStateful(
|
2019-03-28 02:09:46 -05:00
|
|
|
previousState.get(key),
|
2019-03-20 18:33:13 -05:00
|
|
|
state.get(key)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
diffStateful(previous, current) {
|
|
|
|
// Take a pure JS diff.
|
|
|
|
const steps = immutablediff(previous, current).toJS();
|
|
|
|
let diff = {};
|
|
|
|
for (const {op, path, value} of steps) {
|
|
|
|
if ('replace' === op || 'add' === op) {
|
|
|
|
if ('/' === path) {
|
|
|
|
diff = value;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const parts = path.split('/');
|
|
|
|
parts.shift();
|
|
|
|
let walk = diff;
|
|
|
|
for (let i = 0; i < parts.length; ++i) {
|
|
|
|
const part = parts[i];
|
|
|
|
walk[part] = walk[part] || {};
|
|
|
|
if (i === parts.length - 1) {
|
|
|
|
walk[part] = value;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
walk = walk[part];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
2019-03-28 02:09:46 -05:00
|
|
|
get state() {
|
2019-03-20 18:33:13 -05:00
|
|
|
return this._state;
|
|
|
|
}
|
|
|
|
|
2019-03-28 02:09:46 -05:00
|
|
|
tick() {
|
2019-03-20 18:33:13 -05:00
|
|
|
for (const key in this._statefuls) {
|
|
|
|
const stateful = this._statefuls[key];
|
2019-03-26 15:41:49 -05:00
|
|
|
this._state = this._state.set(key, stateful.state);
|
2019-03-20 18:33:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|