Refactor App and Editor events
This commit is contained in:
parent
28b0965626
commit
d05d0fb196
5 changed files with 209 additions and 203 deletions
|
@ -1,5 +1,5 @@
|
|||
import React, { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { events as EVENTS } from '../../Events/AppEvents';
|
||||
import { events as EVENTS, UseCustomEvents } from '../../Events/AppEvents';
|
||||
import { MainMenu } from '../MainMenu/MainMenu';
|
||||
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
|
||||
import { Editor } from '../Editor/Editor';
|
||||
|
@ -41,38 +41,6 @@ function UseHTTPGETStatePreloading(
|
|||
});
|
||||
};
|
||||
|
||||
function UseCustomEvents(
|
||||
root: Element | Document,
|
||||
appRef: React.RefObject<HTMLDivElement>,
|
||||
setEditor: (newState: IEditorState) => void,
|
||||
setLoaded: (loaded: boolean) => void
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const funcs = new Map<string, () => void>();
|
||||
for (const event of EVENTS) {
|
||||
function Func(eventInitDict?: CustomEventInit): void {
|
||||
return event.func(
|
||||
root,
|
||||
setEditor,
|
||||
setLoaded,
|
||||
eventInitDict
|
||||
);
|
||||
}
|
||||
appRef.current?.addEventListener(event.name, Func);
|
||||
funcs.set(event.name, Func);
|
||||
}
|
||||
return () => {
|
||||
for (const event of EVENTS) {
|
||||
const func = funcs.get(event.name);
|
||||
if (func === undefined) {
|
||||
continue;
|
||||
}
|
||||
appRef.current?.removeEventListener(event.name, func);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function App(props: IAppProps): JSX.Element {
|
||||
const [isLoaded, setLoaded] = useState<boolean>(false);
|
||||
const appRef = useRef<HTMLDivElement>(null);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Swal from 'sweetalert2';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { AddMethod } from '../../../Enums/AddMethod';
|
||||
import { IAction } from '../../../Interfaces/IAction';
|
||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||
|
@ -6,13 +7,122 @@ import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
|||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||
import { ISetContainerListRequest } from '../../../Interfaces/ISetContainerListRequest';
|
||||
import { ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
|
||||
import { DISABLE_API } from '../../../utils/default';
|
||||
import { FindContainerById } from '../../../utils/itertools';
|
||||
import { SetContainerList } from '../../API/api';
|
||||
import { IMenuAction } from '../../Menu/Menu';
|
||||
import { GetCurrentHistoryState } from '../Editor';
|
||||
import { AddContainers } from './AddContainer';
|
||||
import { DeleteContainer } from './ContainerOperations';
|
||||
import { DeleteSymbol } from './SymbolOperations';
|
||||
|
||||
export function GetAction(
|
||||
export function InitActions(
|
||||
menuActions: Map<string, IMenuAction[]>,
|
||||
configuration: IConfiguration,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setNewHistory: (newHistory: IHistoryState[]) => void,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
menuActions.set(
|
||||
'',
|
||||
[
|
||||
{
|
||||
text: 'Undo',
|
||||
title: 'Undo last action',
|
||||
shortcut: '<kbd>Ctrl</kbd>+<kbd>Z</kbd>',
|
||||
action: () => {
|
||||
if (historyCurrentStep <= 0) {
|
||||
return;
|
||||
}
|
||||
setHistoryCurrentStep(historyCurrentStep - 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Redo',
|
||||
title: 'Redo last action',
|
||||
shortcut: '<kbd>Ctrl</kbd>+<kbd>Y</kbd>',
|
||||
action: () => {
|
||||
if (historyCurrentStep >= history.length - 1) {
|
||||
return;
|
||||
}
|
||||
setHistoryCurrentStep(historyCurrentStep + 1);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
menuActions.set(
|
||||
'elements-sidebar-row',
|
||||
[{
|
||||
text: 'Delete',
|
||||
title: 'Delete the container',
|
||||
shortcut: '<kbd>Suppr</kbd>',
|
||||
action: (target: HTMLElement) => {
|
||||
const id = target.id;
|
||||
const newHistory = DeleteContainer(
|
||||
id,
|
||||
history,
|
||||
historyCurrentStep
|
||||
);
|
||||
setNewHistory(newHistory);
|
||||
}
|
||||
}]
|
||||
);
|
||||
|
||||
menuActions.set(
|
||||
'symbols-sidebar-row',
|
||||
[{
|
||||
text: 'Delete',
|
||||
title: 'Delete the container',
|
||||
shortcut: '<kbd>Suppr</kbd>',
|
||||
action: (target: HTMLElement) => {
|
||||
const id = target.id;
|
||||
const newHistory = DeleteSymbol(
|
||||
id,
|
||||
history,
|
||||
historyCurrentStep
|
||||
);
|
||||
setNewHistory(newHistory);
|
||||
}
|
||||
}]
|
||||
);
|
||||
|
||||
// API Actions
|
||||
if (DISABLE_API) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const availableContainer of configuration.AvailableContainers) {
|
||||
if (availableContainer.Actions === undefined || availableContainer.Actions === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const action of availableContainer.Actions) {
|
||||
if (menuActions.get(availableContainer.Type) === undefined) {
|
||||
menuActions.set(availableContainer.Type, []);
|
||||
}
|
||||
|
||||
const currentState = GetCurrentHistoryState(history, historyCurrentStep);
|
||||
const newAction: IMenuAction = {
|
||||
text: action.Label,
|
||||
title: action.Description,
|
||||
action: GetAction(
|
||||
action,
|
||||
currentState,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep,
|
||||
setNewHistory
|
||||
)
|
||||
};
|
||||
|
||||
menuActions.get(availableContainer.Type)?.push(newAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function GetAction(
|
||||
action: IAction,
|
||||
currentState: IHistoryState,
|
||||
configuration: IConfiguration,
|
||||
|
|
|
@ -6,13 +6,12 @@ import { UI } from '../UI/UI';
|
|||
import { SelectContainer, DeleteContainer, OnPropertyChange } from './Actions/ContainerOperations';
|
||||
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
|
||||
import { OnKey } from './Actions/Shortcuts';
|
||||
import { events as EVENTS } from '../../Events/EditorEvents';
|
||||
import { IEditorState } from '../../Interfaces/IEditorState';
|
||||
import { DISABLE_API, MAX_HISTORY } from '../../utils/default';
|
||||
import { UseCustomEvents, UseEditorListener } from '../../Events/EditorEvents';
|
||||
import { MAX_HISTORY } from '../../utils/default';
|
||||
import { AddSymbol, OnPropertyChange as OnSymbolPropertyChange, DeleteSymbol, SelectSymbol } from './Actions/SymbolOperations';
|
||||
import { FindContainerById } from '../../utils/itertools';
|
||||
import { IMenuAction, Menu } from '../Menu/Menu';
|
||||
import { GetAction } from './Actions/ContextMenuActions';
|
||||
import { Menu } from '../Menu/Menu';
|
||||
import { InitActions } from './Actions/ContextMenuActions';
|
||||
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
|
||||
|
||||
interface IEditorProps {
|
||||
|
@ -22,112 +21,6 @@ interface IEditorProps {
|
|||
historyCurrentStep: number
|
||||
}
|
||||
|
||||
function InitActions(
|
||||
menuActions: Map<string, IMenuAction[]>,
|
||||
configuration: IConfiguration,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setNewHistory: (newHistory: IHistoryState[]) => void,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
menuActions.set(
|
||||
'',
|
||||
[
|
||||
{
|
||||
text: 'Undo',
|
||||
title: 'Undo last action',
|
||||
shortcut: '<kbd>Ctrl</kbd>+<kbd>Z</kbd>',
|
||||
action: () => {
|
||||
if (historyCurrentStep <= 0) {
|
||||
return;
|
||||
}
|
||||
setHistoryCurrentStep(historyCurrentStep - 1);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Redo',
|
||||
title: 'Redo last action',
|
||||
shortcut: '<kbd>Ctrl</kbd>+<kbd>Y</kbd>',
|
||||
action: () => {
|
||||
if (historyCurrentStep >= history.length - 1) {
|
||||
return;
|
||||
}
|
||||
setHistoryCurrentStep(historyCurrentStep + 1);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
menuActions.set(
|
||||
'elements-sidebar-row',
|
||||
[{
|
||||
text: 'Delete',
|
||||
title: 'Delete the container',
|
||||
shortcut: '<kbd>Suppr</kbd>',
|
||||
action: (target: HTMLElement) => {
|
||||
const id = target.id;
|
||||
const newHistory = DeleteContainer(
|
||||
id,
|
||||
history,
|
||||
historyCurrentStep
|
||||
);
|
||||
setNewHistory(newHistory);
|
||||
}
|
||||
}]
|
||||
);
|
||||
|
||||
menuActions.set(
|
||||
'symbols-sidebar-row',
|
||||
[{
|
||||
text: 'Delete',
|
||||
title: 'Delete the container',
|
||||
shortcut: '<kbd>Suppr</kbd>',
|
||||
action: (target: HTMLElement) => {
|
||||
const id = target.id;
|
||||
const newHistory = DeleteSymbol(
|
||||
id,
|
||||
history,
|
||||
historyCurrentStep
|
||||
);
|
||||
setNewHistory(newHistory);
|
||||
}
|
||||
}]
|
||||
);
|
||||
|
||||
// API Actions
|
||||
if (DISABLE_API) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const availableContainer of configuration.AvailableContainers) {
|
||||
if (availableContainer.Actions === undefined || availableContainer.Actions === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const action of availableContainer.Actions) {
|
||||
if (menuActions.get(availableContainer.Type) === undefined) {
|
||||
menuActions.set(availableContainer.Type, []);
|
||||
}
|
||||
|
||||
const currentState = GetCurrentHistoryState(history, historyCurrentStep);
|
||||
const newAction: IMenuAction = {
|
||||
text: action.Label,
|
||||
title: action.Description,
|
||||
action: GetAction(
|
||||
action,
|
||||
currentState,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep,
|
||||
setNewHistory
|
||||
)
|
||||
};
|
||||
|
||||
menuActions.get(availableContainer.Type)?.push(newAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UseShortcuts(
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
|
@ -152,63 +45,6 @@ function UseShortcuts(
|
|||
});
|
||||
}
|
||||
|
||||
function UseCustomEvents(
|
||||
root: Element | Document,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
configuration: IConfiguration,
|
||||
editorRef: React.RefObject<HTMLDivElement>,
|
||||
setNewHistory: (newHistory: IHistoryState[], historyCurrentStep?: number) => void
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const editorState: IEditorState = {
|
||||
history,
|
||||
historyCurrentStep,
|
||||
configuration
|
||||
};
|
||||
|
||||
const funcs = new Map<string, () => void>();
|
||||
for (const event of EVENTS) {
|
||||
function Func(eventInitDict?: CustomEventInit): void {
|
||||
return event.func(
|
||||
root,
|
||||
editorState,
|
||||
setNewHistory,
|
||||
eventInitDict
|
||||
);
|
||||
}
|
||||
editorRef.current?.addEventListener(event.name, Func);
|
||||
funcs.set(event.name, Func);
|
||||
}
|
||||
return () => {
|
||||
for (const event of EVENTS) {
|
||||
const func = funcs.get(event.name);
|
||||
if (func === undefined) {
|
||||
continue;
|
||||
}
|
||||
editorRef.current?.removeEventListener(event.name, func);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function UseEditorListener(
|
||||
root: Element | Document,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
configuration: IConfiguration
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const editorState: IEditorState = {
|
||||
history,
|
||||
historyCurrentStep,
|
||||
configuration
|
||||
};
|
||||
const event = new CustomEvent('editorListener', { detail: editorState });
|
||||
root.dispatchEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a macro function to use both setHistory
|
||||
* and setHistoryCurrentStep at the same time
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { useEffect } from 'react';
|
||||
import { IConfiguration } from '../Interfaces/IConfiguration';
|
||||
import { IEditorState } from '../Interfaces/IEditorState';
|
||||
import { IHistoryState } from '../Interfaces/IHistoryState';
|
||||
|
@ -22,6 +23,38 @@ export const events: IAppEvent[] = [
|
|||
{ name: 'getDefaultEditorState', func: GetDefaultEditorState }
|
||||
];
|
||||
|
||||
export function UseCustomEvents(
|
||||
root: Element | Document,
|
||||
appRef: React.RefObject<HTMLDivElement>,
|
||||
setEditor: (newState: IEditorState) => void,
|
||||
setLoaded: (loaded: boolean) => void
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const funcs = new Map<string, () => void>();
|
||||
for (const event of events) {
|
||||
function Func(eventInitDict?: CustomEventInit): void {
|
||||
return event.func(
|
||||
root,
|
||||
setEditor,
|
||||
setLoaded,
|
||||
eventInitDict
|
||||
);
|
||||
}
|
||||
appRef.current?.addEventListener(event.name, Func);
|
||||
funcs.set(event.name, Func);
|
||||
}
|
||||
return () => {
|
||||
for (const event of events) {
|
||||
const func = funcs.get(event.name);
|
||||
if (func === undefined) {
|
||||
continue;
|
||||
}
|
||||
appRef.current?.removeEventListener(event.name, func);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function SetEditor(
|
||||
root: Element | Document,
|
||||
setEditor: (newState: IEditorState) => void,
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { useEffect } from 'react';
|
||||
import { AddContainer as AddContainerAction, AddContainerToSelectedContainer as AddContainerToSelectedContainerAction } from '../Components/Editor/Actions/AddContainer';
|
||||
import { DeleteContainer as DeleteContainerAction, SelectContainer as SelectContainerAction } from '../Components/Editor/Actions/ContainerOperations';
|
||||
import { AddSymbol as AddSymbolAction, DeleteSymbol as DeleteSymbolAction, SelectSymbol as SelectSymbolAction } from '../Components/Editor/Actions/SymbolOperations';
|
||||
import { GetCurrentHistory } from '../Components/Editor/Editor';
|
||||
import { IConfiguration } from '../Interfaces/IConfiguration';
|
||||
import { IEditorState } from '../Interfaces/IEditorState';
|
||||
import { IHistoryState } from '../Interfaces/IHistoryState';
|
||||
import { FindContainerById } from '../utils/itertools';
|
||||
import { GetCircularReplacer, ReviveHistory as ReviveHistoryAction } from '../utils/saveload';
|
||||
import { GetCircularReplacer } from '../utils/saveload';
|
||||
|
||||
export interface IEditorEvent {
|
||||
name: string
|
||||
|
@ -34,6 +36,63 @@ export const events: IEditorEvent[] = [
|
|||
{ name: 'deleteSymbol', func: DeleteSymbol }
|
||||
];
|
||||
|
||||
export function UseCustomEvents(
|
||||
root: Element | Document,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
configuration: IConfiguration,
|
||||
editorRef: React.RefObject<HTMLDivElement>,
|
||||
setNewHistory: (newHistory: IHistoryState[], historyCurrentStep?: number) => void
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const editorState: IEditorState = {
|
||||
history,
|
||||
historyCurrentStep,
|
||||
configuration
|
||||
};
|
||||
|
||||
const funcs = new Map<string, () => void>();
|
||||
for (const event of events) {
|
||||
function Func(eventInitDict?: CustomEventInit): void {
|
||||
return event.func(
|
||||
root,
|
||||
editorState,
|
||||
setNewHistory,
|
||||
eventInitDict
|
||||
);
|
||||
}
|
||||
editorRef.current?.addEventListener(event.name, Func);
|
||||
funcs.set(event.name, Func);
|
||||
}
|
||||
return () => {
|
||||
for (const event of events) {
|
||||
const func = funcs.get(event.name);
|
||||
if (func === undefined) {
|
||||
continue;
|
||||
}
|
||||
editorRef.current?.removeEventListener(event.name, func);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function UseEditorListener(
|
||||
root: Element | Document,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
configuration: IConfiguration
|
||||
): void {
|
||||
useEffect(() => {
|
||||
const editorState: IEditorState = {
|
||||
history,
|
||||
historyCurrentStep,
|
||||
configuration
|
||||
};
|
||||
const event = new CustomEvent('editorListener', { detail: editorState });
|
||||
root.dispatchEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
function GetEditorState(root: Element | Document,
|
||||
editorState: IEditorState): void {
|
||||
const customEvent = new CustomEvent<IEditorState>('getEditorState', { detail: structuredClone(editorState) });
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue