Last active
April 9, 2019 23:30
-
-
Save Sawtaytoes/66f318b64712c11c9d95e2c790e5d678 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Subscribes to the `undoNotifier`, and emits all values from | |
* `source`. When `undoNotifier` emits, it will emit previously | |
* emitted values back through time. | |
* | |
* If a `redoNotifier` is passed, it's subscribed to, and when | |
* it emits, will "redo" anything that was "undone", unless new | |
* values have come from the source. | |
* | |
* TODO: Add an upper-bounds to the undo state collected. | |
*/ | |
function undo<T>(undoNotifier: Observable<any>, redoNotifier: Observable<any> = EMPTY) { | |
return (source: Observable<T>) => merge( | |
undoNotifier.pipe(map(() => UNDO_TOKEN)), | |
redoNotifier.pipe(map(() => REDO_TOKEN)), | |
source, | |
).pipe( | |
scan<T, { state: T[], redos: T[]|null }>((d, x) => { | |
console.log({d, x}) | |
let { state, redos } = d; | |
if (x === UNDO_TOKEN) { | |
// We were notified of an "undo". pop state. | |
if (state && state.length > 1) { | |
redos = redos || (d.redos = []); | |
redos.push(state.pop()); | |
} | |
} else if (x === REDO_TOKEN) { | |
if (redos && redos.length > 0) { | |
state.push(redos.pop()); | |
} | |
} else { | |
if (redos) { | |
// clear our redos as new history is written | |
redos.length = 0; | |
} | |
state = state || (d.state = []); | |
// It's not an "undo", push state | |
state.push(x); | |
} | |
return d; | |
}, { state: null, redos: null }), | |
// we only care about state past here | |
map(x => x.state), | |
// Don't emit if we don't have state | |
filter(x => x !== null), | |
// Take the last value from state | |
map(state => state[state.length - 1]), | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment