feat(window post message communicator): Use EventEmitter2

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-09-26 16:23:45 +02:00
parent 3b9cfdf487
commit 883f868399
5 changed files with 38 additions and 28 deletions

View file

@ -70,6 +70,7 @@
"dompurify": "2.4.0", "dompurify": "2.4.0",
"emoji-picker-element": "1.12.1", "emoji-picker-element": "1.12.1",
"emoji-picker-element-data": "1.3.0", "emoji-picker-element-data": "1.3.0",
"eventemitter2": "6.4.9",
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"firacode": "6.2.0", "firacode": "6.2.0",
"flowchart.js": "1.17.1", "flowchart.js": "1.17.1",

View file

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
@ -7,7 +7,7 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import type { CommunicationMessages, RendererToEditorMessageType } from '../rendering-message' import type { CommunicationMessages, RendererToEditorMessageType } from '../rendering-message'
import { useEditorToRendererCommunicator } from '../../../editor-page/render-context/editor-to-renderer-communicator-context-provider' import { useEditorToRendererCommunicator } from '../../../editor-page/render-context/editor-to-renderer-communicator-context-provider'
import type { MaybeHandler } from '../window-post-message-communicator' import type { Handler } from '../window-post-message-communicator'
/** /**
* Sets the handler for the given message type in the current editor to renderer communicator. * Sets the handler for the given message type in the current editor to renderer communicator.
@ -17,13 +17,14 @@ import type { MaybeHandler } from '../window-post-message-communicator'
*/ */
export const useEditorReceiveHandler = <R extends RendererToEditorMessageType>( export const useEditorReceiveHandler = <R extends RendererToEditorMessageType>(
messageType: R, messageType: R,
handler: MaybeHandler<CommunicationMessages, R> handler?: Handler<CommunicationMessages, R>
): void => { ): void => {
const editorToRendererCommunicator = useEditorToRendererCommunicator() const editorToRendererCommunicator = useEditorToRendererCommunicator()
useEffect(() => { useEffect(() => {
editorToRendererCommunicator.setHandler(messageType, handler) if (!handler) {
return () => { return
editorToRendererCommunicator.setHandler(messageType, undefined)
} }
editorToRendererCommunicator.on(messageType, handler)
return () => editorToRendererCommunicator.off(messageType, handler)
}, [editorToRendererCommunicator, handler, messageType]) }, [editorToRendererCommunicator, handler, messageType])
} }

View file

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
@ -26,9 +26,7 @@ export const useRendererReceiveHandler = <MESSAGE_TYPE extends EditorToRendererM
): void => { ): void => {
const editorToRendererCommunicator = useRendererToEditorCommunicator() const editorToRendererCommunicator = useRendererToEditorCommunicator()
useEffect(() => { useEffect(() => {
editorToRendererCommunicator.setHandler(messageType, handler) editorToRendererCommunicator.on(messageType, handler)
return () => { return () => editorToRendererCommunicator.off(messageType, handler)
editorToRendererCommunicator.setHandler(messageType, undefined)
}
}, [editorToRendererCommunicator, handler, messageType]) }, [editorToRendererCommunicator, handler, messageType])
} }

View file

@ -6,6 +6,7 @@
import type { Logger } from '../../../utils/logger' import type { Logger } from '../../../utils/logger'
import { Optional } from '@mrdrogdrog/optional' import { Optional } from '@mrdrogdrog/optional'
import EventEmitter2 from 'eventemitter2'
/** /**
* Error that will be thrown if a message couldn't be sent. * Error that will be thrown if a message couldn't be sent.
@ -16,12 +17,6 @@ export type Handler<MESSAGES, MESSAGE_TYPE extends string> = (
values: Extract<MESSAGES, MessagePayload<MESSAGE_TYPE>> values: Extract<MESSAGES, MessagePayload<MESSAGE_TYPE>>
) => void ) => void
export type MaybeHandler<MESSAGES, MESSAGE_TYPE extends string> = Handler<MESSAGES, MESSAGE_TYPE> | undefined
export type HandlerMap<MESSAGES, MESSAGE_TYPE extends string> = Partial<{
[key in MESSAGE_TYPE]: MaybeHandler<MESSAGES, MESSAGE_TYPE>
}>
export interface MessagePayload<MESSAGE_TYPE extends string> { export interface MessagePayload<MESSAGE_TYPE extends string> {
type: MESSAGE_TYPE type: MESSAGE_TYPE
} }
@ -37,7 +32,7 @@ export abstract class WindowPostMessageCommunicator<
private messageTarget?: Window private messageTarget?: Window
private targetOrigin?: string private targetOrigin?: string
private communicationEnabled: boolean private communicationEnabled: boolean
private readonly handlers: HandlerMap<MESSAGES, RECEIVE_TYPE> = {} private readonly emitter: EventEmitter2 = new EventEmitter2()
private readonly log: Logger private readonly log: Logger
private readonly boundListener: (event: MessageEvent) => void private readonly boundListener: (event: MessageEvent) => void
@ -113,15 +108,25 @@ export abstract class WindowPostMessageCommunicator<
} }
/** /**
* Sets the handler method that processes messages with the given message type. * Registers a handler for the given message type.
* If there is already a handler for the given message type then the handler will be overwritten.
* *
* @param messageType The message type for which the handler should be called * @param messageType The message type for which the handler should be called
* @param handler The handler that processes messages with the given message type. * @param handler The handler that processes messages with the given message type.
*/ */
public setHandler<R extends RECEIVE_TYPE>(messageType: R, handler: MaybeHandler<MESSAGES, R>): void { public on<R extends RECEIVE_TYPE>(messageType: R, handler: Handler<MESSAGES, R>): void {
this.log.debug(handler === undefined ? 'Unset' : 'Set', 'handler for', messageType) this.log.debug('Set handler for', messageType)
this.handlers[messageType] = handler as MaybeHandler<MESSAGES, RECEIVE_TYPE> this.emitter.on(messageType, handler)
}
/**
* Deletes a handler for the given message type.
*
* @param messageType The message type for which the handler should be removed
* @param handler The handler that should be removed.
*/
public off<R extends RECEIVE_TYPE>(messageType: R, handler: Handler<MESSAGES, R>): void {
this.log.debug('Unset handler for', messageType)
this.emitter.off(messageType, handler)
} }
/** /**
@ -142,10 +147,7 @@ export abstract class WindowPostMessageCommunicator<
* Processes a {@link MessagePayload message payload} using the correct {@link Handler handler}. * Processes a {@link MessagePayload message payload} using the correct {@link Handler handler}.
* @param payload The payload that should be processed * @param payload The payload that should be processed
*/ */
private processPayload(payload: MessagePayload<RECEIVE_TYPE>): void { private processPayload(payload: MessagePayload<string>): void {
return Optional.ofNullable<Handler<MESSAGES, RECEIVE_TYPE>>(this.handlers[payload.type]).ifPresent((handler) => { this.emitter.emit(payload.type, payload)
this.log.debug('Received event', payload)
handler(payload as Extract<MESSAGES, MessagePayload<RECEIVE_TYPE>>)
})
} }
} }

View file

@ -1987,6 +1987,7 @@ __metadata:
eslint-plugin-prettier: 4.2.1 eslint-plugin-prettier: 4.2.1
eslint-plugin-promise: 6.0.1 eslint-plugin-promise: 6.0.1
eslint-plugin-testing-library: 5.7.0 eslint-plugin-testing-library: 5.7.0
eventemitter2: 6.4.9
fast-deep-equal: 3.1.3 fast-deep-equal: 3.1.3
firacode: 6.2.0 firacode: 6.2.0
flowchart.js: 1.17.1 flowchart.js: 1.17.1
@ -7009,6 +7010,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eventemitter2@npm:6.4.9":
version: 6.4.9
resolution: "eventemitter2@npm:6.4.9"
checksum: be59577c1e1c35509c7ba0e2624335c35bbcfd9485b8a977384c6cc6759341ea1a98d3cb9dbaa5cea4fff9b687e504504e3f9c2cc1674cf3bd8a43a7c74ea3eb
languageName: node
linkType: hard
"execa@npm:4.1.0": "execa@npm:4.1.0":
version: 4.1.0 version: 4.1.0
resolution: "execa@npm:4.1.0" resolution: "execa@npm:4.1.0"