diff --git a/src/components/plugins/PluginSettingsTab.tsx b/src/components/plugins/PluginSettingsTab.tsx index a285ed7c..a918a879 100644 --- a/src/components/plugins/PluginSettingsTab.tsx +++ b/src/components/plugins/PluginSettingsTab.tsx @@ -1,9 +1,11 @@ import { useState } from 'react'; -import { Trash2, RefreshCw, GitBranch, Loader2, ServerCrash, ChevronRight, ShieldAlert, ExternalLink, BookOpen } from 'lucide-react'; +import { Trash2, RefreshCw, GitBranch, Loader2, ServerCrash, ChevronRight, ShieldAlert, ExternalLink, BookOpen, Download, BarChart3 } from 'lucide-react'; import { usePlugins } from '../../contexts/PluginsContext'; import PluginIcon from './PluginIcon'; import type { Plugin } from '../../contexts/PluginsContext'; +const STARTER_PLUGIN_URL = 'https://github.com/cloudcli-ai/cloudcli-plugin-starter'; + /* ─── Toggle Switch ─────────────────────────────────────────────────────── */ function ToggleSwitch({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) { return ( @@ -186,6 +188,49 @@ function PluginCard({ ); } +/* ─── Starter Plugin Card ───────────────────────────────────────────────── */ +function StarterPluginCard({ onInstall, installing }: { onInstall: () => void; installing: boolean }) { + return ( +
+
+
+
+
+
+ +
+
+
+ + Project Stats + + + starter + +
+

+ File counts, lines of code, file-type breakdown, and recent activity for your project. +

+
+
+ +
+
+
+ ); +} + /* ─── Empty State ───────────────────────────────────────────────────────── */ function EmptyState() { return ( @@ -212,6 +257,7 @@ export default function PluginSettingsTab() { const [gitUrl, setGitUrl] = useState(''); const [installing, setInstalling] = useState(false); + const [installingStarter, setInstallingStarter] = useState(false); const [installError, setInstallError] = useState(null); const [confirmUninstall, setConfirmUninstall] = useState(null); const [updatingPlugin, setUpdatingPlugin] = useState(null); @@ -240,6 +286,16 @@ export default function PluginSettingsTab() { setInstalling(false); }; + const handleInstallStarter = async () => { + setInstallingStarter(true); + setInstallError(null); + const result = await installPlugin(STARTER_PLUGIN_URL); + if (!result.success) { + setInstallError(result.error || 'Installation failed'); + } + setInstallingStarter(false); + }; + const handleUninstall = async (name: string) => { if (confirmUninstall !== name) { setConfirmUninstall(name); @@ -249,6 +305,8 @@ export default function PluginSettingsTab() { setConfirmUninstall(null); }; + const hasStarterInstalled = plugins.some((p) => p.name === 'project-stats'); + return (
{/* Header */} @@ -258,11 +316,14 @@ export default function PluginSettingsTab() { Plugins

- Extend the interface with custom tabs. Drop a folder in{' '} - - ~/.claude-code-ui/plugins/ + Extend the interface with custom plugins. Install from{' '} + + git {' '} - or install from git. + or drop a folder in{' '} + + ~/.claude-code-ui/plugins/ +

{!loading && plugins.length > 0 && ( @@ -272,86 +333,47 @@ export default function PluginSettingsTab() { )}
- {/* Install from Git */} -
-
- - - Install from git - -
- -
- - $ - - { - setGitUrl(e.target.value); - setInstallError(null); - }} - placeholder="git clone https://github.com/user/my-plugin" - className="flex-1 px-1.5 py-2.5 text-xs font-mono bg-transparent text-foreground placeholder:text-muted-foreground/40 focus:outline-none" - onKeyDown={(e) => { - if (e.key === 'Enter') void handleInstall(); - }} - /> - -
- - {installError && ( -

{installError}

- )} - -

- - - Plugins run with full access to the host page. Only install plugins - whose source code you have reviewed or from authors you trust. - -

+ {/* Install from Git — compact */} +
+ + + + { + setGitUrl(e.target.value); + setInstallError(null); + }} + placeholder="https://github.com/user/my-plugin" + className="flex-1 px-2 py-2 text-xs font-mono bg-transparent text-foreground placeholder:text-muted-foreground/40 focus:outline-none" + onKeyDown={(e) => { + if (e.key === 'Enter') void handleInstall(); + }} + /> +
- {/* Build your own */} -
- -
-

- Build your own plugin or start from an example. -

-
-
- - Starter plugin - - | - - Docs - -
-
+ {installError && ( +

{installError}

+ )} + +

+ + + Only install plugins whose source code you have reviewed or from authors you trust. + +

{/* Plugin List */}
@@ -378,6 +400,40 @@ export default function PluginSettingsTab() { /> )) )} + + {/* Starter plugin suggestion */} + {!loading && !hasStarterInstalled && ( + + )} +
+ + {/* Build your own */} +
+
+ + + Build your own plugin + +
+
+ + Starter + + · + + Docs + +
);