|
@@ -1,5 +1,5 @@
|
|
|
import React, {
|
|
import React, {
|
|
|
- useCallback, useEffect, useMemo, useRef,
|
|
|
|
|
|
|
+ useCallback, useEffect, useMemo, useRef, useState,
|
|
|
} from 'react';
|
|
} from 'react';
|
|
|
|
|
|
|
|
import EventEmitter from 'events';
|
|
import EventEmitter from 'events';
|
|
@@ -8,35 +8,55 @@ import { useTranslation } from 'react-i18next';
|
|
|
import { debounce } from 'throttle-debounce';
|
|
import { debounce } from 'throttle-debounce';
|
|
|
|
|
|
|
|
import { CustomWindow } from '~/interfaces/global';
|
|
import { CustomWindow } from '~/interfaces/global';
|
|
|
-import { IGraphViewer } from '~/interfaces/graph-viewer';
|
|
|
|
|
|
|
+import { IGraphViewer, isGraphViewer } from '~/interfaces/graph-viewer';
|
|
|
|
|
|
|
|
import NotAvailableForGuest from './NotAvailableForGuest';
|
|
import NotAvailableForGuest from './NotAvailableForGuest';
|
|
|
|
|
|
|
|
type Props = {
|
|
type Props = {
|
|
|
|
|
+ GraphViewer: IGraphViewer,
|
|
|
drawioContent: string,
|
|
drawioContent: string,
|
|
|
rangeLineNumberOfMarkdown: { beginLineNumber: number, endLineNumber: number },
|
|
rangeLineNumberOfMarkdown: { beginLineNumber: number, endLineNumber: number },
|
|
|
isPreview?: boolean,
|
|
isPreview?: boolean,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// It calls callback when GraphViewer is not null.
|
|
|
|
|
+// eslint-disable-next-line @typescript-eslint/ban-types
|
|
|
|
|
+const waitForGraphViewer = async(callback: Function) => {
|
|
|
|
|
+ const MAX_WAIT_COUNT = 10; // no reason for 10
|
|
|
|
|
+
|
|
|
|
|
+ for (let i = 0; i < MAX_WAIT_COUNT; i++) {
|
|
|
|
|
+ if (isGraphViewer((window as CustomWindow).GraphViewer)) {
|
|
|
|
|
+ callback((window as CustomWindow).GraphViewer);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Sleep 500 ms
|
|
|
|
|
+ // eslint-disable-next-line no-await-in-loop
|
|
|
|
|
+ await new Promise<void>(r => setTimeout(() => r(), 500));
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const Drawio = (props: Props): JSX.Element => {
|
|
const Drawio = (props: Props): JSX.Element => {
|
|
|
|
|
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
|
|
|
|
|
|
|
+ // Wrap with a function since GraphViewer is a function.
|
|
|
|
|
+ // This applies when call setGraphViewer as well.
|
|
|
|
|
+ const [GraphViewer, setGraphViewer] = useState<IGraphViewer | undefined>(() => (window as CustomWindow).GraphViewer);
|
|
|
|
|
+
|
|
|
const { drawioContent, rangeLineNumberOfMarkdown, isPreview } = props;
|
|
const { drawioContent, rangeLineNumberOfMarkdown, isPreview } = props;
|
|
|
|
|
|
|
|
// const { open: openDrawioModal } = useDrawioModalForPage();
|
|
// const { open: openDrawioModal } = useDrawioModalForPage();
|
|
|
|
|
|
|
|
const drawioContainerRef = useRef<HTMLDivElement>(null);
|
|
const drawioContainerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
- const globalEmitter: EventEmitter = useMemo(() => (window as CustomWindow).globalEmitter, []);
|
|
|
|
|
- const GraphViewer: IGraphViewer = useMemo(() => (window as CustomWindow).GraphViewer, []);
|
|
|
|
|
|
|
+ const globalEmitter: EventEmitter = (window as CustomWindow).globalEmitter;
|
|
|
|
|
|
|
|
const editButtonClickHandler = useCallback(() => {
|
|
const editButtonClickHandler = useCallback(() => {
|
|
|
const { beginLineNumber, endLineNumber } = rangeLineNumberOfMarkdown;
|
|
const { beginLineNumber, endLineNumber } = rangeLineNumberOfMarkdown;
|
|
|
globalEmitter.emit('launchDrawioModal', beginLineNumber, endLineNumber);
|
|
globalEmitter.emit('launchDrawioModal', beginLineNumber, endLineNumber);
|
|
|
}, [rangeLineNumberOfMarkdown, globalEmitter]);
|
|
}, [rangeLineNumberOfMarkdown, globalEmitter]);
|
|
|
|
|
|
|
|
- const renderDrawio = useCallback(() => {
|
|
|
|
|
|
|
+ const renderDrawio = useCallback((GraphViewer: IGraphViewer) => {
|
|
|
if (drawioContainerRef.current == null) {
|
|
if (drawioContainerRef.current == null) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -51,16 +71,19 @@ const Drawio = (props: Props): JSX.Element => {
|
|
|
GraphViewer.createViewerForElement(div);
|
|
GraphViewer.createViewerForElement(div);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }, [GraphViewer]);
|
|
|
|
|
|
|
+ }, [drawioContainerRef]);
|
|
|
|
|
|
|
|
const renderDrawioWithDebounce = useMemo(() => debounce(200, renderDrawio), [renderDrawio]);
|
|
const renderDrawioWithDebounce = useMemo(() => debounce(200, renderDrawio), [renderDrawio]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
if (GraphViewer == null) {
|
|
if (GraphViewer == null) {
|
|
|
|
|
+ waitForGraphViewer((gv: IGraphViewer) => {
|
|
|
|
|
+ setGraphViewer(() => gv);
|
|
|
|
|
+ });
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- renderDrawioWithDebounce();
|
|
|
|
|
|
|
+ renderDrawioWithDebounce(GraphViewer);
|
|
|
}, [renderDrawioWithDebounce, GraphViewer]);
|
|
}, [renderDrawioWithDebounce, GraphViewer]);
|
|
|
|
|
|
|
|
return (
|
|
return (
|