@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
95 lines (94 loc) • 3 kB
JavaScript
import { applySnapshot, getEnv, getSnapshot, onSnapshot, resolvePath, types, } from '@jbrowse/mobx-state-tree';
const MAX_HISTORY_LENGTH = 20;
const TimeTraveller = types
.model('TimeTraveller', {
undoIdx: -1,
targetPath: '',
})
.volatile(() => ({
history: [],
notTrackingUndo: false,
}))
.views(self => ({
get canUndo() {
return self.undoIdx > 0 && !self.notTrackingUndo;
},
get canRedo() {
return self.undoIdx < self.history.length - 1 && !self.notTrackingUndo;
},
}))
.actions(self => {
let targetStore;
let snapshotDisposer;
let skipNextUndoState = false;
let debounceTimer;
let pendingSnapshot;
return {
stopTrackingUndo() {
self.notTrackingUndo = true;
},
resumeTrackingUndo() {
self.notTrackingUndo = false;
},
addUndoState(snapshot) {
if (self.notTrackingUndo) {
return;
}
if (skipNextUndoState) {
skipNextUndoState = false;
return;
}
self.history.splice(self.undoIdx + 1);
self.history.push(snapshot);
if (self.history.length > MAX_HISTORY_LENGTH) {
self.history.shift();
}
self.undoIdx = self.history.length - 1;
},
beforeDestroy() {
snapshotDisposer();
if (debounceTimer) {
clearTimeout(debounceTimer);
}
},
initialize() {
targetStore = self.targetPath
? resolvePath(self, self.targetPath)
: getEnv(self).targetStore;
if (!targetStore) {
throw new Error('Failed to find target store for TimeTraveller. Please provide `targetPath` property, or a `targetStore` in the environment');
}
snapshotDisposer = onSnapshot(targetStore, snapshot => {
if (self.notTrackingUndo || skipNextUndoState) {
return;
}
pendingSnapshot = snapshot;
if (debounceTimer) {
clearTimeout(debounceTimer);
}
debounceTimer = setTimeout(() => {
debounceTimer = undefined;
this.addUndoState(pendingSnapshot);
}, 300);
});
if (self.history.length === 0) {
this.addUndoState(getSnapshot(targetStore));
}
},
undo() {
self.undoIdx--;
skipNextUndoState = true;
if (targetStore) {
applySnapshot(targetStore, self.history[self.undoIdx]);
}
},
redo() {
self.undoIdx++;
skipNextUndoState = true;
if (targetStore) {
applySnapshot(targetStore, self.history[self.undoIdx]);
}
},
};
});
export default TimeTraveller;