import { useEffect } from 'react'; import { Link } from 'react-router-dom'; import { AlertCircle, Download, PackageCheck, RefreshCw, Trash2 } from 'lucide-react'; import { toast } from 'sonner'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import type { MarketplaceInstallation, MarketplaceLibrarySnapshot } from '@/lib/plugin-marketplace'; import { pluginMarketplaceStore, usePluginMarketplaceStore } from '@/stores/plugin-marketplace'; import { useAuthStore } from '@/stores/auth'; function failureText(reason?: string): string | null { if (!reason) return null; const messages: string[] = []; if (reason.includes('signature')) messages.push('签名校验失败,旧版本仍保留。'); if (reason.includes('artifact_invalid')) messages.push('插件包校验失败,旧版本仍保留。'); if (reason.includes('yanked')) messages.push('此版本已撤回,旧版本仍保留。'); if (reason.includes('not_ready')) messages.push('此版本尚未就绪,旧版本仍保留。'); if (reason.includes('incompatible')) messages.push('当前 MakeLore 版本不兼容,旧版本仍保留。'); if (reason.includes('runtime_suspended')) messages.push('插件运行已暂停,设备版本未替换。'); if (reason.includes('backend_unavailable')) messages.push('Marketplace 服务暂不可用,设备版本未替换。'); if (reason.includes('library_required')) messages.push('请先在账号插件库中获取此插件。'); if (messages.length === 0) messages.push('当前版本暂不可用,旧版本仍保留。'); return messages.join(' '); } function actionErrorText(error?: string | null): string | null { if (!error) return null; if (error.includes('plugin_artifact_invalid')) return '插件签名或包校验失败,设备上此前可用版本仍保留。'; if (error.includes('plugin_signature_invalid')) return '插件签名校验失败,设备上此前可用版本仍保留。'; if (error.includes('plugin_release_yanked')) return '此版本已撤回;不会替换此前可用版本。'; if (error.includes('plugin_release_not_ready')) return '版本尚未就绪;不会替换此前可用版本。'; if (error.includes('plugin_incompatible_client')) return '当前 MakeLore 版本不兼容;不会替换此前可用版本。'; if (error.includes('plugin_runtime_suspended')) return '插件运行已暂停;不会替换此前可用版本。'; if (error.includes('plugin_backend_unavailable')) return 'Marketplace 服务暂不可用;不会替换此前可用版本。'; if (error.includes('plugin_library_required')) return '请先在账号插件库中获取此插件。'; return error; } export type MyPluginsViewProps = { library: MarketplaceLibrarySnapshot | null; installations: Record; state: 'idle' | 'loading' | 'ready' | 'error'; error?: string | null; pending: Record; onRefresh(): void | Promise; onInstall(pluginId: string): void | Promise; onInstallBeta(pluginId: string): void | Promise; onUpdate(pluginId: string): void | Promise; onUninstall(pluginId: string): void | Promise; onRemove(pluginId: string): void | Promise; onReacquire(pluginId: string): void | Promise; }; export function MyPluginsView(props: MyPluginsViewProps) { const visibleError = actionErrorText(props.error); return (

我的插件

账号插件库与本机下载分开管理。下载不会自动启用到项目,也不会分配给伙伴。

{props.library?.stale ?

正在显示上次可信的插件库;服务恢复前,在线计量或托管能力保持不可用。

: null} {props.state === 'loading' && !props.library ?

正在读取我的插件…

: null} {props.state === 'error' && !props.library ?

无法读取我的插件

{props.error ?? '请稍后重试。'}

: null} {visibleError && props.library ?

{visibleError}

: null} {props.library && props.library.items.length === 0 ?

账号插件库还是空的

前往插件中心免费获取需要的插件。

: null}
{props.library?.items.map((plugin) => { const installed = props.installations[plugin.pluginId]; const hasDevicePackage = Boolean(installed?.version); const removed = plugin.removedAt !== null; const suspended = plugin.runtimeStatus === 'suspended'; const retired = plugin.catalogStatus === 'retired'; const installedChannel = hasDevicePackage ? installed?.channel ?? 'stable' : 'stable'; const channelVersion = installedChannel === 'beta' ? plugin.betaVersion : plugin.stableVersion; const updateAvailable = Boolean(hasDevicePackage && channelVersion && installed?.version !== channelVersion); const betaChannelUnavailable = Boolean(hasDevicePackage && installedChannel === 'beta' && !plugin.betaVersion); const busy = Object.keys(props.pending).some((key) => key.endsWith(`:${plugin.pluginId}`)); const failure = failureText(installed?.reason); return

{plugin.title}

{plugin.acquisition === 'system_included' ? 系统内置 : removed ? 已移除 : 已获取}

{plugin.summary}

稳定版 {plugin.stableVersion ?? '不可用'}

{plugin.betaVersion ?

Beta 版 {plugin.betaVersion}

: null}{hasDevicePackage ? <>

设备版本 {installed?.version}

当前频道:{installedChannel === 'beta' ? 'Beta' : '稳定'}

:

尚未下载到设备

}
{suspended ?

运行已暂停

: null}{retired ?

{removed ? '已退役,移除后不可重新获取' : '已退役;现有账号插件库仍可继续使用受支持版本'}

: null}{betaChannelUnavailable ?

当前 Beta 频道暂无可用版本;不会静默切回稳定版。

: null}{failure ?

{failure}

: null}
{removed ? : !hasDevicePackage ? : updateAvailable ? : 设备版本已是最新} {!removed && plugin.acquisition !== 'system_included' && plugin.betaVersion && installedChannel !== 'beta' ? : null} {!removed && plugin.acquisition !== 'system_included' ? : null} {hasDevicePackage ? : null}
; })}
); } export function MyPlugins() { const user = useAuthStore((state) => state.user); const accountKey = user?.userId ?? user?.username ?? null; const library = usePluginMarketplaceStore((state) => state.library); const installations = usePluginMarketplaceStore((state) => state.installations); const state = usePluginMarketplaceStore((value) => value.libraryState); const error = usePluginMarketplaceStore((value) => value.libraryError); const pending = usePluginMarketplaceStore((value) => value.pending); useEffect(() => { pluginMarketplaceStore.getState().activateAccount(accountKey); if (accountKey) void pluginMarketplaceStore.getState().loadLibrary().catch(() => undefined); }, [accountKey]); const safe = (operation: Promise) => operation.catch((reason) => { toast.error(reason instanceof Error ? reason.message : String(reason)); }); const store = pluginMarketplaceStore.getState; return safe(store().loadLibrary())} onInstall={(id) => safe(store().install(id))} onInstallBeta={(id) => safe(store().installBeta(id))} onUpdate={(id) => safe(store().update(id))} onUninstall={(id) => safe(store().uninstall(id))} onRemove={(id) => safe(store().remove(id))} onReacquire={(id) => safe(store().acquire(id))} />; }