Iframe communicator context (2/3) (#1310)

* Add type

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>

* Extract code and add new context provider

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>

* Adjust import

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2021-06-12 16:14:46 +02:00 committed by GitHub
parent 829cc2fe48
commit 6285af458a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 189 additions and 154 deletions

View file

@ -8,14 +8,16 @@ import React, { useCallback } from 'react'
import { ImageClickHandler } from '../../markdown-renderer/replace-components/image/image-replacer'
import { IframeRendererToEditorCommunicator } from '../iframe-renderer-to-editor-communicator'
export const useImageClickHandler = (iframeCommunicator: IframeRendererToEditorCommunicator): ImageClickHandler => {
export const useImageClickHandler = (
iframeCommunicator: IframeRendererToEditorCommunicator | undefined
): ImageClickHandler => {
return useCallback(
(event: React.MouseEvent<HTMLImageElement, MouseEvent>) => {
const image = event.target as HTMLImageElement
if (image.src === '') {
return
}
iframeCommunicator.sendClickedImageUrl({
iframeCommunicator?.sendClickedImageUrl({
src: image.src,
alt: image.alt,
title: image.title

View file

@ -0,0 +1,106 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useCallback, useEffect, useState } from 'react'
import { ScrollState } from '../editor-page/synced-scroll/scroll-props'
import { BaseConfiguration, RendererType } from './rendering-message'
import { setDarkMode } from '../../redux/dark-mode/methods'
import { NoteFrontmatter } from '../editor-page/note-frontmatter/note-frontmatter'
import { setNoteFrontmatter } from '../../redux/note-details/methods'
import { ImageClickHandler } from '../markdown-renderer/replace-components/image/image-replacer'
import { useImageClickHandler } from './hooks/use-image-click-handler'
import { MarkdownDocument } from './markdown-document'
import { useIFrameRendererToEditorCommunicator } from '../editor-page/render-context/iframe-renderer-to-editor-communicator-context-provider'
export const IframeMarkdownRenderer: React.FC = () => {
const [markdownContent, setMarkdownContent] = useState('')
const [scrollState, setScrollState] = useState<ScrollState>({ firstLineInView: 1, scrolledPercentage: 0 })
const [baseConfiguration, setBaseConfiguration] = useState<BaseConfiguration | undefined>(undefined)
const iframeCommunicator = useIFrameRendererToEditorCommunicator()
useEffect(() => iframeCommunicator?.onSetBaseConfiguration(setBaseConfiguration), [iframeCommunicator])
useEffect(() => iframeCommunicator?.onSetMarkdownContent(setMarkdownContent), [iframeCommunicator])
useEffect(() => iframeCommunicator?.onSetDarkMode(setDarkMode), [iframeCommunicator])
useEffect(() => iframeCommunicator?.onSetScrollState(setScrollState), [iframeCommunicator, scrollState])
const onTaskCheckedChange = useCallback(
(lineInMarkdown: number, checked: boolean) => {
iframeCommunicator?.sendTaskCheckBoxChange(lineInMarkdown, checked)
},
[iframeCommunicator]
)
const onFirstHeadingChange = useCallback(
(firstHeading?: string) => {
iframeCommunicator?.sendFirstHeadingChanged(firstHeading)
},
[iframeCommunicator]
)
const onMakeScrollSource = useCallback(() => {
iframeCommunicator?.sendSetScrollSourceToRenderer()
}, [iframeCommunicator])
const onFrontmatterChange = useCallback(
(frontmatter?: NoteFrontmatter) => {
setNoteFrontmatter(frontmatter)
iframeCommunicator?.sendSetFrontmatter(frontmatter)
},
[iframeCommunicator]
)
const onScroll = useCallback(
(scrollState: ScrollState) => {
iframeCommunicator?.sendSetScrollState(scrollState)
},
[iframeCommunicator]
)
const onImageClick: ImageClickHandler = useImageClickHandler(iframeCommunicator)
const onHeightChange = useCallback(
(height: number) => {
iframeCommunicator?.sendHeightChange(height)
},
[iframeCommunicator]
)
if (!baseConfiguration) {
return null
}
switch (baseConfiguration.rendererType) {
case RendererType.DOCUMENT:
return (
<MarkdownDocument
additionalOuterContainerClasses={'vh-100 bg-light'}
markdownContent={markdownContent}
onTaskCheckedChange={onTaskCheckedChange}
onFirstHeadingChange={onFirstHeadingChange}
onMakeScrollSource={onMakeScrollSource}
onFrontmatterChange={onFrontmatterChange}
scrollState={scrollState}
onScroll={onScroll}
baseUrl={baseConfiguration.baseUrl}
onImageClick={onImageClick}
/>
)
case RendererType.INTRO:
return (
<MarkdownDocument
additionalOuterContainerClasses={'vh-100 bg-light overflow-y-hidden'}
markdownContent={markdownContent}
baseUrl={baseConfiguration.baseUrl}
onImageClick={onImageClick}
disableToc={true}
onHeightChange={onHeightChange}
/>
)
default:
return null
}
}

View file

@ -3,120 +3,19 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useApplicationState } from '../../hooks/common/use-application-state'
import React from 'react'
import { useApplyDarkMode } from '../../hooks/common/use-apply-dark-mode'
import { setDarkMode } from '../../redux/dark-mode/methods'
import { setNoteFrontmatter } from '../../redux/note-details/methods'
import { NoteFrontmatter } from '../editor-page/note-frontmatter/note-frontmatter'
import { ScrollState } from '../editor-page/synced-scroll/scroll-props'
import { ImageClickHandler } from '../markdown-renderer/replace-components/image/image-replacer'
import { useImageClickHandler } from './hooks/use-image-click-handler'
import { IframeRendererToEditorCommunicator } from './iframe-renderer-to-editor-communicator'
import { MarkdownDocument } from './markdown-document'
import { BaseConfiguration, RendererType } from './rendering-message'
import { IframeMarkdownRenderer } from './iframe-markdown-renderer'
import { IframeRendererToEditorCommunicatorContextProvider } from '../editor-page/render-context/iframe-renderer-to-editor-communicator-context-provider'
export const RenderPage: React.FC = () => {
useApplyDarkMode()
const [markdownContent, setMarkdownContent] = useState('')
const [scrollState, setScrollState] = useState<ScrollState>({ firstLineInView: 1, scrolledPercentage: 0 })
const [baseConfiguration, setBaseConfiguration] = useState<BaseConfiguration | undefined>(undefined)
const editorOrigin = useApplicationState((state) => state.config.iframeCommunication.editorOrigin)
const iframeCommunicator = useMemo(() => {
const newCommunicator = new IframeRendererToEditorCommunicator()
newCommunicator.setOtherSide(window.parent, editorOrigin)
return newCommunicator
}, [editorOrigin])
useEffect(() => {
iframeCommunicator.sendRendererReady()
return () => iframeCommunicator.unregisterEventListener()
}, [iframeCommunicator])
useEffect(() => iframeCommunicator.onSetBaseConfiguration(setBaseConfiguration), [iframeCommunicator])
useEffect(() => iframeCommunicator.onSetMarkdownContent(setMarkdownContent), [iframeCommunicator])
useEffect(() => iframeCommunicator.onSetDarkMode(setDarkMode), [iframeCommunicator])
useEffect(() => iframeCommunicator.onSetScrollState(setScrollState), [iframeCommunicator, scrollState])
const onTaskCheckedChange = useCallback(
(lineInMarkdown: number, checked: boolean) => {
iframeCommunicator.sendTaskCheckBoxChange(lineInMarkdown, checked)
},
[iframeCommunicator]
return (
<IframeRendererToEditorCommunicatorContextProvider>
<IframeMarkdownRenderer />
</IframeRendererToEditorCommunicatorContextProvider>
)
const onFirstHeadingChange = useCallback(
(firstHeading?: string) => {
iframeCommunicator.sendFirstHeadingChanged(firstHeading)
},
[iframeCommunicator]
)
const onMakeScrollSource = useCallback(() => {
iframeCommunicator.sendSetScrollSourceToRenderer()
}, [iframeCommunicator])
const onFrontmatterChange = useCallback(
(frontmatter?: NoteFrontmatter) => {
setNoteFrontmatter(frontmatter)
iframeCommunicator.sendSetFrontmatter(frontmatter)
},
[iframeCommunicator]
)
const onScroll = useCallback(
(scrollState: ScrollState) => {
iframeCommunicator.sendSetScrollState(scrollState)
},
[iframeCommunicator]
)
const onImageClick: ImageClickHandler = useImageClickHandler(iframeCommunicator)
const onHeightChange = useCallback(
(height: number) => {
iframeCommunicator.sendHeightChange(height)
},
[iframeCommunicator]
)
if (!baseConfiguration) {
return null
}
switch (baseConfiguration.rendererType) {
case RendererType.DOCUMENT:
return (
<MarkdownDocument
additionalOuterContainerClasses={'vh-100 bg-light'}
markdownContent={markdownContent}
onTaskCheckedChange={onTaskCheckedChange}
onFirstHeadingChange={onFirstHeadingChange}
onMakeScrollSource={onMakeScrollSource}
onFrontmatterChange={onFrontmatterChange}
scrollState={scrollState}
onScroll={onScroll}
baseUrl={baseConfiguration.baseUrl}
onImageClick={onImageClick}
/>
)
case RendererType.INTRO:
return (
<MarkdownDocument
additionalOuterContainerClasses={'vh-100 bg-light overflow-y-hidden'}
markdownContent={markdownContent}
baseUrl={baseConfiguration.baseUrl}
onImageClick={onImageClick}
disableToc={true}
onHeightChange={onHeightChange}
/>
)
default:
return null
}
}
export default RenderPage