svg-layout-designer-react/src/Components/App/App.tsx
2022-11-04 12:05:37 +01:00

132 lines
3.8 KiB
TypeScript

import React, { Dispatch, SetStateAction, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { UseCustomEvents } from '../../Events/AppEvents';
import { MainMenu } from '../MainMenu/MainMenu';
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
import { Editor } from '../Editor/Editor';
import { IEditorState } from '../../Interfaces/IEditorState';
import { LoadState } from './Actions/Load';
import { LoadEditor, NewEditor } from './Actions/MenuActions';
import { DEFAULT_CONFIG, DEFAULT_MAINCONTAINER_PROPS, FAST_BOOT } from '../../utils/default';
import { AppState } from '../../Enums/AppState';
import { Loader } from '../Loader/Loader';
import { LanguageContext } from '../LanguageProvider/LanguageProvider';
// App will never have props
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IAppProps {
root: Element | Document
}
function UseHTTPGETStatePreloading(
appState: AppState,
setEditorState: Dispatch<SetStateAction<IEditorState>>,
setAppState: Dispatch<SetStateAction<AppState>>
): void {
useEffect(() => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const state = urlParams.get('state');
if (state === null) {
return;
}
if (appState !== AppState.Loaded) {
fetch(state)
.then(
async(response) => await response.json(),
(error) => { throw new Error(error); }
)
.then((data: IEditorState) => {
LoadState(data, setEditorState, setAppState);
}, (error) => { throw new Error(error); });
}
});
};
export function App(props: IAppProps): JSX.Element {
const [appState, setAppState] = useState<AppState>(FAST_BOOT);
const appRef = useRef<HTMLDivElement>(null);
const languageContext = useContext(LanguageContext);
const defaultMainContainer = new ContainerModel(
DEFAULT_MAINCONTAINER_PROPS
);
const containers = new Map<string, IContainerModel>();
containers.set(defaultMainContainer.properties.id, defaultMainContainer);
const [editorState, setEditorState] = useState<IEditorState>({
configuration: DEFAULT_CONFIG,
history: [{
lastAction: '',
mainContainer: defaultMainContainer.properties.id,
containers,
selectedContainerId: defaultMainContainer.properties.id,
typeCounters: {},
symbols: new Map(),
selectedSymbolId: ''
}],
historyCurrentStep: 0
});
UseCustomEvents(
props.root,
appRef,
languageContext,
setEditorState,
setAppState
);
UseHTTPGETStatePreloading(appState, setEditorState, setAppState);
switch (appState) {
case AppState.Loaded:
return (
<div
ref={appRef}
className='App'
>
<Editor
root={props.root}
configuration={editorState.configuration}
history={editorState.history}
historyCurrentStep={editorState.historyCurrentStep}
/>
</div>
);
case AppState.Loading:
return (
<div
ref={appRef}
className='App mainmenu-bg'
>
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
<Loader />
</div>
</div>
);
default:
return (
<div
ref={appRef}
className='App mainmenu-bg'
>
<MainMenu
newEditor={() => {
setAppState(AppState.Loading);
NewEditor(
editorState,
(newEditor) => setEditorState(newEditor),
() => setAppState(AppState.Loaded)
);
}}
loadEditor={(files: FileList | null) => LoadEditor(
files,
setEditorState,
setAppState
)}
/>
</div>
);
}
};