import * as React from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { PluginHtmlContents, ViewInfo } from '@joplin/lib/services/plugins/reducer'; import ExtendedWebView, { WebViewControl } from '../../../components/ExtendedWebView'; import { ViewStyle } from 'react-native'; import usePlugin from '@joplin/lib/hooks/usePlugin'; import shim from '@joplin/lib/shim'; import useDialogMessenger from './hooks/useDialogMessenger'; import useWebViewSetup from './hooks/useWebViewSetup'; import { DialogWebViewApi } from '../types'; interface Props { themeId: number; pluginHtmlContents: PluginHtmlContents; viewInfo: ViewInfo; style: ViewStyle; onLoadEnd: ()=> void; setDialogControl: (dialogControl: DialogWebViewApi)=> void; } const PluginUserWebView = (props: Props) => { const viewInfo = props.viewInfo; const view = viewInfo.view; const pluginId = viewInfo.plugin.id; const viewId = view.id; const plugin = usePlugin(pluginId); const [webViewLoadCount, setWebViewLoadCount] = useState(0); const webviewRef = useRef(null); const messageChannelId = `dialog-messenger-${pluginId}-${viewId}`; const messenger = useDialogMessenger({ pluginId, viewId, webviewRef, messageChannelId, }); useEffect(() => { // Because of how messenger.remoteApi handles message forwarding (property names // are not known), we need to send methods individually and can't use an object // spread or send messenger.remoteApi. props.setDialogControl({ includeCssFiles: messenger.remoteApi.includeCssFiles, includeJsFiles: messenger.remoteApi.includeJsFiles, setThemeCss: messenger.remoteApi.setThemeCss, getFormData: messenger.remoteApi.getFormData, getContentSize: messenger.remoteApi.getContentSize, }); }, [messenger, props.setDialogControl]); useWebViewSetup({ themeId: props.themeId, dialogControl: messenger.remoteApi, scriptPaths: view.scripts ?? [], pluginBaseDir: plugin.baseDir, webViewLoadCount, }); const htmlContent = props.pluginHtmlContents[pluginId]?.[viewId] ?? ''; const html = ` Plugin Dialog
${htmlContent}
`; const injectedJs = useMemo(() => { return ` if (!window.backgroundPageLoaded) { ${shim.injectedJs('pluginBackgroundPage')} pluginBackgroundPage.initializeDialogWebView( ${JSON.stringify(messageChannelId)} ); window.backgroundPageLoaded = true; } `; }, [messageChannelId]); const onWebViewLoaded = useCallback(() => { setWebViewLoadCount(webViewLoadCount + 1); props.onLoadEnd(); messenger.onWebViewLoaded(); }, [messenger, setWebViewLoadCount, webViewLoadCount, props.onLoadEnd]); return ( ); }; export default PluginUserWebView;