/* * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import type { PropsWithChildren } from 'react' import React, { createContext, useContext, useEffect, useMemo } from 'react' import { RendererToEditorCommunicator } from '../../render-page/window-post-message-communicator/renderer-to-editor-communicator' import { CommunicationMessageType } from '../../render-page/window-post-message-communicator/rendering-message' import { ORIGIN, useBaseUrl } from '../../../hooks/common/use-base-url' const RendererToEditorCommunicatorContext = createContext(undefined) /** * Provides the {@link RendererToEditorCommunicator renderer to editor iframe communicator} that is set by a {@link RendererToEditorCommunicatorContextProvider context provider}. * * @return the received communicator * @throws {Error} if no communicator was received */ export const useRendererToEditorCommunicator: () => RendererToEditorCommunicator = () => { const communicatorFromContext = useContext(RendererToEditorCommunicatorContext) if (!communicatorFromContext) { throw new Error('No renderer-to-editor-iframe-communicator received. Did you forget to use the provider component?') } return communicatorFromContext } export const RendererToEditorCommunicatorContextProvider: React.FC> = ({ children }) => { const editorOrigin = useBaseUrl(ORIGIN.EDITOR) const communicator = useMemo(() => new RendererToEditorCommunicator(), []) useEffect(() => { const currentCommunicator = communicator currentCommunicator.setMessageTarget(window.parent, new URL(editorOrigin).origin) currentCommunicator.registerEventListener() currentCommunicator.enableCommunication() currentCommunicator.sendMessageToOtherSide({ type: CommunicationMessageType.RENDERER_READY }) return () => currentCommunicator?.unregisterEventListener() }, [communicator, editorOrigin]) /** * Provides a {@link RendererToEditorCommunicator renderer to editor communicator} for the child components via Context. */ return ( {children} ) }