mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-14 03:30:19 +00:00
✨ feat: support plugin settings modal
This commit is contained in:
@@ -15,7 +15,6 @@ const ChatInputDesktopLayout = memo(() => {
|
||||
|
||||
return (
|
||||
<DraggablePanel
|
||||
expandable={false}
|
||||
fullscreen={expand}
|
||||
headerHeight={HEADER_HEIGHT}
|
||||
minHeight={CHAT_TEXTAREA_HEIGHT}
|
||||
|
||||
@@ -36,7 +36,7 @@ const PluginSettings: RenderErrorMessage = memo(({ id, plugin }) => {
|
||||
<Flexbox className={styles.desc}>{t('pluginSettings.desc')}</Flexbox>
|
||||
<Divider style={{ margin: '0 16px' }} />
|
||||
{manifest.settings && (
|
||||
<PluginSettingsConfig id={manifest.identifier} settings={manifest.settings} />
|
||||
<PluginSettingsConfig id={manifest.identifier} schema={manifest.settings} />
|
||||
)}
|
||||
<Button
|
||||
block
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { ActionIcon } from '@lobehub/ui';
|
||||
import { LucideSettings } from 'lucide-react';
|
||||
import { memo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import PluginSettingsModal from '@/features/PluginSettingsModal';
|
||||
import { pluginSelectors, usePluginStore } from '@/store/plugin';
|
||||
|
||||
const Settings = memo<{ id: string }>(({ id }) => {
|
||||
const item = usePluginStore(pluginSelectors.getPluginManifestById(id));
|
||||
const [open, setOpen] = useState(false);
|
||||
const { t } = useTranslation('plugin');
|
||||
return (
|
||||
item?.settings && (
|
||||
<>
|
||||
<ActionIcon
|
||||
icon={LucideSettings}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
title={t('setting')}
|
||||
/>
|
||||
<PluginSettingsModal
|
||||
id={id}
|
||||
onClose={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
open={open}
|
||||
schema={item.settings}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
export default Settings;
|
||||
@@ -10,6 +10,7 @@ import { Flexbox } from 'react-layout-kit';
|
||||
import { pluginHelpers, pluginSelectors, usePluginStore } from '@/store/plugin';
|
||||
|
||||
import PluginResult from './PluginResultJSON';
|
||||
import Settings from './Settings';
|
||||
import { useStyles } from './style';
|
||||
|
||||
export interface InspectorProps {
|
||||
@@ -76,6 +77,7 @@ const Inspector = memo<InspectorProps>(
|
||||
</Flexbox>
|
||||
<Flexbox horizontal>
|
||||
{type === 'standalone' && <ActionIcon icon={LucideOrbit} />}
|
||||
<Settings id={id} />
|
||||
{setShow && (
|
||||
<ActionIcon
|
||||
icon={showRender ? LucideChevronUp : LucideChevronDown}
|
||||
|
||||
@@ -9,6 +9,8 @@ import { usePluginStore } from '@/store/plugin';
|
||||
import PluginSettingRender from './PluginSettingRender';
|
||||
|
||||
export const transformPluginSettings = (pluginSettings: PluginSchema) => {
|
||||
if (!pluginSettings?.properties) return [];
|
||||
|
||||
return Object.entries(pluginSettings.properties).map(([name, i]) => ({
|
||||
desc: i.description,
|
||||
format: i.format,
|
||||
@@ -21,7 +23,7 @@ export const transformPluginSettings = (pluginSettings: PluginSchema) => {
|
||||
|
||||
interface PluginSettingsConfigProps {
|
||||
id: string;
|
||||
settings: PluginSchema;
|
||||
schema: PluginSchema;
|
||||
}
|
||||
|
||||
const useStyles = createStyles(({ css, token }) => ({
|
||||
@@ -32,8 +34,8 @@ const useStyles = createStyles(({ css, token }) => ({
|
||||
`,
|
||||
}));
|
||||
|
||||
const PluginSettingsConfig = memo<PluginSettingsConfigProps>(({ settings, id }) => {
|
||||
const items = transformPluginSettings(settings);
|
||||
const PluginSettingsConfig = memo<PluginSettingsConfigProps>(({ schema, id }) => {
|
||||
const items = transformPluginSettings(schema);
|
||||
|
||||
const { styles } = useStyles();
|
||||
const [updatePluginSettings] = usePluginStore((s) => [s.updatePluginSettings]);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Avatar, Modal } from '@lobehub/ui';
|
||||
import { Divider, Typography } from 'antd';
|
||||
import { useTheme } from 'antd-style';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Center, Flexbox } from 'react-layout-kit';
|
||||
|
||||
import PluginSettingsConfig from '@/features/PluginSettings';
|
||||
import { pluginHelpers, pluginSelectors, usePluginStore } from '@/store/plugin';
|
||||
|
||||
interface PluginSettingsModalProps {
|
||||
id: string;
|
||||
onClose: () => void;
|
||||
open?: boolean;
|
||||
schema: any;
|
||||
}
|
||||
|
||||
const PluginSettingsModal = memo<PluginSettingsModalProps>(({ schema, onClose, id, open }) => {
|
||||
const pluginMeta = usePluginStore(pluginSelectors.getPluginMetaById(id), isEqual);
|
||||
|
||||
const { t } = useTranslation('plugin');
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Modal onCancel={onClose} open={open} title={t('setting')} width={600}>
|
||||
<Center gap={16}>
|
||||
<Avatar
|
||||
avatar={pluginHelpers.getPluginAvatar(pluginMeta?.meta) || '⚙️'}
|
||||
background={theme.colorFillContent}
|
||||
gap={12}
|
||||
size={64}
|
||||
/>
|
||||
|
||||
<Flexbox style={{ fontSize: 20 }}>{pluginHelpers.getPluginTitle(pluginMeta?.meta)}</Flexbox>
|
||||
<Typography.Text type={'secondary'}>
|
||||
{pluginHelpers.getPluginDesc(pluginMeta?.meta)}
|
||||
</Typography.Text>
|
||||
<Divider style={{ marginBottom: 0, marginTop: 8 }} />
|
||||
{schema && <PluginSettingsConfig id={id} schema={schema} />}
|
||||
</Center>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default PluginSettingsModal;
|
||||
Reference in New Issue
Block a user