Files
image-studio/commands/dispatcher.ts
syntaxbullet 4ad0bb8b2c feat: enhance layer masking functionality and brush controls
- Refactor LayersSheet component to support mask editing state and improve layer visibility handling.
- Introduce functions to collect mask layer IDs and count display layers excluding masks.
- Update BrushControls to include mask view mode options and a Done button for exiting mask editing.
- Modify brush session handling to support brush previews when editing masks.
- Implement a new BrushPreviewRenderer for rendering brush strokes with visual feedback.
- Add document geometry utilities for transforming points and resolving layer bounds.
- Ensure proper cleanup of brush preview on pointer leave and other interactions.
2026-07-03 20:49:29 +02:00

60 lines
1.9 KiB
TypeScript

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";
export type Dispatch = <TCommandId extends CommandId>(commandId: TCommandId, payload: CommandPayloads[TCommandId]) => AppState;
export type CommandDispatcher = {
dispatch: Dispatch;
};
export function createCommandDispatcher(options: {
registry: CommandRegistry;
getState: () => AppState;
setState: (state: AppState) => void;
}): CommandDispatcher {
return {
dispatch(commandId, payload) {
const command = options.registry.get(commandId);
if (!command) {
throw new Error(`Unknown command: ${commandId}`);
}
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,
brushPreview: undefined,
brushStrokePreview: undefined,
},
};
}