You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-16 00:14:34 +02:00
Chore: Refactor mobile plugin logic into locations more consistent with other parts of the app (#10636)
This commit is contained in:
@ -0,0 +1,53 @@
|
||||
import { useMemo, RefObject } from 'react';
|
||||
import { DialogMainProcessApi, DialogWebViewApi } from '../../types';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { WebViewControl } from '../../../../components/ExtendedWebView';
|
||||
import createOnLogHander from '../../utils/createOnLogHandler';
|
||||
import RNToWebViewMessenger from '../../../../utils/ipc/RNToWebViewMessenger';
|
||||
import { SerializableData } from '@joplin/lib/utils/ipc/types';
|
||||
import PostMessageService, { ResponderComponentType } from '@joplin/lib/services/PostMessageService';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
|
||||
interface Props {
|
||||
pluginId: string;
|
||||
viewId: string;
|
||||
webviewRef: RefObject<WebViewControl>;
|
||||
messageChannelId: string;
|
||||
}
|
||||
|
||||
const useDialogMessenger = (props: Props) => {
|
||||
const { pluginId, webviewRef, viewId, messageChannelId } = props;
|
||||
|
||||
return useMemo(() => {
|
||||
const plugin = PluginService.instance().pluginById(pluginId);
|
||||
const logger = Logger.create(`PluginDialogWebView(${pluginId})`);
|
||||
|
||||
const dialogApi: DialogMainProcessApi = {
|
||||
postMessage: async (message: SerializableData) => {
|
||||
return await plugin.viewController(viewId).emitMessage({ message });
|
||||
},
|
||||
onMessage: async (callback) => {
|
||||
PostMessageService.instance().registerViewMessageHandler(
|
||||
ResponderComponentType.UserWebview,
|
||||
viewId,
|
||||
(message: SerializableData) => {
|
||||
// For compatibility with desktop, the message needs to be wrapped in
|
||||
// an object.
|
||||
return callback({ message });
|
||||
},
|
||||
);
|
||||
},
|
||||
onError: async (error: string) => {
|
||||
logger.error(`Unhandled error: ${error}`);
|
||||
plugin.hasErrors = true;
|
||||
},
|
||||
onLog: createOnLogHander(plugin, logger),
|
||||
};
|
||||
|
||||
return new RNToWebViewMessenger<DialogMainProcessApi, DialogWebViewApi>(
|
||||
messageChannelId, webviewRef, dialogApi,
|
||||
);
|
||||
}, [webviewRef, pluginId, viewId, messageChannelId]);
|
||||
};
|
||||
|
||||
export default useDialogMessenger;
|
@ -0,0 +1,52 @@
|
||||
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
|
||||
import { useRef, useState } from 'react';
|
||||
import { DialogContentSize, DialogWebViewApi } from '../../types';
|
||||
import { PixelRatio } from 'react-native';
|
||||
|
||||
interface Props {
|
||||
dialogControl: DialogWebViewApi;
|
||||
webViewLoadCount: number;
|
||||
watchForSizeChanges: boolean;
|
||||
}
|
||||
|
||||
const useDialogSize = (props: Props) => {
|
||||
const { dialogControl, webViewLoadCount } = props;
|
||||
|
||||
const [dialogSize, setDialogSize] = useState<DialogContentSize|null>(null);
|
||||
const lastSizeRef = useRef(dialogSize);
|
||||
lastSizeRef.current = dialogSize;
|
||||
useAsyncEffect(async event => {
|
||||
if (!dialogControl) {
|
||||
// May happen if the webview is still loading.
|
||||
return;
|
||||
}
|
||||
|
||||
while (!event.cancelled) {
|
||||
const contentSize = await dialogControl.getContentSize();
|
||||
if (event.cancelled) return;
|
||||
|
||||
const lastSize = lastSizeRef.current;
|
||||
if (contentSize.width !== lastSize?.width || contentSize.height !== lastSize?.height) {
|
||||
// We use 1000 here because getPixelSizeForLayoutSize is guaranteed to return
|
||||
// an integer.
|
||||
const pixelToDpRatio = 1000 / PixelRatio.getPixelSizeForLayoutSize(1000);
|
||||
setDialogSize({
|
||||
width: contentSize.width * pixelToDpRatio,
|
||||
height: contentSize.height * pixelToDpRatio,
|
||||
});
|
||||
}
|
||||
|
||||
if (!props.watchForSizeChanges) return;
|
||||
|
||||
await new Promise<void>(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
}, [dialogControl, setDialogSize, webViewLoadCount]);
|
||||
|
||||
return dialogSize;
|
||||
};
|
||||
|
||||
export default useDialogSize;
|
@ -0,0 +1,10 @@
|
||||
import { PluginStates, utils as pluginUtils } from '@joplin/lib/services/plugins/reducer';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
const useViewInfos = (pluginStates: PluginStates) => {
|
||||
return useMemo(() => {
|
||||
return pluginUtils.viewInfosByType(pluginStates, 'webview');
|
||||
}, [pluginStates]);
|
||||
};
|
||||
|
||||
export default useViewInfos;
|
@ -0,0 +1,43 @@
|
||||
import { useEffect } from 'react';
|
||||
import { DialogWebViewApi } from '../../types';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import { themeStyle } from '../../../../components/global-style';
|
||||
import themeToCss from '@joplin/lib/services/style/themeToCss';
|
||||
|
||||
interface Props {
|
||||
themeId: number;
|
||||
scriptPaths: string[];
|
||||
dialogControl: DialogWebViewApi;
|
||||
pluginBaseDir: string;
|
||||
|
||||
// Whenever the WebView reloads, we need to re-inject CSS and JavaScript.
|
||||
webViewLoadCount: number;
|
||||
}
|
||||
|
||||
const useWebViewSetup = (props: Props) => {
|
||||
const { scriptPaths, dialogControl, pluginBaseDir, themeId } = props;
|
||||
|
||||
useEffect(() => {
|
||||
const jsPaths = [];
|
||||
const cssPaths = [];
|
||||
for (const rawPath of scriptPaths) {
|
||||
const resolvedPath = shim.fsDriver().resolveRelativePathWithinDir(pluginBaseDir, rawPath);
|
||||
|
||||
if (resolvedPath.match(/\.css$/i)) {
|
||||
cssPaths.push(resolvedPath);
|
||||
} else {
|
||||
jsPaths.push(resolvedPath);
|
||||
}
|
||||
}
|
||||
void dialogControl.includeCssFiles(cssPaths);
|
||||
void dialogControl.includeJsFiles(jsPaths);
|
||||
}, [dialogControl, scriptPaths, props.webViewLoadCount, pluginBaseDir]);
|
||||
|
||||
useEffect(() => {
|
||||
const theme = themeStyle(themeId);
|
||||
const themeVariableCss = themeToCss(theme);
|
||||
void dialogControl.setThemeCss(themeVariableCss);
|
||||
}, [dialogControl, themeId, props.webViewLoadCount]);
|
||||
};
|
||||
|
||||
export default useWebViewSetup;
|
Reference in New Issue
Block a user