1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-18 09:35:20 +02:00
joplin/packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useWebViewApi.ts

73 lines
2.0 KiB
TypeScript

import PluginService from '@joplin/lib/services/plugins/PluginService';
import { useEffect } from 'react';
import { Editor } from 'tinymce';
const useWebViewApi = (editor: Editor) => {
useEffect(() => {
if (!editor) return ()=>{};
const scriptElement = document.createElement('script');
const channelId = `plugin-post-message-${Math.random()}`;
scriptElement.appendChild(document.createTextNode(`
window.webviewApi = {
postMessage: (contentScriptId, message) => {
const channelId = ${JSON.stringify(channelId)};
const messageId = Math.random();
window.parent.postMessage({
channelId,
messageId,
contentScriptId,
message,
}, '*');
const waitForResponse = async () => {
while (true) {
const messageEvent = await new Promise(resolve => {
window.addEventListener('message', event => {
resolve(event);
}, {once: true});
});
if (messageEvent.source !== window.parent || messageEvent.data.messageId !== messageId) {
continue;
}
const data = messageEvent.data;
return data.response;
}
};
return waitForResponse();
},
};
`));
const editorWindow = editor.getWin();
editorWindow.document.head.appendChild(scriptElement);
const onMessageHandler = async (event: MessageEvent) => {
if (event.source !== editorWindow || event.data.channelId !== channelId) {
return;
}
const contentScriptId = event.data.contentScriptId;
const pluginService = PluginService.instance();
const plugin = pluginService.pluginById(
pluginService.pluginIdByContentScriptId(contentScriptId),
);
const result = await plugin.emitContentScriptMessage(contentScriptId, event.data.message);
editorWindow.postMessage({
messageId: event.data.messageId,
response: result,
}, '*');
};
window.addEventListener('message', onMessageHandler);
return () => {
window.removeEventListener('message', onMessageHandler);
scriptElement.remove();
};
}, [editor]);
};
export default useWebViewApi;