|
@@ -60,11 +60,9 @@ import loggerFactory from '~/utils/logger';
|
|
|
// import Editor from './Editor';
|
|
// import Editor from './Editor';
|
|
|
import EditorNavbarBottom from './EditorNavbarBottom';
|
|
import EditorNavbarBottom from './EditorNavbarBottom';
|
|
|
import Preview from './Preview';
|
|
import Preview from './Preview';
|
|
|
-import scrollSyncHelper from './ScrollSyncHelper';
|
|
|
|
|
-import { scrollEditor, scrollPreview } from './ScrollSyncHelperTest';
|
|
|
|
|
|
|
+import { scrollEditor, scrollPreview } from './ScrollSyncHelper';
|
|
|
|
|
|
|
|
import '@growi/editor/dist/style.css';
|
|
import '@growi/editor/dist/style.css';
|
|
|
-import { preview } from 'vite';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const logger = loggerFactory('growi:PageEditor');
|
|
const logger = loggerFactory('growi:PageEditor');
|
|
@@ -75,13 +73,11 @@ declare global {
|
|
|
var globalEmitter: EventEmitter;
|
|
var globalEmitter: EventEmitter;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
// for scrolling
|
|
// for scrolling
|
|
|
-const lastScrolledDateWithCursor: Date | null = null;
|
|
|
|
|
|
|
+let lastScrolledDateWithCursor: Date | null = null;
|
|
|
let isOriginOfScrollSyncEditor = false;
|
|
let isOriginOfScrollSyncEditor = false;
|
|
|
let isOriginOfScrollSyncPreview = false;
|
|
let isOriginOfScrollSyncPreview = false;
|
|
|
|
|
|
|
|
-
|
|
|
|
|
type Props = {
|
|
type Props = {
|
|
|
visibility?: boolean,
|
|
visibility?: boolean,
|
|
|
}
|
|
}
|
|
@@ -358,112 +354,46 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
return AcceptedUploadFileType.IMAGE;
|
|
return AcceptedUploadFileType.IMAGE;
|
|
|
}, [isUploadAllFileAllowed, isUploadEnabled]);
|
|
}, [isUploadAllFileAllowed, isUploadEnabled]);
|
|
|
|
|
|
|
|
- const scrollPreviewByEditorLine = useCallback((line: number) => {
|
|
|
|
|
- if (previewRef.current == null) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // prevent circular invocation
|
|
|
|
|
- if (isOriginOfScrollSyncPreview) {
|
|
|
|
|
- isOriginOfScrollSyncPreview = false; // turn off the flag
|
|
|
|
|
|
|
+ const scrollEditorHandler = useCallback(() => {
|
|
|
|
|
+ if (codeMirrorEditor?.view?.scrollDOM == null || previewRef.current == null) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // turn on the flag
|
|
|
|
|
- isOriginOfScrollSyncEditor = true;
|
|
|
|
|
- scrollSyncHelper.scrollPreview(previewRef.current, line);
|
|
|
|
|
- }, []);
|
|
|
|
|
- const scrollPreviewByEditorLineWithThrottle = useMemo(() => throttle(20, scrollPreviewByEditorLine), [scrollPreviewByEditorLine]);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * the scroll event handler from codemirror
|
|
|
|
|
- * @param {any} data {left, top, width, height, clientWidth, clientHeight} object that represents the current scroll position,
|
|
|
|
|
- * the size of the scrollable area, and the size of the visible area (minus scrollbars).
|
|
|
|
|
- * And data.line is also available that is added by Editor component
|
|
|
|
|
- * @see https://codemirror.net/doc/manual.html#events
|
|
|
|
|
- */
|
|
|
|
|
- const editorScrolledHandler = useCallback(({ line }: { line: number }) => {
|
|
|
|
|
- // prevent scrolling
|
|
|
|
|
- // if the elapsed time from last scroll with cursor is shorter than 40ms
|
|
|
|
|
const now = new Date();
|
|
const now = new Date();
|
|
|
- if (lastScrolledDateWithCursor != null && now.getTime() - lastScrolledDateWithCursor.getTime() < 40) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- scrollPreviewByEditorLineWithThrottle(line);
|
|
|
|
|
- }, [scrollPreviewByEditorLineWithThrottle]);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * scroll Preview element by cursor moving
|
|
|
|
|
- * @param {number} line
|
|
|
|
|
- */
|
|
|
|
|
- const scrollPreviewByCursorMoving = useCallback((line: number) => {
|
|
|
|
|
- if (previewRef.current == null) {
|
|
|
|
|
|
|
+ if (lastScrolledDateWithCursor != null && now.getTime() - lastScrolledDateWithCursor.getTime() < 50) {
|
|
|
|
|
+ lastScrolledDateWithCursor = now;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // prevent circular invocation
|
|
|
|
|
if (isOriginOfScrollSyncPreview) {
|
|
if (isOriginOfScrollSyncPreview) {
|
|
|
- isOriginOfScrollSyncPreview = false; // turn off the flag
|
|
|
|
|
|
|
+ isOriginOfScrollSyncPreview = false;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // turn on the flag
|
|
|
|
|
isOriginOfScrollSyncEditor = true;
|
|
isOriginOfScrollSyncEditor = true;
|
|
|
- if (previewRef.current != null) {
|
|
|
|
|
- scrollSyncHelper.scrollPreviewToRevealOverflowing(previewRef.current, line);
|
|
|
|
|
- }
|
|
|
|
|
- }, []);
|
|
|
|
|
- const scrollPreviewByCursorMovingWithThrottle = useMemo(() => throttle(20, scrollPreviewByCursorMoving), [scrollPreviewByCursorMoving]);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * the scroll event handler from codemirror
|
|
|
|
|
- * @param {number} line
|
|
|
|
|
- * @see https://codemirror.net/doc/manual.html#events
|
|
|
|
|
- */
|
|
|
|
|
- // const editorScrollCursorIntoViewHandler = useCallback((line: number) => {
|
|
|
|
|
- // // record date
|
|
|
|
|
- // lastScrolledDateWithCursor = new Date();
|
|
|
|
|
- // scrollPreviewByCursorMovingWithThrottle(line);
|
|
|
|
|
- // }, [scrollPreviewByCursorMovingWithThrottle]);
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * scroll Editor component by scroll event of Preview component
|
|
|
|
|
- * @param {number} offset
|
|
|
|
|
- */
|
|
|
|
|
- // const scrollEditorByPreviewScroll = useCallback((offset: number) => {
|
|
|
|
|
- // if (codeMirrorEditorContainerRef.current == null || previewRef.current == null) {
|
|
|
|
|
- // return;
|
|
|
|
|
- // }
|
|
|
|
|
-
|
|
|
|
|
- // // prevent circular invocation
|
|
|
|
|
- // if (isOriginOfScrollSyncEditor) {
|
|
|
|
|
- // isOriginOfScrollSyncEditor = false; // turn off the flag
|
|
|
|
|
- // return;
|
|
|
|
|
- // }
|
|
|
|
|
-
|
|
|
|
|
- // // turn on the flag
|
|
|
|
|
- // // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
|
- // isOriginOfScrollSyncPreview = true;
|
|
|
|
|
-
|
|
|
|
|
- // scrollSyncHelper.scrollEditor(codeMirrorEditorContainerRef.current, previewRef.current, offset);
|
|
|
|
|
- // }, []);
|
|
|
|
|
- // const scrollEditorByPreviewScrollWithThrottle = useMemo(() => throttle(20, scrollEditorByPreviewScroll), [scrollEditorByPreviewScroll]);
|
|
|
|
|
-
|
|
|
|
|
- const scrollEditorHandler = useCallback(() => {
|
|
|
|
|
- console.log('ScrollEditor!');
|
|
|
|
|
- if (codeMirrorEditor?.view?.scrollDOM != null && previewRef.current != null) {
|
|
|
|
|
- scrollEditor(codeMirrorEditor.view.scrollDOM, previewRef.current);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ scrollEditor(codeMirrorEditor.view.scrollDOM, previewRef.current);
|
|
|
}, [codeMirrorEditor, previewRef]);
|
|
}, [codeMirrorEditor, previewRef]);
|
|
|
|
|
|
|
|
- const scrollEditorHandlerThrottle = useMemo(() => throttle(150, scrollEditorHandler), [scrollEditorHandler]);
|
|
|
|
|
|
|
+ const scrollEditorHandlerThrottle = useMemo(() => throttle(25, scrollEditorHandler), [scrollEditorHandler]);
|
|
|
|
|
|
|
|
const scrollPreviewHandler = useCallback(() => {
|
|
const scrollPreviewHandler = useCallback(() => {
|
|
|
- console.log('ScrollPreview!');
|
|
|
|
|
- if (codeMirrorEditor?.view?.scrollDOM != null && previewRef.current != null) {
|
|
|
|
|
- scrollPreview(codeMirrorEditor.view.scrollDOM, previewRef.current);
|
|
|
|
|
|
|
+ if (codeMirrorEditor?.view?.scrollDOM == null || previewRef.current == null) {
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ if (lastScrolledDateWithCursor != null && now.getTime() - lastScrolledDateWithCursor.getTime() < 50) {
|
|
|
|
|
+ lastScrolledDateWithCursor = now;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isOriginOfScrollSyncEditor) {
|
|
|
|
|
+ isOriginOfScrollSyncEditor = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ isOriginOfScrollSyncPreview = true;
|
|
|
|
|
+ scrollPreview(codeMirrorEditor.view.scrollDOM, previewRef.current);
|
|
|
}, [codeMirrorEditor, previewRef]);
|
|
}, [codeMirrorEditor, previewRef]);
|
|
|
|
|
|
|
|
const scrollPreviewHandlerThrottle = useMemo(() => throttle(150, scrollPreviewHandler), [scrollPreviewHandler]);
|
|
const scrollPreviewHandlerThrottle = useMemo(() => throttle(150, scrollPreviewHandler), [scrollPreviewHandler]);
|
|
@@ -501,21 +431,6 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
codeMirrorEditor?.setCaretLine();
|
|
codeMirrorEditor?.setCaretLine();
|
|
|
}, [codeMirrorEditor]);
|
|
}, [codeMirrorEditor]);
|
|
|
|
|
|
|
|
- // set handler to set caret line
|
|
|
|
|
- useEffect(() => {
|
|
|
|
|
- const handler = (line) => {
|
|
|
|
|
- codeMirrorEditor?.setCaretLine(line);
|
|
|
|
|
-
|
|
|
|
|
- if (previewRef.current != null) {
|
|
|
|
|
- scrollSyncHelper.scrollPreview(previewRef.current, line);
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
- globalEmitter.on('setCaretLine', handler);
|
|
|
|
|
-
|
|
|
|
|
- return function cleanup() {
|
|
|
|
|
- globalEmitter.removeListener('setCaretLine', handler);
|
|
|
|
|
- };
|
|
|
|
|
- }, [codeMirrorEditor]);
|
|
|
|
|
|
|
|
|
|
// set handler to save and return to View
|
|
// set handler to save and return to View
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
@@ -600,16 +515,13 @@ export const PageEditor = React.memo((props: Props): JSX.Element => {
|
|
|
acceptedFileType={acceptedFileType}
|
|
acceptedFileType={acceptedFileType}
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
- <div ref={previewRef} className="page-editor-preview-container flex-expand-vert d-none d-lg-flex">
|
|
|
|
|
|
|
+ <div ref={previewRef} onScroll={scrollPreviewHandlerThrottle} className="page-editor-preview-container flex-expand-vert d-none d-lg-flex">
|
|
|
<Preview
|
|
<Preview
|
|
|
rendererOptions={rendererOptions}
|
|
rendererOptions={rendererOptions}
|
|
|
markdown={markdownToPreview}
|
|
markdown={markdownToPreview}
|
|
|
pagePath={currentPagePath}
|
|
pagePath={currentPagePath}
|
|
|
expandContentWidth={shouldExpandContent}
|
|
expandContentWidth={shouldExpandContent}
|
|
|
pastEnd={previewRef.current?.getBoundingClientRect().height}
|
|
pastEnd={previewRef.current?.getBoundingClientRect().height}
|
|
|
- // TODO: implement
|
|
|
|
|
- // refs: https://redmine.weseek.co.jp/issues/126519
|
|
|
|
|
- // onScroll={(offset) => { console.log('Preview'); console.log(offset) }}
|
|
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
{/*
|
|
{/*
|