mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-21 18:55:19 -04:00

Some tests fail because the iframe hasn't loaded the inner hedgedoc renderer yet but cypress tries to travel through the dom and verify the render results. Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
147 lines
5.1 KiB
TypeScript
147 lines
5.1 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
import equal from 'fast-deep-equal'
|
|
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'
|
|
import { useApplicationState } from '../../../hooks/common/use-application-state'
|
|
import { useIsDarkModeActivated } from '../../../hooks/common/use-is-dark-mode-activated'
|
|
import { setRendererReady } from '../../../redux/editor/methods'
|
|
import { isTestMode } from '../../../utils/test-modes'
|
|
import { RendererProps } from '../../render-page/markdown-document'
|
|
import { ImageDetails, RendererType } from '../../render-page/rendering-message'
|
|
import { useIFrameEditorToRendererCommunicator } from '../render-context/iframe-editor-to-renderer-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'
|
|
|
|
export interface RenderIframeProps extends RendererProps {
|
|
rendererType: RendererType
|
|
forcedDarkMode?: boolean
|
|
frameClasses?: string
|
|
}
|
|
|
|
export const RenderIframe: React.FC<RenderIframeProps> = ({
|
|
markdownContent,
|
|
onTaskCheckedChange,
|
|
onFrontmatterChange,
|
|
scrollState,
|
|
onFirstHeadingChange,
|
|
onScroll,
|
|
onMakeScrollSource,
|
|
frameClasses,
|
|
rendererType,
|
|
forcedDarkMode
|
|
}) => {
|
|
const savedDarkMode = useIsDarkModeActivated()
|
|
const darkMode = forcedDarkMode ?? savedDarkMode
|
|
const [lightboxDetails, setLightboxDetails] = useState<ImageDetails | undefined>(undefined)
|
|
|
|
const frameReference = useRef<HTMLIFrameElement>(null)
|
|
const rendererOrigin = useApplicationState((state) => state.config.iframeCommunication.rendererOrigin)
|
|
const renderPageUrl = `${rendererOrigin}render`
|
|
const resetRendererReady = useCallback(() => setRendererReady(false), [])
|
|
const iframeCommunicator = useIFrameEditorToRendererCommunicator()
|
|
const onIframeLoad = useOnIframeLoad(
|
|
frameReference,
|
|
iframeCommunicator,
|
|
rendererOrigin,
|
|
renderPageUrl,
|
|
resetRendererReady
|
|
)
|
|
const [frameHeight, setFrameHeight] = useState<number>(0)
|
|
|
|
const rendererReady = useApplicationState((state) => state.editorConfig.rendererReady)
|
|
|
|
useEffect(
|
|
() => () => {
|
|
iframeCommunicator.unregisterEventListener()
|
|
setRendererReady(false)
|
|
},
|
|
[iframeCommunicator]
|
|
)
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onFirstHeadingChange(onFirstHeadingChange)
|
|
return () => iframeCommunicator.onFirstHeadingChange(undefined)
|
|
}, [iframeCommunicator, onFirstHeadingChange])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onFrontmatterChange(onFrontmatterChange)
|
|
return () => iframeCommunicator.onFrontmatterChange(undefined)
|
|
}, [iframeCommunicator, onFrontmatterChange])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onSetScrollState(onScroll)
|
|
return () => iframeCommunicator.onSetScrollState(undefined)
|
|
}, [iframeCommunicator, onScroll])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onSetScrollSourceToRenderer(onMakeScrollSource)
|
|
return () => iframeCommunicator.onSetScrollSourceToRenderer(undefined)
|
|
}, [iframeCommunicator, onMakeScrollSource])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onTaskCheckboxChange(onTaskCheckedChange)
|
|
return () => iframeCommunicator.onTaskCheckboxChange(undefined)
|
|
}, [iframeCommunicator, onTaskCheckedChange])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onImageClicked(setLightboxDetails)
|
|
return () => iframeCommunicator.onImageClicked(undefined)
|
|
}, [iframeCommunicator])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onHeightChange(setFrameHeight)
|
|
return () => iframeCommunicator.onHeightChange(undefined)
|
|
}, [iframeCommunicator])
|
|
|
|
useEffect(() => {
|
|
iframeCommunicator.onRendererReady(() => {
|
|
iframeCommunicator.sendSetBaseConfiguration({
|
|
baseUrl: window.location.toString(),
|
|
rendererType
|
|
})
|
|
setRendererReady(true)
|
|
})
|
|
return () => iframeCommunicator.onRendererReady(undefined)
|
|
}, [iframeCommunicator, rendererType])
|
|
|
|
useEffect(() => {
|
|
if (rendererReady) {
|
|
iframeCommunicator.sendSetDarkmode(darkMode)
|
|
}
|
|
}, [darkMode, iframeCommunicator, rendererReady])
|
|
|
|
const oldScrollState = useRef<ScrollState | undefined>(undefined)
|
|
useEffect(() => {
|
|
if (rendererReady && !equal(scrollState, oldScrollState.current)) {
|
|
oldScrollState.current = scrollState
|
|
iframeCommunicator.sendScrollState(scrollState)
|
|
}
|
|
}, [iframeCommunicator, rendererReady, scrollState])
|
|
|
|
useEffect(() => {
|
|
if (rendererReady) {
|
|
iframeCommunicator.sendSetMarkdownContent(markdownContent)
|
|
}
|
|
}, [iframeCommunicator, markdownContent, rendererReady])
|
|
|
|
return (
|
|
<Fragment>
|
|
<ShowOnPropChangeImageLightbox details={lightboxDetails} />
|
|
<iframe
|
|
style={{ height: `${frameHeight}px` }}
|
|
data-cy={'documentIframe'}
|
|
onLoad={onIframeLoad}
|
|
title='render'
|
|
src={renderPageUrl}
|
|
{...(isTestMode() ? {} : { sandbox: 'allow-downloads allow-same-origin allow-scripts allow-popups' })}
|
|
ref={frameReference}
|
|
className={`border-0 ${frameClasses ?? ''}`}
|
|
data-content-ready={rendererReady}
|
|
/>
|
|
</Fragment>
|
|
)
|
|
}
|