import PluginInstalledComponent, { PluginInstalledComponentRef, FilterOptions, FilterType, } from '@/app/home/plugins/components/plugin-installed/PluginInstalledComponent'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import PluginDetailContent from './PluginDetailContent'; import styles from './plugins.module.css'; import { Button } from '@/components/ui/button'; import { Power, Code, Copy, Check, Bug, Unlink } from 'lucide-react'; import { copyToClipboard } from '@/app/utils/clipboard'; import { Popover, PopoverContent, PopoverTrigger, } from '@/components/ui/popover'; import { Alert, AlertTitle, AlertDescription } from '@/components/ui/alert'; import { Skeleton } from '@/components/ui/skeleton'; import { Input } from '@/components/ui/input'; import React, { useState, useRef, useEffect } from 'react'; import { useSearchParams } from 'react-router-dom'; import { httpClient } from '@/app/infra/http/HttpClient'; import { toast } from 'sonner'; import { useTranslation } from 'react-i18next'; import { ApiRespPluginSystemStatus } from '@/app/infra/entities/api'; import { useSidebarData } from '@/app/home/components/home-sidebar/SidebarDataContext'; import { PluginInstallTaskQueue, usePluginInstallTasks, } from '@/app/home/plugins/components/plugin-install-task'; export default function PluginConfigPage() { const [searchParams] = useSearchParams(); const detailId = searchParams.get('id'); if (detailId) { return ; } return ; } function PluginListView() { const { t } = useTranslation(); const { refreshPlugins, extensionsGroupByType: groupByType, setExtensionsGroupByType: setGroupByType, } = useSidebarData(); const { registerOnTaskComplete, unregisterOnTaskComplete } = usePluginInstallTasks(); const [pluginSystemStatus, setPluginSystemStatus] = useState(null); const [statusLoading, setStatusLoading] = useState(true); const [debugInfo, setDebugInfo] = useState<{ debug_url: string; plugin_debug_key: string; } | null>(null); const [debugPopoverOpen, setDebugPopoverOpen] = useState(false); const [copiedDebugUrl, setCopiedDebugUrl] = useState(false); const [copiedDebugKey, setCopiedDebugKey] = useState(false); const [filterType, setFilterType] = useState('all'); const pluginInstalledRef = useRef(null); useEffect(() => { const fetchPluginSystemStatus = async () => { try { setStatusLoading(true); const status = await httpClient.getPluginSystemStatus(); setPluginSystemStatus(status); } catch (error) { console.error('Failed to fetch plugin system status:', error); toast.error(t('plugins.failedToGetStatus')); } finally { setStatusLoading(false); } }; void fetchPluginSystemStatus(); }, [t]); useEffect(() => { const onComplete = (_taskId: number, success: boolean, error?: string) => { if (success) { toast.success(t('plugins.installSuccess')); pluginInstalledRef.current?.refreshPluginList(); refreshPlugins(); } else { toast.error(error || t('plugins.installFailed')); } }; registerOnTaskComplete(onComplete); return () => { unregisterOnTaskComplete(onComplete); }; }, [registerOnTaskComplete, unregisterOnTaskComplete, refreshPlugins, t]); const handleShowDebugInfo = async () => { try { const info = await httpClient.getPluginDebugInfo(); setDebugInfo(info); setDebugPopoverOpen(true); } catch (error) { console.error('Failed to fetch debug info:', error); toast.error(t('plugins.failedToGetDebugInfo')); } }; const handleCopyDebugInfo = (text: string, type: 'url' | 'key') => { copyToClipboard(text).catch(() => {}); if (type === 'url') { setCopiedDebugUrl(true); setTimeout(() => setCopiedDebugUrl(false), 2000); } else { setCopiedDebugKey(true); setTimeout(() => setCopiedDebugKey(false), 2000); } }; const renderPluginDisabledState = () => (
{t('plugins.systemDisabled')} {t('plugins.systemDisabledDesc')}
); const renderPluginConnectionErrorState = () => (
{t('plugins.connectionError')} {t('plugins.connectionErrorDesc')}
); const renderLoadingState = () => (
); if (statusLoading) { return renderLoadingState(); } if (!pluginSystemStatus?.is_enable) { return renderPluginDisabledState(); } if (!pluginSystemStatus?.is_connected) { return renderPluginConnectionErrorState(); } return (
setFilterType(value as FilterType)} > {FilterOptions.map((option) => ( {option.icon && } {t(option.labelKey)} ))}

{t('plugins.debugInfoTitle')}

{!debugInfo?.plugin_debug_key && (

{t('plugins.debugKeyDisabled')}

)}
); }