UNPKG

rrweb

Version:
233 lines (230 loc) 8.9 kB
import { __assign, __values } from '../../node_modules/tslib/tslib.es6.js'; import { ReplayerEvents, EventType } from '../types.js'; import { needCastInSyncMode } from '../utils.js'; import { addDelay } from './timer.js'; import { interpret as f, createMachine as c, assign as r } from '../../node_modules/@xstate/fsm/es/index.js'; function discardPriorSnapshots(events, baselineTime) { for (var idx = events.length - 1; idx >= 0; idx--) { var event = events[idx]; if (event.type === EventType.Meta) { if (event.timestamp <= baselineTime) { return events.slice(idx); } } } return events; } function createPlayerService(context, _a) { var getCastFn = _a.getCastFn, emitter = _a.emitter; var playerMachine = c({ id: 'player', context: context, initial: 'paused', states: { playing: { on: { PAUSE: { target: 'paused', actions: ['pause'], }, CAST_EVENT: { target: 'playing', actions: 'castEvent', }, END: { target: 'paused', actions: ['resetLastPlayedEvent', 'pause'], }, }, }, paused: { on: { PLAY: { target: 'playing', actions: ['recordTimeOffset', 'play'], }, CAST_EVENT: { target: 'paused', actions: 'castEvent', }, }, }, live: { on: { ADD_EVENT: { target: 'live', actions: ['addEvent'], }, }, }, }, }, { actions: { castEvent: r({ lastPlayedEvent: function (ctx, event) { if (event.type === 'CAST_EVENT') { return event.payload.event; } return ctx.lastPlayedEvent; }, }), recordTimeOffset: r(function (ctx, event) { var timeOffset = ctx.timeOffset; if ('payload' in event && 'timeOffset' in event.payload) { timeOffset = event.payload.timeOffset; } return __assign(__assign({}, ctx), { timeOffset: timeOffset, baselineTime: ctx.events[0].timestamp + timeOffset }); }), play: function (ctx) { var e_1, _a, e_2, _b; var timer = ctx.timer, events = ctx.events, baselineTime = ctx.baselineTime, lastPlayedEvent = ctx.lastPlayedEvent; timer.clear(); try { for (var events_1 = __values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) { var event = events_1_1.value; addDelay(event, baselineTime); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1); } finally { if (e_1) throw e_1.error; } } var neededEvents = discardPriorSnapshots(events, baselineTime); var actions = new Array(); var _loop_1 = function (event) { if (lastPlayedEvent && lastPlayedEvent.timestamp < baselineTime && (event.timestamp <= lastPlayedEvent.timestamp || event === lastPlayedEvent)) { return "continue"; } var isSync = event.timestamp < baselineTime; if (isSync && !needCastInSyncMode(event)) { return "continue"; } var castFn = getCastFn(event, isSync); if (isSync) { castFn(); } else { actions.push({ doAction: function () { castFn(); emitter.emit(ReplayerEvents.EventCast, event); }, delay: event.delay, }); } }; try { for (var neededEvents_1 = __values(neededEvents), neededEvents_1_1 = neededEvents_1.next(); !neededEvents_1_1.done; neededEvents_1_1 = neededEvents_1.next()) { var event = neededEvents_1_1.value; _loop_1(event); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (neededEvents_1_1 && !neededEvents_1_1.done && (_b = neededEvents_1.return)) _b.call(neededEvents_1); } finally { if (e_2) throw e_2.error; } } emitter.emit(ReplayerEvents.Flush); timer.addActions(actions); timer.start(); }, pause: function (ctx) { ctx.timer.clear(); }, resetLastPlayedEvent: r(function (ctx) { return __assign(__assign({}, ctx), { lastPlayedEvent: null }); }), startLive: r({ baselineTime: function (ctx, event) { ctx.timer.toggleLiveMode(true); ctx.timer.start(); if (event.type === 'TO_LIVE' && event.payload.baselineTime) { return event.payload.baselineTime; } return Date.now(); }, }), addEvent: r(function (ctx, machineEvent) { var baselineTime = ctx.baselineTime, timer = ctx.timer, events = ctx.events; if (machineEvent.type === 'ADD_EVENT') { var event_1 = machineEvent.payload.event; addDelay(event_1, baselineTime); events.push(event_1); var isSync = event_1.timestamp < baselineTime; var castFn_1 = getCastFn(event_1, isSync); if (isSync) { castFn_1(); } else { timer.addAction({ doAction: function () { castFn_1(); emitter.emit(ReplayerEvents.EventCast, event_1); }, delay: event_1.delay, }); } } return __assign(__assign({}, ctx), { events: events }); }), }, }); return f(playerMachine); } function createSpeedService(context) { var speedMachine = c({ id: 'speed', context: context, initial: 'normal', states: { normal: { on: { FAST_FORWARD: { target: 'skipping', actions: ['recordSpeed', 'setSpeed'], }, SET_SPEED: { target: 'normal', actions: ['setSpeed'], }, }, }, skipping: { on: { BACK_TO_NORMAL: { target: 'normal', actions: ['restoreSpeed'], }, SET_SPEED: { target: 'normal', actions: ['setSpeed'], }, }, }, }, }, { actions: { setSpeed: function (ctx, event) { if ('payload' in event) { ctx.timer.setSpeed(event.payload.speed); } }, recordSpeed: r({ normalSpeed: function (ctx) { return ctx.timer.speed; }, }), restoreSpeed: function (ctx) { ctx.timer.setSpeed(ctx.normalSpeed); }, }, }); return f(speedMachine); } export { createPlayerService, createSpeedService, discardPriorSnapshots };