mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
4465950f0c
* feat: add bounded undo and redo history * fix: address undo redo review feedback * chore: refresh guide viewer manifest * fix undo history review regressions * chore: refresh guide viewer manifest
59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { DEFAULT_STATE, type AnnotatorState, type Stroke } from './types';
|
|
|
|
/** Internal image-annotator state that adds redo without widening the published state contract. */
|
|
export interface StrokeHistoryState extends AnnotatorState {
|
|
/** Strokes removed by undo, newest redo candidate last. */
|
|
futureStrokes: Stroke[];
|
|
}
|
|
|
|
/** Initial state for the image annotator's internal stroke history. */
|
|
export const DEFAULT_STROKE_HISTORY_STATE: StrokeHistoryState = {
|
|
...DEFAULT_STATE,
|
|
futureStrokes: [],
|
|
};
|
|
|
|
/** Commit a completed stroke and invalidate the abandoned redo branch. */
|
|
export function recordStroke(state: StrokeHistoryState, stroke: Stroke): StrokeHistoryState {
|
|
return {
|
|
...state,
|
|
strokes: [...state.strokes, stroke],
|
|
futureStrokes: [],
|
|
currentStroke: null,
|
|
};
|
|
}
|
|
|
|
/** Move the latest visible stroke to the redo stack. */
|
|
export function undoStroke(state: StrokeHistoryState): StrokeHistoryState {
|
|
const stroke = state.strokes.at(-1);
|
|
if (!stroke) return state;
|
|
return {
|
|
...state,
|
|
strokes: state.strokes.slice(0, -1),
|
|
futureStrokes: [...state.futureStrokes, stroke],
|
|
currentStroke: null,
|
|
};
|
|
}
|
|
|
|
/** Restore the latest stroke removed by undo. */
|
|
export function redoStroke(state: StrokeHistoryState): StrokeHistoryState {
|
|
const stroke = state.futureStrokes.at(-1);
|
|
if (!stroke) return state;
|
|
return {
|
|
...state,
|
|
strokes: [...state.strokes, stroke],
|
|
futureStrokes: state.futureStrokes.slice(0, -1),
|
|
currentStroke: null,
|
|
};
|
|
}
|
|
|
|
/** Clear the canvas and invalidate both stroke branches. */
|
|
export function clearStrokeHistory(state: StrokeHistoryState): StrokeHistoryState {
|
|
if (state.strokes.length === 0 && state.futureStrokes.length === 0 && state.currentStroke === null) return state;
|
|
return {
|
|
...state,
|
|
strokes: [],
|
|
futureStrokes: [],
|
|
currentStroke: null,
|
|
};
|
|
}
|