feat: 插件中心从服务端拉取插件列表

pull/13/head
moonrailgun
parent 3bd89eb7d9
commit 6490901b64

@ -1,5 +1,6 @@
import { ChatConverseInfo, fetchConverseInfo } from '../model/converse'; import { ChatConverseInfo, fetchConverseInfo } from '../model/converse';
import { findGroupInviteByCode, GroupInvite } from '../model/group'; import { findGroupInviteByCode, GroupInvite } from '../model/group';
import { fetchRegistryPlugins } from '../model/plugin';
import { fetchUserInfo, UserBaseInfo } from '../model/user'; import { fetchUserInfo, UserBaseInfo } from '../model/user';
import { queryClient } from './index'; import { queryClient } from './index';
@ -46,3 +47,18 @@ export async function getCachedGroupInviteInfo(
return data; return data;
} }
/**
*
*/
export async function getCachedRegistryPlugins() {
const data = await queryClient.fetchQuery(
['pluginRegistry'],
() => fetchRegistryPlugins(),
{
staleTime: 2 * 60 * 60 * 1000, // 缓存2小时
}
);
return data;
}

@ -5,7 +5,11 @@ export { createSocket } from './api/socket';
export type { AppSocket } from './api/socket'; export type { AppSocket } from './api/socket';
// cache // cache
export { getCachedUserInfo, getCachedGroupInviteInfo } from './cache/cache'; export {
getCachedUserInfo,
getCachedGroupInviteInfo,
getCachedRegistryPlugins,
} from './cache/cache';
export { useCachedUserInfo } from './cache/useCache'; export { useCachedUserInfo } from './cache/useCache';
// components // components

@ -1,3 +1,5 @@
import { request } from '../api/request';
export interface PluginManifest { export interface PluginManifest {
/** /**
* *
@ -46,3 +48,9 @@ export interface PluginManifest {
*/ */
requireRestart: boolean; requireRestart: boolean;
} }
export async function fetchRegistryPlugins(): Promise<PluginManifest[]> {
const { data } = await request.get('/api/plugin/registry/list');
return data;
}

@ -15,9 +15,9 @@ import { pluginManager } from '../manager';
export const PluginStoreItem: React.FC<{ export const PluginStoreItem: React.FC<{
manifest: PluginManifest; manifest: PluginManifest;
installed: boolean; installed: boolean;
builtin: boolean; builtin?: boolean;
}> = React.memo((props) => { }> = React.memo((props) => {
const { manifest, builtin } = props; const { manifest, builtin = false } = props;
const [installed, setInstalled] = useState(props.installed); const [installed, setInstalled] = useState(props.installed);
const [{ loading }, handleInstallPlugin] = useAsyncRequest(async () => { const [{ loading }, handleInstallPlugin] = useAsyncRequest(async () => {

@ -11,14 +11,30 @@ import { builtinPlugins } from '../builtin';
import { pluginManager } from '../manager'; import { pluginManager } from '../manager';
import { PluginStoreItem } from './Item'; import { PluginStoreItem } from './Item';
export const PluginStore: React.FC = React.memo(() => { function usePluginStoreData() {
const { loading, value: installedPluginList = [] } = useAsync( const { loading: loading1, value: installedPluginList = [] } = useAsync(
async () => pluginManager.getInstalledPlugins(), async () => pluginManager.getInstalledPlugins(),
[] []
); );
const { loading: loading2, value: allPlugins = [] } = useAsync(
async () => pluginManager.getRegistryPlugins(),
[]
);
const loading = loading1 || loading2;
return {
loading,
installedPluginList,
allPlugins,
};
}
export const PluginStore: React.FC = React.memo(() => {
const { loading, installedPluginList, allPlugins } = usePluginStoreData();
if (loading) { if (loading) {
return <LoadingSpinner tip={t('正在加载已安装插件')} />; return <LoadingSpinner tip={t('正在加载插件列表')} />;
} }
const installedPluginNameList = installedPluginList.map((p) => p.name); const installedPluginNameList = installedPluginList.map((p) => p.name);
@ -43,7 +59,16 @@ export const PluginStore: React.FC = React.memo(() => {
<Divider orientation="left">{t('插件中心')}</Divider> <Divider orientation="left">{t('插件中心')}</Divider>
{/* TODO: 插件中心 */} <div className="flex flex-wrap">
{allPlugins.map((plugin) => (
<div key={plugin.name} className="m-1">
<PluginStoreItem
manifest={plugin}
installed={installedPluginNameList.includes(plugin.name)}
/>
</div>
))}
</div>
</PillTabPane> </PillTabPane>
<PillTabPane key="2" tab={t('已安装')}> <PillTabPane key="2" tab={t('已安装')}>

@ -1,5 +1,5 @@
import { initMiniStar, regDependency, regSharedModule } from 'mini-star'; import { regDependency, regSharedModule } from 'mini-star';
import { builtinPlugins } from './builtin'; import { pluginManager } from './manager';
/** /**
* *
@ -8,14 +8,7 @@ export function initPlugins(): Promise<void> {
registerDependencies(); registerDependencies();
registerModules(); registerModules();
const plugins = builtinPlugins.map(({ name, url }) => ({ return pluginManager.initPlugins();
name,
url,
}));
return initMiniStar({
plugins,
});
} }
function registerDependencies() { function registerDependencies() {

@ -1,4 +1,8 @@
import { getStorage, PluginManifest } from 'tailchat-shared'; import {
getCachedRegistryPlugins,
getStorage,
PluginManifest,
} from 'tailchat-shared';
import { initMiniStar, loadSinglePlugin } from 'mini-star'; import { initMiniStar, loadSinglePlugin } from 'mini-star';
import _once from 'lodash/once'; import _once from 'lodash/once';
import { builtinPlugins } from './builtin'; import { builtinPlugins } from './builtin';
@ -7,7 +11,7 @@ class PluginManager {
/** /**
* Key * Key
*/ */
static STORE_KEY = '__installed_plugins'; static STORE_KEY = '$TailchatInstalledPlugins';
/** /**
* *
@ -40,6 +44,13 @@ class PluginManager {
return plugins; return plugins;
} }
/**
*
*/
async getRegistryPlugins(): Promise<PluginManifest[]> {
return await getCachedRegistryPlugins();
}
/** /**
* *
*/ */

Loading…
Cancel
Save