feat(history): add undo redo stack
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { AppState } from "@editor/state";
|
||||
import type { AppState, HistorySnapshot } from "@editor/state";
|
||||
import type { CommandContext } from "./command";
|
||||
import { commandIds } from "./ids";
|
||||
import type { CommandId, CommandPayloads } from "./payloads";
|
||||
import type { CommandRegistry } from "./registry";
|
||||
|
||||
@@ -21,10 +22,31 @@ export function createCommandDispatcher(options: {
|
||||
throw new Error(`Unknown command: ${commandId}`);
|
||||
}
|
||||
|
||||
const context: CommandContext = { state: options.getState() };
|
||||
const nextState = command.execute(context, payload);
|
||||
const currentState = options.getState();
|
||||
const context: CommandContext = { state: currentState };
|
||||
const executedState = command.execute(context, payload);
|
||||
const nextState = shouldRecordHistory(commandId, currentState, executedState) ? recordHistory(currentState, executedState) : executedState;
|
||||
options.setState(nextState);
|
||||
return nextState;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function shouldRecordHistory(commandId: CommandId, currentState: AppState, nextState: AppState) {
|
||||
if (commandId === commandIds.historyUndo || commandId === commandIds.historyRedo) return false;
|
||||
return currentState.document !== nextState.document;
|
||||
}
|
||||
|
||||
function recordHistory(currentState: AppState, nextState: AppState): AppState {
|
||||
return {
|
||||
...nextState,
|
||||
history: {
|
||||
past: [...currentState.history.past, snapshot(currentState)].slice(-100),
|
||||
future: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function snapshot(state: AppState): HistorySnapshot {
|
||||
return { document: state.document, editor: state.editor };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user