2 EditorToClientGenericMessage,
3 EditorToClientInvokationMessage,
4 EditorToClientReplyMessage,
5 ClientToEditorReplyMessage,
6 EditorRequiresClientMethods,
7 InternalEventBusInterface,
9 } from '@proton/docs-shared'
10 import { EditorBridgeMessageType, BridgeOriginProvider, DOCS_EDITOR_DEBUG_KEY } from '@proton/docs-shared'
11 import { EditorInvoker } from './EditorInvoker'
12 import { EditorToClientRequestHandler } from './EditorToClientRequestHandler'
13 import { Logger } from '@proton/utils/logs'
14 import type { EditorOrchestratorInterface } from '../Services/Orchestrator/EditorOrchestratorInterface'
16 export class ClientToEditorBridge {
17 public readonly logger = new Logger('DocsClient', DOCS_EDITOR_DEBUG_KEY)
18 public readonly editorInvoker = new EditorInvoker(this.editorFrame, this.logger)
19 private editorRequestHandler: EditorToClientRequestHandler
22 private editorFrame: HTMLIFrameElement,
23 private readonly editorController: EditorOrchestratorInterface,
24 private readonly eventBus: InternalEventBusInterface,
25 private readonly syncedEditorState?: SyncedEditorState,
27 this.editorRequestHandler = new EditorToClientRequestHandler(this.editorFrame, this.editorController, this.eventBus)
29 this.syncedEditorState?.subscribeToAnyProperty((property, value) => {
30 void this.editorInvoker.syncProperty(property, value)
33 window.addEventListener('message', (event) => {
34 if (event.source !== this.editorFrame.contentWindow) {
35 this.logger.info('Client ignoring message from unknown source', event.data)
39 const message = event.data as EditorToClientGenericMessage
41 this.logger.debug('Received message data from editor', message)
43 if (message.type === EditorBridgeMessageType.EditorToClientInvokation) {
44 void this.handleEditorRequestingClientMethod(
45 message as EditorToClientInvokationMessage<keyof EditorRequiresClientMethods>,
47 } else if (message.type === EditorBridgeMessageType.EditorToClientReply) {
48 this.editorInvoker.handleReplyFromEditor(message as EditorToClientReplyMessage)
52 editorController.provideEditorInvoker(this.editorInvoker)
55 private async handleEditorRequestingClientMethod(
56 message: EditorToClientInvokationMessage<keyof EditorRequiresClientMethods>,
58 const func = this.editorRequestHandler[message.functionName].bind(this.editorRequestHandler)
62 const returnValue = await func(...message.args)
64 const reply: ClientToEditorReplyMessage = {
65 messageId: message.messageId,
67 type: EditorBridgeMessageType.ClientToEditorReply,
70 this.editorFrame.contentWindow?.postMessage(reply, BridgeOriginProvider.GetEditorOrigin())
72 this.logger.error('Error while handling editor request', 'message:', message, 'error:', String(error))