import React from "react"; import { Action, ActionsManagerInterface, UpdaterFn, ActionFilterFn, } from "./types"; import { ExcalidrawElement } from "../element/types"; import { AppState } from "../types"; import { t } from "../i18n"; export class ActionManager implements ActionsManagerInterface { actions: { [keyProp: string]: Action } = {}; updater: UpdaterFn; resumeHistoryRecording: () => void; getAppState: () => AppState; getElements: () => readonly ExcalidrawElement[]; constructor( updater: UpdaterFn, resumeHistoryRecording: () => void, getAppState: () => AppState, getElements: () => readonly ExcalidrawElement[], ) { this.updater = updater; this.resumeHistoryRecording = resumeHistoryRecording; this.getAppState = getAppState; this.getElements = getElements; } registerAction(action: Action) { this.actions[action.name] = action; } handleKeyDown(event: KeyboardEvent) { const data = Object.values(this.actions) .sort((a, b) => (b.keyPriority || 0) - (a.keyPriority || 0)) .filter( action => action.keyTest && action.keyTest(event, this.getAppState(), this.getElements()), ); if (data.length === 0) { return null; } event.preventDefault(); if ( data[0].commitToHistory && data[0].commitToHistory(this.getAppState(), this.getElements()) ) { this.resumeHistoryRecording(); } return data[0].perform(this.getElements(), this.getAppState(), null); } getContextMenuItems(actionFilter: ActionFilterFn = action => action) { return Object.values(this.actions) .filter(actionFilter) .filter(action => "contextItemLabel" in action) .sort( (a, b) => (a.contextMenuOrder !== undefined ? a.contextMenuOrder : 999) - (b.contextMenuOrder !== undefined ? b.contextMenuOrder : 999), ) .map(action => ({ label: action.contextItemLabel ? t(action.contextItemLabel) : "", action: () => { if ( action.commitToHistory && action.commitToHistory(this.getAppState(), this.getElements()) ) { this.resumeHistoryRecording(); } this.updater( action.perform(this.getElements(), this.getAppState(), null), ); }, })); } renderAction(name: string) { if (this.actions[name] && "PanelComponent" in this.actions[name]) { const action = this.actions[name]; const PanelComponent = action.PanelComponent!; const updateData = (formState: any) => { if ( action.commitToHistory && action.commitToHistory(this.getAppState(), this.getElements()) === true ) { this.resumeHistoryRecording(); } this.updater( action.perform(this.getElements(), this.getAppState(), formState), ); }; return ( ); } return null; } }