import type { Plugin } from '../store/plugin'; import clsx from 'clsx'; import yaml from 'js-yaml'; import OpenAPIClientAxios from 'openapi-client-axios'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useDebouncedCallback } from 'use-debounce'; import { PLUGINS_REPO_URL } from '../constant'; import AddIcon from '../icons/add.svg'; import CloseIcon from '../icons/close.svg'; import ConfirmIcon from '../icons/confirm.svg'; import DeleteIcon from '../icons/delete.svg'; import EditIcon from '../icons/edit.svg'; import GithubIcon from '../icons/github.svg'; import ReloadIcon from '../icons/reload.svg'; import Locale from '../locales'; import { FunctionToolService, usePluginStore } from '../store/plugin'; import { IconButton } from './button'; import { ErrorBoundary } from './error'; import styles from './mask.module.scss'; import pluginStyles from './plugin.module.scss'; import { List, ListItem, Modal, PasswordInput, showConfirm, showToast, } from './ui-lib'; export function PluginPage() { const navigate = useNavigate(); const pluginStore = usePluginStore(); const allPlugins = pluginStore.getAll(); const [searchPlugins, setSearchPlugins] = useState([]); const [searchText, setSearchText] = useState(''); const plugins = searchText.length > 0 ? searchPlugins : allPlugins; // refactored already, now it accurate const onSearch = (text: string) => { setSearchText(text); if (text.length > 0) { const result = allPlugins.filter( m => m?.title.toLowerCase().includes(text.toLowerCase()), ); setSearchPlugins(result); } else { setSearchPlugins(allPlugins); } }; const [editingPluginId, setEditingPluginId] = useState(); const editingPlugin = pluginStore.get(editingPluginId); const editingPluginTool = FunctionToolService.get(editingPlugin?.id); const closePluginModal = () => setEditingPluginId(undefined); const onChangePlugin = useDebouncedCallback((editingPlugin, e) => { const content = e.target.innerText; try { const api = new OpenAPIClientAxios({ definition: yaml.load(content) as any, }); api .init() .then(() => { if (content != editingPlugin.content) { pluginStore.updatePlugin(editingPlugin.id, (plugin) => { plugin.content = content; const tool = FunctionToolService.add(plugin, true); plugin.title = tool.api.definition.info.title; plugin.version = tool.api.definition.info.version; }); } }) .catch((e) => { console.error(e); showToast(Locale.Plugin.EditModal.Error); }); } catch (e) { console.error(e); showToast(Locale.Plugin.EditModal.Error); } }, 100).bind(null, editingPlugin); const [loadUrl, setLoadUrl] = useState(''); const loadFromUrl = (loadUrl: string) => fetch(loadUrl) .catch((e) => { const p = new URL(loadUrl); return fetch(`/api/proxy/${p.pathname}?${p.search}`, { headers: { 'X-Base-URL': p.origin, }, }); }) .then(res => res.text()) .then((content) => { try { return JSON.stringify(JSON.parse(content), null, ' '); } catch (e) { return content; } }) .then((content) => { pluginStore.updatePlugin(editingPlugin.id, (plugin) => { plugin.content = content; const tool = FunctionToolService.add(plugin, true); plugin.title = tool.api.definition.info.title; plugin.version = tool.api.definition.info.version; }); }) .catch((e) => { showToast(Locale.Plugin.EditModal.Error); }); return (
{Locale.Plugin.Page.Title}
{Locale.Plugin.Page.SubTitle(plugins.length)}
} bordered onClick={() => navigate(-1)} />
onSearch(e.currentTarget.value)} /> } text={Locale.Plugin.Page.Create} bordered onClick={() => { const createdPlugin = pluginStore.create(); setEditingPluginId(createdPlugin.id); }} />
{plugins.length == 0 && (
{Locale.Plugin.Page.Find} } bordered />
)} {plugins.map(m => (
{m.title} @ {m.version}
{Locale.Plugin.Item.Info( FunctionToolService.add(m).length, )}
} text={Locale.Plugin.Item.Edit} onClick={() => setEditingPluginId(m.id)} /> {!m.builtin && ( } text={Locale.Plugin.Item.Delete} onClick={async () => { if ( await showConfirm(Locale.Plugin.Item.DeleteConfirm) ) { pluginStore.delete(m.id); } }} /> )}
))}
{editingPlugin && (
} text={Locale.UI.Confirm} key="export" bordered onClick={() => setEditingPluginId('')} />, ]} > {['bearer', 'basic', 'custom'].includes( editingPlugin.authType as string, ) && ( )} {editingPlugin.authType == 'custom' && ( { pluginStore.updatePlugin(editingPlugin.id, (plugin) => { plugin.authHeader = e.target.value; }); }} > )} {['bearer', 'basic', 'custom'].includes( editingPlugin.authType as string, ) && ( { pluginStore.updatePlugin(editingPlugin.id, (plugin) => { plugin.authToken = e.currentTarget.value; }); }} > )}
setLoadUrl(e.currentTarget.value)} > } text={Locale.Plugin.EditModal.Load} bordered onClick={() => loadFromUrl(loadUrl)} />
                      
                      
                    
)} > {editingPluginTool?.tools.map((tool, index) => ( ))} )}
); }