文件
mynode/packages/app-desktop/services/plugins/UserWebviewDialog.tsx
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

108 行
3.3 KiB
TypeScript

import * as React from 'react';
import { useRef, useCallback, useMemo } from 'react';
import { ButtonSpec, DialogResult } from '@joplin/lib/services/plugins/api/types';
import PluginService from '@joplin/lib/services/plugins/PluginService';
import WebviewController from '@joplin/lib/services/plugins/WebviewController';
import UserWebview, { Props as UserWebviewProps } from './UserWebview';
import UserWebviewDialogButtonBar from './UserWebviewDialogButtonBar';
import { focus } from '@joplin/lib/utils/focusHandler';
import Dialog from '@joplin/lib/components/Dialog';
interface Props extends UserWebviewProps {
buttons: ButtonSpec[];
fitToContent: boolean;
}
function defaultButtons(): ButtonSpec[] {
return [
{
id: 'ok',
},
{
id: 'cancel',
},
];
}
function findSubmitButton(buttons: ButtonSpec[]): ButtonSpec | null {
return buttons.find((b: ButtonSpec) => {
return ['ok', 'yes', 'confirm', 'submit'].includes(b.id);
});
}
function findDismissButton(buttons: ButtonSpec[]): ButtonSpec | null {
return buttons.find((b: ButtonSpec) => {
return ['cancel', 'no', 'reject'].includes(b.id);
});
}
export default function UserWebviewDialog(props: Props) {
const webviewRef = useRef(null);
function viewController(): WebviewController {
return PluginService.instance().pluginById(props.pluginId).viewController(props.viewId) as WebviewController;
}
const buttons: ButtonSpec[] = (props.buttons ? props.buttons : defaultButtons()).map((b: ButtonSpec) => {
return {
...b,
onClick: async () => {
const response: DialogResult = { id: b.id };
const formData = await webviewRef.current.formData();
if (formData && Object.keys(formData).length) response.formData = formData;
viewController().closeWithResponse(response);
},
};
});
const onSubmit = useCallback(() => {
const submitButton = findSubmitButton(buttons);
if (submitButton) {
submitButton.onClick();
}
}, [buttons]);
const onDismiss = useCallback(() => {
const dismissButton = findDismissButton(buttons);
if (dismissButton) {
dismissButton.onClick();
}
}, [buttons]);
const onReady = useCallback(() => {
// We focus the dialog once it's ready to make sure that the ESC/Enter
// keyboard shortcuts are working.
// https://github.com/laurent22/joplin/issues/4474
if (webviewRef.current) focus('UserWebviewDialog', webviewRef.current);
}, []);
// When the iframe is isolated (security setting enabled), keyboard events
// like Escape don't reach the iframe content. We let the native <dialog>
// handle Escape by passing onCancel, but only when there's a dismiss button.
// https://github.com/laurent22/joplin/issues/13718
const onCancel = useMemo(() => {
return findDismissButton(buttons) ? onDismiss : undefined;
}, [buttons, onDismiss]);
return (
<Dialog className={`user-webview-dialog ${props.fitToContent ? '-fit' : ''}`} onCancel={onCancel}>
<div className='user-dialog-wrapper'>
<UserWebview
ref={webviewRef}
html={props.html}
scripts={props.scripts}
pluginId={props.pluginId}
viewId={props.viewId}
themeId={props.themeId}
borderBottom={false}
fitToContent={props.fitToContent}
onSubmit={onSubmit}
onDismiss={onDismiss}
onReady={onReady}
/>
</div>
<UserWebviewDialogButtonBar buttons={buttons}/>
</Dialog>
);
}