vscroll
Version:
Virtual scroll engine
205 lines • 7.56 kB
JavaScript
import { __read, __spreadArray } from "tslib";
import { Scroller } from './scroller';
import { runStateMachine } from './workflow-transducer';
import { Reactive } from './classes/reactive';
import { AdapterProcess, CommonProcess, ProcessStatus as Status } from './processes/index';
import { WORKFLOW, validate } from './inputs/index';
var Workflow = /** @class */ (function () {
function Workflow(params) {
var _this = this;
var element = params.element, datasource = params.datasource, consumer = params.consumer, run = params.run, Routines = params.Routines;
var validationResult = validate(params, WORKFLOW);
if (!validationResult.isValid) {
throw new Error("Invalid Workflow params: ".concat(validationResult.errors.join(', '), "."));
}
this.isInitialized = false;
this.disposed = false;
this.initTimer = null;
this.adapterRun$ = new Reactive();
this.cyclesDone = 0;
this.cyclesDone$ = new Reactive(0);
this.interruptionCount = 0;
this.errors = [];
this.offScroll = function () { return null; };
this.propagateChanges = run;
this.stateMachineMethods = {
run: this.runProcess(),
interrupt: this.interrupt.bind(this),
done: this.done.bind(this),
onError: this.onError.bind(this)
};
this.scroller = new Scroller({
element: element,
datasource: datasource,
consumer: consumer,
workflow: this.getUpdater(),
Routines: Routines
});
if (this.scroller.settings.initializeDelay) {
this.initTimer = setTimeout(function () {
_this.initTimer = null;
_this.init();
}, this.scroller.settings.initializeDelay);
}
else {
this.init();
}
}
Workflow.prototype.init = function () {
var _this = this;
this.scroller.init(this.adapterRun$);
// set up scroll event listener
var routines = this.scroller.routines;
var onScrollHandler = function (event) {
return _this.callWorkflow({
process: CommonProcess.scroll,
status: Status.start,
payload: { event: event }
});
};
this.offScroll = routines.onScroll(onScrollHandler);
// run the Workflow
this.isInitialized = true;
this.callWorkflow({
process: CommonProcess.init,
status: Status.start
});
};
Workflow.prototype.changeItems = function (items) {
this.propagateChanges(items);
};
Workflow.prototype.callWorkflow = function (processSubject) {
if (!this.isInitialized) {
return;
}
var process = processSubject.process, status = processSubject.status;
// if the scroller is paused, any process other than "pause" and "reset" should be blocked
if (this.scroller.state.paused.get()) {
if (![AdapterProcess.pause, AdapterProcess.reset].includes(process)) {
this.scroller.logger.log('scroller is paused: ' + process + ' process is ignored');
return;
}
}
if (process && process.startsWith('adapter') && status !== Status.next) {
this.adapterRun$.set(processSubject);
}
this.process(processSubject);
};
Workflow.prototype.getUpdater = function () {
return {
call: this.callWorkflow.bind(this),
onDataChanged: this.changeItems.bind(this)
};
};
Workflow.prototype.process = function (data) {
var _this = this;
var status = data.status, process = data.process, payload = data.payload;
if (this.scroller.settings.logProcessRun) {
this.scroller.logger.log(function () {
var _fire = _this.scroller.settings.logColor
? ['%cfire%c', 'color: #cc7777;', 'color: #000000;']
: ['fire'];
return __spreadArray(__spreadArray(__spreadArray([], __read(_fire), false), [process, "\"".concat(status, "\"")], false), __read((payload !== void 0 ? [payload] : [])), false);
});
}
this.scroller.logger.logProcess(data);
if (process === CommonProcess.end) {
this.scroller.finalize();
}
runStateMachine({
input: data,
methods: this.stateMachineMethods
});
};
Workflow.prototype.runProcess = function () {
var _this = this;
return function (_a) {
var run = _a.run, process = _a.process, name = _a.name;
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (_this.scroller.settings.logProcessRun) {
_this.scroller.logger.log(function () {
var _run = _this.scroller.settings.logColor
? ['%crun%c', 'color: #333399;', 'color: #000000;']
: ['run'];
return __spreadArray(__spreadArray(__spreadArray([], __read(_run), false), [process || name], false), __read(args), false);
});
}
run.apply(void 0, __spreadArray([_this.scroller], __read(args), false));
};
};
};
Workflow.prototype.onError = function (process, payload) {
var message = (payload && String(payload.error)) || '';
var _a = this.scroller.state, time = _a.time, cycle = _a.cycle;
this.errors.push({
process: process,
message: message,
time: time,
loop: cycle.loopIdNext
});
this.scroller.logger.logError(message);
};
Workflow.prototype.interrupt = function (_a) {
var _this = this;
var process = _a.process, finalize = _a.finalize, datasource = _a.datasource;
if (finalize) {
var _b = this.scroller, workflow = _b.workflow, logger_1 = _b.logger;
// we are going to create a new reference for the scroller.workflow object
// calling the old version of the scroller.workflow by any outstanding async processes will be skipped
workflow.call = function (_) { return logger_1.log('[skip wf call]'); };
workflow.call.interrupted = true;
this.scroller.workflow = this.getUpdater();
this.interruptionCount++;
logger_1.log(function () { return "workflow had been interrupted by the ".concat(process, " process (").concat(_this.interruptionCount, ")"); });
}
if (datasource) {
// Scroller re-initialization case
var reInit = function () {
_this.scroller.logger.log('new Scroller instantiation');
var scroller = new Scroller({ datasource: datasource, scroller: _this.scroller });
_this.scroller.dispose();
_this.scroller = scroller;
_this.scroller.init();
};
if (this.scroller.state.cycle.busy.get()) {
// todo: think about immediate re-initialization even is there are pending processes
this.scroller.adapter.relax(reInit.bind(this));
}
else {
reInit();
}
}
};
Workflow.prototype.done = function () {
var _a = this.scroller, state = _a.state, logger = _a.logger;
this.cyclesDone++;
this.cyclesDone$.set(this.cyclesDone);
logger.logCycle(false);
state.endWorkflowCycle(this.cyclesDone + 1);
this.finalize();
};
Workflow.prototype.dispose = function () {
var _this = this;
this.scroller.logger.log(function () { return 'disposing workflow'; });
if (this.initTimer) {
clearTimeout(this.initTimer);
}
this.offScroll();
this.adapterRun$.dispose();
this.cyclesDone$.dispose();
this.scroller.dispose(true);
Object.getOwnPropertyNames(this).forEach(function (prop) {
delete _this[prop];
});
this.isInitialized = false;
this.disposed = true;
};
Workflow.prototype.finalize = function () { };
return Workflow;
}());
export { Workflow };
//# sourceMappingURL=workflow.js.map