obsidian-visualiser/shared/history.util.ts

94 lines
2.5 KiB
TypeScript

export type HistoryHandler = {
undo: (action: HistoryAction) => void;
redo: (action: HistoryAction) => void;
}
interface HistoryEvent
{
source: string;
event: string;
actions: HistoryAction[];
}
interface HistoryAction
{
element: any;
from?: any;
to?: any;
}
export class History
{
private handlers: Record<string, { handlers: Record<string, HistoryHandler>, any?: (action: HistoryAction) => any }>;
private history: HistoryEvent[];
private position: number;
constructor()
{
this.handlers = {};
this.history = [];
this.position = -1;
}
get last()
{
return this.history.length > 0 && this.position > -1 ? this.history[this.position] : undefined;
}
get undoable()
{
return this.history && this.position !== -1;
}
get redoable()
{
return this.history && this.position < this.history.length - 1;
}
undo()
{
const last = this.last;
if(!last)
return;
last.actions.forEach(e => {
this.handlers[last.source] && this.handlers[last.source].handlers[last.event]?.undo(e)
this.handlers[last.source] && this.handlers[last.source].any && this.handlers[last.source].any!(e);
});
this.position--;
}
redo()
{
if(!this.history || this.history.length - 1 <= this.position)
return;
this.position++;
const last = this.last;
if(!last)
{
this.position--;
return;
}
last.actions.forEach(e => {
this.handlers[last.source] && this.handlers[last.source].handlers[last.event]?.redo(e)
this.handlers[last.source] && this.handlers[last.source].any && this.handlers[last.source].any!(e);
});
}
add(source: string, event: string, actions: HistoryAction[], apply: boolean = false)
{
this.position++;
this.history.splice(this.position, history.length - this.position, { source, event, actions });
if(apply)
actions.forEach(e => {
this.handlers[source] && this.handlers[source].handlers[event]?.redo(e);
this.handlers[source] && this.handlers[source].any && this.handlers[source].any(e);
});
}
register(source: string, handlers: Record<string, HistoryHandler>, any?: (action: HistoryAction) => any)
{
this.handlers[source] = { handlers, any };
}
unregister(source: string)
{
delete this.handlers[source];
}
}