avocado-old/packages/state/synchronized.js

116 lines
2.9 KiB
JavaScript
Raw Normal View History

2019-04-07 11:43:50 -05:00
import * as I from 'immutable';
2019-04-28 23:45:03 -05:00
import {compose, Property} from '@avocado/core';
2019-04-07 11:43:50 -05:00
2019-04-07 15:46:07 -05:00
import {nextStep} from './next-step';
2019-04-07 11:43:50 -05:00
const decorate = compose(
Property('state'),
);
2019-04-16 17:52:56 -05:00
export function Synchronized(Superclass) {
2019-04-16 16:34:28 -05:00
return class Synchronized extends decorate(Superclass) {
2019-04-07 11:43:50 -05:00
2019-04-16 16:34:28 -05:00
constructor(...args) {
super(...args);
this.state = I.Map();
this._childrenNeedInitialization = true;
this._childrenWithState = []
this._childrenWithoutState = [];
2019-05-05 20:04:50 -05:00
this._childrenTickers = [];
}
ensureChildrenAreSynchronized() {
if (!this._childrenNeedInitialization) {
return;
}
this._childrenNeedInitialization = false;
const synchronizedChildren = this.synchronizedChildren();
for (let i = 0; i < synchronizedChildren.length; ++i) {
const key = synchronizedChildren[i];
if (
'undefined' !== typeof this[key]
&& 'undefined' !== typeof this[key].tick
) {
2019-05-05 20:04:50 -05:00
this._childrenTickers.push(this[key].tick.bind(this[key]));
}
if (
'undefined' !== typeof this[key]
&& 'undefined' !== typeof this[key].state
) {
this._childrenWithState.push(key);
}
else {
this._childrenWithoutState.push(key);
}
}
2019-04-16 16:34:28 -05:00
}
2019-04-07 11:43:50 -05:00
2019-04-16 16:34:28 -05:00
patchState(patch) {
for (const step of patch) {
const {op, path, value} = step;
if ('/' === path) {
for (const key in value) {
this.patchStateStep(key, {
op,
path,
value: value[key],
});
}
}
else {
const [key, substep] = nextStep(step);
2019-04-11 06:49:42 -05:00
this.patchStateStep(key, {
2019-04-16 16:34:28 -05:00
op: substep.op,
path: substep.path,
value: substep.value,
2019-04-11 06:49:42 -05:00
});
2019-04-07 11:43:50 -05:00
}
}
}
2019-04-16 16:34:28 -05:00
patchStateStep(key, step) {
if (!(key in this)) {
return;
}
2019-04-16 17:52:56 -05:00
if (
'undefined' !== typeof this[key]
&& 'undefined' !== typeof this[key].patchState
) {
2019-04-16 16:34:28 -05:00
this[key].patchState([step]);
}
else {
this[key] = step.value;
2019-04-07 11:43:50 -05:00
}
}
2019-04-16 16:34:28 -05:00
2019-05-03 23:48:51 -05:00
synchronizedChildren() {
return [];
}
tickSynchronized(elapsed) {
this.ensureChildrenAreSynchronized();
2019-05-05 20:04:50 -05:00
for (let i = 0; i < this._childrenTickers.length; ++i) {
this._childrenTickers[i](elapsed);
2019-04-12 13:18:34 -05:00
}
2019-04-23 15:25:03 -05:00
if (AVOCADO_SERVER) {
this.tickMutateState();
}
}
tickMutateState() {
this.state = this.state.withMutations((state) => {
2019-05-04 13:06:33 -05:00
for (let i = 0; i < this._childrenWithState.length; ++i) {
const key = this._childrenWithState[i];
state.set(key, this[key].state);
}
2019-05-04 13:06:33 -05:00
for (let i = 0; i < this._childrenWithoutState.length; ++i) {
const key = this._childrenWithoutState[i];
state.set(key, this[key]);
}
});
2019-04-16 16:34:28 -05:00
}
2019-04-07 11:43:50 -05:00
2019-04-16 16:34:28 -05:00
}
2019-04-07 11:43:50 -05:00
}