2024-04-26 00:04:24 +02:00
|
|
|
import { DialogWebViewApi, DialogMainProcessApi, WebViewPostMessageCallback, DialogSetOnMessageListenerCallback } from '../types';
|
2024-03-14 21:04:32 +02:00
|
|
|
import reportUnhandledErrors from './utils/reportUnhandledErrors';
|
|
|
|
import wrapConsoleLog from './utils/wrapConsoleLog';
|
|
|
|
import WebViewToRNMessenger from '../../../utils/ipc/WebViewToRNMessenger';
|
2024-04-03 19:56:54 +02:00
|
|
|
import getFormData from './utils/getFormData';
|
2024-03-14 21:04:32 +02:00
|
|
|
|
2024-04-26 00:04:24 +02:00
|
|
|
interface ExtendedWindow extends Window {
|
|
|
|
webviewApi: {
|
|
|
|
postMessage: WebViewPostMessageCallback;
|
|
|
|
onMessage: DialogSetOnMessageListenerCallback;
|
|
|
|
};
|
|
|
|
exports: Record<string, unknown>;
|
|
|
|
}
|
|
|
|
|
|
|
|
declare const window: ExtendedWindow;
|
|
|
|
|
2024-03-14 21:04:32 +02:00
|
|
|
let themeCssElement: HTMLStyleElement|null = null;
|
|
|
|
|
|
|
|
const initializeDialogWebView = (messageChannelId: string) => {
|
|
|
|
const loadedPaths: Set<string> = new Set();
|
|
|
|
|
|
|
|
type ScriptType = 'js'|'css';
|
|
|
|
const includeScriptsOrStyles = (type: ScriptType, paths: string[]) => {
|
|
|
|
for (const path of paths) {
|
|
|
|
if (loadedPaths.has(path)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
loadedPaths.add(path);
|
|
|
|
|
|
|
|
if (type === 'css') {
|
|
|
|
const stylesheetLink = document.createElement('link');
|
|
|
|
stylesheetLink.rel = 'stylesheet';
|
|
|
|
stylesheetLink.href = path;
|
|
|
|
document.head.appendChild(stylesheetLink);
|
|
|
|
} else {
|
|
|
|
const script = document.createElement('script');
|
|
|
|
script.src = path;
|
|
|
|
document.head.appendChild(script);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const localApi: DialogWebViewApi = {
|
|
|
|
includeCssFiles: async (paths: string[]) => {
|
|
|
|
return includeScriptsOrStyles('css', paths);
|
|
|
|
},
|
|
|
|
includeJsFiles: async (paths: string[]) => {
|
|
|
|
return includeScriptsOrStyles('js', paths);
|
|
|
|
},
|
2024-08-02 15:51:49 +02:00
|
|
|
runScript: async (key: string, scriptData: string) => {
|
|
|
|
if (loadedPaths.has(key)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
loadedPaths.add(key);
|
|
|
|
|
|
|
|
if (key.endsWith('.css')) {
|
|
|
|
const stylesheetLink = document.createElement('style');
|
|
|
|
stylesheetLink.appendChild(document.createTextNode(scriptData));
|
|
|
|
document.head.appendChild(stylesheetLink);
|
|
|
|
} else {
|
|
|
|
const script = document.createElement('script');
|
|
|
|
script.appendChild(document.createTextNode(scriptData));
|
|
|
|
document.head.appendChild(script);
|
|
|
|
}
|
|
|
|
},
|
2024-03-14 21:04:32 +02:00
|
|
|
getFormData: async () => {
|
2024-04-03 19:56:54 +02:00
|
|
|
return getFormData();
|
2024-03-14 21:04:32 +02:00
|
|
|
},
|
|
|
|
setThemeCss: async (css: string) => {
|
|
|
|
themeCssElement?.remove?.();
|
|
|
|
const styleElement = document.createElement('style');
|
|
|
|
styleElement.appendChild(document.createTextNode(css));
|
|
|
|
document.body.appendChild(styleElement);
|
|
|
|
themeCssElement = styleElement;
|
|
|
|
},
|
|
|
|
getContentSize: async () => {
|
|
|
|
// To convert to React Native pixel units from browser pixel units,
|
|
|
|
// we need to multiply by the devicePixelRatio:
|
|
|
|
const dpr = window.devicePixelRatio ?? 1;
|
|
|
|
|
2024-04-03 19:56:54 +02:00
|
|
|
const element = document.getElementById('joplin-plugin-content') ?? document.body;
|
2024-03-14 21:04:32 +02:00
|
|
|
return {
|
2024-04-03 19:56:54 +02:00
|
|
|
width: element.clientWidth * dpr,
|
|
|
|
height: element.clientHeight * dpr,
|
2024-03-14 21:04:32 +02:00
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const messenger = new WebViewToRNMessenger<DialogWebViewApi, DialogMainProcessApi>(messageChannelId, localApi);
|
|
|
|
|
2024-04-26 00:04:24 +02:00
|
|
|
window.webviewApi = {
|
2024-03-14 21:04:32 +02:00
|
|
|
postMessage: messenger.remoteApi.postMessage,
|
|
|
|
onMessage: messenger.remoteApi.onMessage,
|
|
|
|
};
|
|
|
|
|
|
|
|
reportUnhandledErrors(messenger.remoteApi.onError);
|
|
|
|
wrapConsoleLog(messenger.remoteApi.onLog);
|
|
|
|
|
|
|
|
// If dialog content scripts were bundled with Webpack for NodeJS,
|
|
|
|
// they may expect a global "exports" to be present.
|
2024-04-26 00:04:24 +02:00
|
|
|
window.exports ??= {};
|
2024-03-14 21:04:32 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export default initializeDialogWebView;
|