mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-23 19:47:03 -04:00
Add renderer ready state to global application state
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
2dad1d565e
commit
cfb2de8909
12 changed files with 144 additions and 52 deletions
|
@ -4,38 +4,74 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/**
|
||||
* Error that will be thrown if a message couldn't be sent.
|
||||
*/
|
||||
export class IframeCommunicatorSendingError extends Error {}
|
||||
|
||||
/**
|
||||
* Base class for communication between renderer and editor.
|
||||
*/
|
||||
export abstract class IframeCommunicator<SEND, RECEIVE> {
|
||||
protected otherSide?: Window
|
||||
protected otherOrigin?: string
|
||||
private messageTarget?: Window
|
||||
private targetOrigin?: string
|
||||
private communicationEnabled: boolean
|
||||
|
||||
constructor() {
|
||||
window.addEventListener('message', this.handleEvent.bind(this))
|
||||
this.communicationEnabled = false
|
||||
}
|
||||
|
||||
public unregisterEventListener(): void {
|
||||
window.removeEventListener('message', this.handleEvent.bind(this))
|
||||
}
|
||||
|
||||
public setOtherSide(otherSide: Window, otherOrigin: string): void {
|
||||
this.otherSide = otherSide
|
||||
this.otherOrigin = otherOrigin
|
||||
/**
|
||||
* Sets the target for message sending.
|
||||
* Messages can be sent as soon as the communication is enabled.
|
||||
*
|
||||
* @see enableCommunication
|
||||
* @param otherSide The target {@link Window} that should receive the messages.
|
||||
* @param otherOrigin The origin from the URL of the target. If this isn't correct then the message sending will produce CORS errors.
|
||||
*/
|
||||
public setMessageTarget(otherSide: Window, otherOrigin: string): void {
|
||||
this.messageTarget = otherSide
|
||||
this.targetOrigin = otherOrigin
|
||||
this.communicationEnabled = false
|
||||
}
|
||||
|
||||
public unsetOtherSide(): void {
|
||||
this.otherSide = undefined
|
||||
this.otherOrigin = undefined
|
||||
/**
|
||||
* Unsets the message target. Should be used if the old target isn't available anymore.
|
||||
*/
|
||||
public unsetMessageTarget(): void {
|
||||
this.messageTarget = undefined
|
||||
this.targetOrigin = undefined
|
||||
this.communicationEnabled = false
|
||||
}
|
||||
|
||||
public getOtherSide(): Window | undefined {
|
||||
return this.otherSide
|
||||
/**
|
||||
* Enables the message communication.
|
||||
* Should be called as soon as the other sides is ready to receive messages.
|
||||
*/
|
||||
protected enableCommunication(): void {
|
||||
this.communicationEnabled = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the message target.
|
||||
*
|
||||
* @param message The message to send.
|
||||
*/
|
||||
protected sendMessageToOtherSide(message: SEND): void {
|
||||
if (this.otherSide === undefined || this.otherOrigin === undefined) {
|
||||
console.error("Can't send message because otherSide is null", message)
|
||||
return
|
||||
if (this.messageTarget === undefined || this.targetOrigin === undefined) {
|
||||
throw new IframeCommunicatorSendingError(`Other side is not set.\nMessage was: ${JSON.stringify(message)}`)
|
||||
}
|
||||
this.otherSide.postMessage(message, this.otherOrigin)
|
||||
if (!this.communicationEnabled) {
|
||||
throw new IframeCommunicatorSendingError(
|
||||
`Communication isn't enabled. Maybe the other side is not ready?\nMessage was: ${JSON.stringify(message)}`
|
||||
)
|
||||
}
|
||||
this.messageTarget.postMessage(message, this.targetOrigin)
|
||||
}
|
||||
|
||||
protected abstract handleEvent(event: MessageEvent<RECEIVE>): void
|
||||
|
|
|
@ -106,6 +106,7 @@ export class IframeEditorToRendererCommunicator extends IframeCommunicator<
|
|||
const renderMessage = event.data
|
||||
switch (renderMessage.type) {
|
||||
case RenderIframeMessageType.RENDERER_READY:
|
||||
this.enableCommunication()
|
||||
this.onRendererReadyHandler?.()
|
||||
return false
|
||||
case RenderIframeMessageType.SET_SCROLL_SOURCE_TO_RENDERER:
|
||||
|
|
|
@ -38,7 +38,7 @@ export const IframeMarkdownRenderer: React.FC = () => {
|
|||
useEffect(() => iframeCommunicator.onSetDarkMode(setDarkMode), [iframeCommunicator])
|
||||
useEffect(() => iframeCommunicator.onSetScrollState(setScrollState), [iframeCommunicator, scrollState])
|
||||
useEffect(
|
||||
() => iframeCommunicator?.onGetWordCount(countWordsInRenderedDocument),
|
||||
() => iframeCommunicator.onGetWordCount(countWordsInRenderedDocument),
|
||||
[iframeCommunicator, countWordsInRenderedDocument]
|
||||
)
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ export class IframeRendererToEditorCommunicator extends IframeCommunicator<
|
|||
}
|
||||
|
||||
public sendRendererReady(): void {
|
||||
this.enableCommunication()
|
||||
this.sendMessageToOtherSide({
|
||||
type: RenderIframeMessageType.RENDERER_READY
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue