Files
ttstd-infinite-canvas/web/src/pages/plugins/plugin-documentation-modals.tsx

93 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Modal, Upload } from "antd";
import { CloudUpload, FileText, ShieldCheck } from "lucide-react";
import type { RegisteredPlugin } from "@/lib/plugins/plugin-types";
import pluginDevelopmentGuideMarkdown from "./plugin-development-guide.md?raw";
import { getPluginDocumentation } from "./plugin-documentation";
import { PluginMarkdown } from "./plugin-markdown";
type UploadPluginModalProps = {
open: boolean;
onClose: () => void;
onUpload: (file: File) => void;
};
export function UploadPluginModal({ open, onClose, onUpload }: UploadPluginModalProps) {
return (
<Modal
className="workspace-modal workspace-modal-wide plugin-upload-modal"
title="上传插件"
open={open}
centered
footer={null}
destroyOnHidden
onCancel={onClose}
styles={{ body: { maxHeight: "min(82vh, 900px)", overflowY: "auto", overscrollBehavior: "contain" } }}
>
<div className="plugin-upload-layout">
<section className="plugin-upload-guide">
<PluginMarkdown source={pluginDevelopmentGuideMarkdown} />
</section>
<aside className="plugin-upload-panel">
<div className="plugin-upload-panel-heading">
<span className="plugin-upload-panel-icon"><CloudUpload className="size-5" /></span>
<div>
<h2>安装插件包</h2>
<p>选择符合清单规范的 JSON 文件,安装后会立即进入插件中心。</p>
</div>
</div>
<Upload.Dragger
className="plugin-upload-dropzone"
accept=".json,application/json"
maxCount={1}
showUploadList={false}
beforeUpload={(file) => {
onUpload(file);
return false;
}}
>
<CloudUpload className="plugin-upload-dropzone-icon" />
<p className="ant-upload-text">点击选择插件文件</p>
<p className="ant-upload-hint">仅支持 JSON 清单,大小不超过 512 KiB</p>
</Upload.Dragger>
<div className="plugin-upload-notice">
<ShieldCheck className="size-4" />
<span>上传前请确认插件来源可信。协议插件不会在浏览器执行任意脚本,密钥也不会从清单读取。</span>
</div>
</aside>
</div>
</Modal>
);
}
type PluginDetailsModalProps = {
plugin?: RegisteredPlugin;
restoreFocus: boolean;
onClose: () => void;
};
export function PluginDetailsModal({ plugin, restoreFocus, onClose }: PluginDetailsModalProps) {
return (
<Modal
className="workspace-modal workspace-modal-wide plugin-details-modal"
title={plugin ? (
<div className="plugin-details-title">
<FileText className="size-4" />
<span>{plugin.manifest.name}</span>
<span className="plugin-version">v{plugin.manifest.version}</span>
</div>
) : null}
open={Boolean(plugin)}
centered
footer={null}
destroyOnHidden
focusTriggerAfterClose={restoreFocus}
onCancel={onClose}
styles={{ body: { maxHeight: "min(78vh, 820px)", overflowY: "auto", overscrollBehavior: "contain" } }}
>
{plugin ? <PluginMarkdown className="plugin-details-document" source={getPluginDocumentation(plugin.manifest)} /> : null}
</Modal>
);
}