import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; import { Archive, CheckCircle2, Loader2, Package } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { httpClient } from '@/app/infra/http/HttpClient'; import { extractI18nObject } from '@/i18n/I18nProvider'; import { usePluginInstallTasks } from '@/app/home/plugins/components/plugin-install-task'; import PluginComponentList from '@/app/home/plugins/components/plugin-installed/PluginComponentList'; type PluginLocalPreview = Awaited< ReturnType >; interface PluginLocalPreviewPanelProps { file: File; onInstallStarted?: () => void; onCancel?: () => void; } function formatFileSize(bytes: number): string { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i]; } export default function PluginLocalPreviewPanel({ file, onInstallStarted, onCancel, }: PluginLocalPreviewPanelProps) { const { t } = useTranslation(); const { addTask, setSelectedTaskId } = usePluginInstallTasks(); const [preview, setPreview] = useState(null); const [previewing, setPreviewing] = useState(false); const [installing, setInstalling] = useState(false); const [errorMessage, setErrorMessage] = useState(null); const loadPreview = useCallback(async () => { setPreviewing(true); setPreview(null); setErrorMessage(null); try { const result = await httpClient.previewPluginInstallFromLocal(file); setPreview(result); } catch (error: unknown) { const message = error instanceof Error ? error.message : typeof error === 'object' && error && 'msg' in error ? String((error as { msg?: string }).msg || '') : String(error); setErrorMessage(message || t('plugins.localPreview.failed')); } finally { setPreviewing(false); } }, [file, t]); useEffect(() => { void loadPreview(); }, [loadPreview]); async function handleInstall() { setInstalling(true); setErrorMessage(null); try { const resp = await httpClient.installPluginFromLocal(file); const taskId = resp.task_id; const taskKey = `local-${taskId}`; const pluginName = preview?.metadata.label && extractI18nObject(preview.metadata.label) ? extractI18nObject(preview.metadata.label) : preview?.metadata.name || file.name; addTask({ taskId, pluginName, source: 'local', extensionType: 'plugin', fileSize: file.size, }); setSelectedTaskId(taskKey); toast.success(t('plugins.installSuccess')); onInstallStarted?.(); } catch (error: unknown) { const message = error instanceof Error ? error.message : typeof error === 'object' && error && 'msg' in error ? String((error as { msg?: string }).msg || '') : String(error); setErrorMessage(message || t('plugins.installFailed')); } finally { setInstalling(false); } } const metadata = preview?.metadata; const label = metadata?.label ? extractI18nObject(metadata.label) : ''; const description = metadata?.description ? extractI18nObject(metadata.description) : ''; const componentCounts = preview?.component_counts || {}; return (
{previewing ? ( ) : ( )}
{previewing ? t('plugins.localPreview.unpacking') : t('plugins.localPreview.unpackComplete')}
{file.name} ยท {formatFileSize(file.size)}
{preview && (
{t('plugins.localPreview.pluginInfo')}
{t('plugins.localPreview.name')} {label || metadata?.name || '-'}
{t('plugins.localPreview.author')} {metadata?.author || '-'}
{t('plugins.localPreview.version')} {metadata?.version || '-'}
{description && (

{description}

)}
)} {preview && (
{t('plugins.localPreview.ready')}
)} {errorMessage && (
{errorMessage}
)}
{onCancel && ( )}
); }