Last active
April 10, 2019 00:08
-
-
Save Sawtaytoes/bb310267e0e236cbdb40d476c955c338 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
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[], subtractor: number, redos: T[]|null }>((d, x) => { | |
let { state, subtractor, redos } = d; | |
if (x === UNDO_TOKEN) { | |
// We were notified of an "undo". pop state. | |
if (state && state.length > 1) { | |
d.subtractor += state[state.length - 1] - state[state.length - 2]; | |
redos = redos || (d.redos = []); | |
redos.push(state.pop()); | |
} | |
} else if (x === REDO_TOKEN) { | |
if (redos && redos.length > 0) { | |
d.subtractor -= redos[redos.length - 1] - state[state.length - 1]; | |
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 - subtractor); | |
} | |
return d; | |
}, { state: null, subtractor: 0, 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