feat: 增加插件文档的按钮

pull/81/head
moonrailgun 3 years ago
parent 9328c9b8de
commit e29c22f4dc

@ -104,7 +104,7 @@ importers:
specifiers:
'@iconify/iconify': ^2.0.2
'@iconify/react': ^3.0.0-alpha.1
'@loadable/component': ^5.15.0
'@loadable/component': ^5.15.2
'@testing-library/jest-dom': ^5.14.1
'@testing-library/react': ^12.0.0
'@testing-library/react-hooks': ^7.0.1
@ -2423,7 +2423,7 @@ packages:
dev: true
/@types/loadable__component/5.13.4:
resolution: {integrity: sha1-pGRrJAaxKD76wanZSFgkqQWzPUo=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/@types/loadable__component/download/@types/loadable__component-5.13.4.tgz}
resolution: {integrity: sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==}
dependencies:
'@types/react': 17.0.38
dev: true
@ -4845,6 +4845,12 @@ packages:
value-equal: registry.nlark.com/value-equal/1.0.1
dev: false
/hoist-non-react-statics/3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
dependencies:
react-is: 16.13.1
dev: false
/hosted-git-info/2.8.9:
resolution: {integrity: sha1-3/wL+aIcAiCQkPKqaUKeFBTa8/k=, registry: https://registry.npm.taobao.org/, tarball: https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.9.tgz}
dev: true

@ -47,6 +47,12 @@ export interface PluginManifest {
*
*/
requireRestart: boolean;
/**
*
* markdown, html使iframe
*/
documentUrl?: string;
}
/**

@ -25,7 +25,7 @@
"dependencies": {
"@iconify/iconify": "^2.0.2",
"@iconify/react": "^3.0.0-alpha.1",
"@loadable/component": "^5.15.0",
"@loadable/component": "^5.15.2",
"antd": "^4.18.2",
"axios": "^0.21.1",
"clsx": "^1.1.1",

@ -1,7 +1,10 @@
import React, { useCallback } from 'react';
import { isValidStr } from 'tailchat-shared';
import { Loadable } from './Loadable';
const ReactMarkdown = React.lazy(() => import('react-markdown'));
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const ReactMarkdown = Loadable(() => import('react-markdown'));
export const Markdown: React.FC<{
raw: string;
@ -20,6 +23,7 @@ export const Markdown: React.FC<{
return (
<ReactMarkdown
className="tailchat-markdown"
transformImageUri={(src) => transformUrl(src)}
transformLinkUri={(href) => transformUrl(href)}
>

@ -0,0 +1,30 @@
import { LoadingSpinner } from '@/components/LoadingSpinner';
import { Markdown } from '@/components/Markdown';
import { Problem } from '@/components/Problem';
import React from 'react';
import { useAsync } from 'tailchat-shared';
export const DocumentMarkdownRender: React.FC<{ url: string }> = React.memo(
({ url }) => {
const { loading, value, error } = useAsync(async () => {
const data = await fetch(url);
if (data.status >= 400) {
throw new Error('请求异常');
}
const raw = data.text();
return raw;
}, [url]);
if (loading) {
return <LoadingSpinner />;
}
if (error) {
return <Problem text={String(error)} />;
}
return <Markdown raw={String(value)} />;
}
);
DocumentMarkdownRender.displayName = 'DocumentMarkdownRender';

@ -0,0 +1,24 @@
import { Problem } from '@/components/Problem';
import React from 'react';
import { isValidStr, t } from 'tailchat-shared';
import { DocumentMarkdownRender } from './DocumentMarkdownRender';
interface DocumentViewProps {
documentUrl?: string;
}
export const DocumentView: React.FC<DocumentViewProps> = React.memo((props) => {
const { documentUrl } = props;
if (!isValidStr(documentUrl)) {
return <Problem text={t('该插件没有更多描述')} />;
}
if (documentUrl.endsWith('.md')) {
return <DocumentMarkdownRender url={documentUrl} />;
} else if (documentUrl.endsWith('.html')) {
return <iframe src={documentUrl} />;
} else {
return <Problem text={t('不支持渲染的文档链接')} />;
}
});
DocumentView.displayName = 'DocumentView';

@ -1,14 +1,17 @@
import { Avatar } from '@/components/Avatar';
import { Button } from 'antd';
import { Button, Space } from 'antd';
import React, { useCallback, useState } from 'react';
import {
isValidStr,
PluginManifest,
showAlert,
showToasts,
t,
useAsyncRequest,
} from 'tailchat-shared';
import { ModalWrapper, openModal } from '../common';
import { pluginManager } from '../manager';
import { DocumentView } from './DocumentView';
/**
*
@ -41,6 +44,18 @@ export const PluginStoreItem: React.FC<{
});
}, [manifest]);
const handleShowDocument = useCallback(() => {
if (!isValidStr(manifest.documentUrl)) {
return;
}
openModal(
<ModalWrapper title={manifest.label}>
<DocumentView documentUrl={manifest.documentUrl} />
</ModalWrapper>
);
}, [manifest]);
return (
<div className="rounded-md flex w-80 mobile:w-full h-36 bg-white bg-opacity-40 dark:bg-black dark:bg-opacity-40 shadow py-2 px-3">
<div className="flex w-full">
@ -57,25 +72,31 @@ export const PluginStoreItem: React.FC<{
<div className="flex-1 overflow-auto">{manifest.description}</div>
<div className="mt-1 text-right">
{builtin ? (
<Button type="primary" disabled={true}>
{t('内置插件')}
</Button>
) : installed ? (
<Button type="primary" onClick={handleUninstallPlugin}>
{t('已安装')}
</Button>
) : (
<Button
type="primary"
loading={loading}
onClick={handleInstallPlugin}
>
{t('安装')}
</Button>
<Space className="mt-1 justify-end">
{isValidStr(manifest.documentUrl) && (
<Button onClick={handleShowDocument}></Button>
)}
</div>
<div>
{builtin ? (
<Button type="primary" disabled={true}>
{t('内置插件')}
</Button>
) : installed ? (
<Button type="primary" onClick={handleUninstallPlugin}>
{t('已安装')}
</Button>
) : (
<Button
type="primary"
loading={loading}
onClick={handleInstallPlugin}
>
{t('安装')}
</Button>
)}
</div>
</Space>
</div>
</div>
</div>

Loading…
Cancel
Save