Add context for iframe communicator in editor page (#1146)

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2021-04-03 12:59:14 +02:00 committed by GitHub
parent 6e43ec99a3
commit af887877aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 27 deletions

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { Fragment, useCallback, useRef, useState } from 'react'
import React, { useCallback, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { useApplyDarkMode } from '../../hooks/common/use-apply-dark-mode'
@ -34,6 +34,7 @@ import { RendererType } from '../render-page/rendering-message'
import { useEditorModeFromUrl } from './hooks/useEditorModeFromUrl'
import { UiNotifications } from '../notifications/ui-notifications'
import { useNotificationTest } from './use-notification-test'
import { IframeCommunicatorContextProvider } from './render-context/iframe-communicator-context-provider'
export interface EditorPagePathParams {
id: string
@ -86,13 +87,35 @@ export const EditorPage: React.FC = () => {
useNotificationTest()
const leftPane = useMemo(() =>
<EditorPane
onContentChange={ setNoteMarkdownContent }
content={ markdownContent }
scrollState={ scrollState.editorScrollState }
onScroll={ onEditorScroll }
onMakeScrollSource={ setEditorToScrollSource }/>
, [markdownContent, onEditorScroll, scrollState.editorScrollState, setEditorToScrollSource])
const rightPane = useMemo(() =>
<RenderIframe
frameClasses={ 'h-100 w-100' }
markdownContent={ markdownContent }
onMakeScrollSource={ setRendererToScrollSource }
onFirstHeadingChange={ updateNoteTitleByFirstHeading }
onTaskCheckedChange={ SetCheckboxInMarkdownContent }
onFrontmatterChange={ setNoteFrontmatter }
onScroll={ onMarkdownRendererScroll }
scrollState={ scrollState.rendererScrollState }
rendererType={ RendererType.DOCUMENT }/>
, [markdownContent, onMarkdownRendererScroll, scrollState.rendererScrollState,
setRendererToScrollSource])
return (
<Fragment>
<IframeCommunicatorContextProvider>
<UiNotifications/>
<MotdBanner/>
<div className={ 'd-flex flex-column vh-100' }>
<AppBar mode={ AppBarMode.EDITOR }/>
<div className={ 'container' }>
<ErrorWhileLoadingNoteAlert show={ error }/>
<LoadingNoteAlert show={ loading }/>
@ -101,33 +124,16 @@ export const EditorPage: React.FC = () => {
<div className={ 'flex-fill d-flex h-100 w-100 overflow-hidden flex-row' }>
<Splitter
showLeft={ editorMode === EditorMode.EDITOR || editorMode === EditorMode.BOTH }
left={
<EditorPane
onContentChange={ setNoteMarkdownContent }
content={ markdownContent }
scrollState={ scrollState.editorScrollState }
onScroll={ onEditorScroll }
onMakeScrollSource={ setEditorToScrollSource }/>
}
left={ leftPane }
showRight={ editorMode === EditorMode.PREVIEW || editorMode === EditorMode.BOTH }
right={
<RenderIframe
frameClasses={ 'h-100 w-100' }
markdownContent={ markdownContent }
onMakeScrollSource={ setRendererToScrollSource }
onFirstHeadingChange={ updateNoteTitleByFirstHeading }
onTaskCheckedChange={ SetCheckboxInMarkdownContent }
onFrontmatterChange={ setNoteFrontmatter }
onScroll={ onMarkdownRendererScroll }
scrollState={ scrollState.rendererScrollState }
rendererType={ RendererType.DOCUMENT }/>
}
right={ rightPane }
containerClassName={ 'overflow-hidden' }/>
<Sidebar/>
</div>
</ShowIf>
</div>
</Fragment>
</IframeCommunicatorContextProvider>
)
}
export default EditorPage

View file

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useContext, useMemo } from 'react'
import { IframeEditorToRendererCommunicator } from '../../render-page/iframe-editor-to-renderer-communicator'
const IFrameEditorToRendererCommunicatorContext = React.createContext<IframeEditorToRendererCommunicator | undefined>(undefined)
export const useIFrameCommunicator: () => IframeEditorToRendererCommunicator | undefined = () => useContext(IFrameEditorToRendererCommunicatorContext)
export const useContextOrStandaloneIframeCommunicator: () => IframeEditorToRendererCommunicator = () => {
const contextCommunicator = useIFrameCommunicator()
return useMemo(() => contextCommunicator ? contextCommunicator : new IframeEditorToRendererCommunicator(), [contextCommunicator])
}
export const IframeCommunicatorContextProvider: React.FC = ({ children }) => {
const currentIFrameCommunicator = useMemo<IframeEditorToRendererCommunicator>(() => new IframeEditorToRendererCommunicator(), [])
return <IFrameEditorToRendererCommunicatorContext.Provider value={ currentIFrameCommunicator }>
{ children }
</IFrameEditorToRendererCommunicatorContext.Provider>
}

View file

@ -4,14 +4,14 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import equal from 'fast-deep-equal'
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
import { useSelector } from 'react-redux'
import { useIsDarkModeActivated } from '../../../hooks/common/use-is-dark-mode-activated'
import { ApplicationState } from '../../../redux'
import { isTestMode } from '../../../utils/is-test-mode'
import { IframeEditorToRendererCommunicator } from '../../render-page/iframe-editor-to-renderer-communicator'
import { RendererProps } from '../../render-page/markdown-document'
import { ImageDetails, RendererType } from '../../render-page/rendering-message'
import { useContextOrStandaloneIframeCommunicator } from '../render-context/iframe-communicator-context-provider'
import { ScrollState } from '../synced-scroll/scroll-props'
import { useOnIframeLoad } from './hooks/use-on-iframe-load'
import { ShowOnPropChangeImageLightbox } from './show-on-prop-change-image-lightbox'
@ -46,7 +46,7 @@ export const RenderIframe: React.FC<RenderIframeProps> = (
const rendererOrigin = useSelector((state: ApplicationState) => state.config.iframeCommunication.rendererOrigin)
const renderPageUrl = `${ rendererOrigin }/render`
const resetRendererReady = useCallback(() => setRendererReady(false), [])
const iframeCommunicator = useMemo(() => new IframeEditorToRendererCommunicator(), [])
const iframeCommunicator = useContextOrStandaloneIframeCommunicator()
const onIframeLoad = useOnIframeLoad(frameReference, iframeCommunicator, rendererOrigin, renderPageUrl, resetRendererReady)
const [frameHeight, setFrameHeight] = useState<number>(0)