import { useState } from "react"; import { useTranslation } from "react-i18next"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Badge } from "@/components/ui/badge"; import { Switch } from "@/components/ui/switch"; import { Trash2, ExternalLink, Plus, Loader2 } from "lucide-react"; import { toast } from "sonner"; import { settingsApi } from "@/lib/api"; import { FullScreenPanel } from "@/components/common/FullScreenPanel"; import { useTemplateRepos, useAddTemplateRepo, useRemoveTemplateRepo, useToggleTemplateRepo, } from "@/lib/query/template"; interface RepoManagerProps { onClose: () => void; } export function RepoManager({ onClose }: RepoManagerProps) { const { t } = useTranslation(); const [repoUrl, setRepoUrl] = useState(""); const [branch, setBranch] = useState(""); const [error, setError] = useState(""); const { data: repos = [], isLoading } = useTemplateRepos(); const addRepoMutation = useAddTemplateRepo(); const removeRepoMutation = useRemoveTemplateRepo(); const toggleRepoMutation = useToggleTemplateRepo(); const parseRepoUrl = ( url: string, ): { owner: string; name: string } | null => { let cleaned = url.trim(); cleaned = cleaned.replace(/^https?:\/\/github\.com\//, ""); cleaned = cleaned.replace(/\.git$/, ""); const parts = cleaned.split("/"); if (parts.length === 2 && parts[0] && parts[1]) { return { owner: parts[0], name: parts[1] }; } return null; }; const handleAdd = async () => { setError(""); const parsed = parseRepoUrl(repoUrl); if (!parsed) { setError( t("templates.repo.invalidUrl", { defaultValue: "仓库地址格式不正确", }), ); return; } try { await addRepoMutation.mutateAsync({ owner: parsed.owner, name: parsed.name, branch: branch || "main", }); toast.success( t("templates.repo.addSuccess", { owner: parsed.owner, name: parsed.name, defaultValue: `已添加仓库 ${parsed.owner}/${parsed.name}`, }), ); setRepoUrl(""); setBranch(""); } catch (e) { const errorMessage = e instanceof Error ? e.message : String(e); setError( t("templates.repo.addFailed", { defaultValue: "添加仓库失败", }), ); toast.error( t("templates.repo.addFailed", { defaultValue: "添加仓库失败" }), { description: errorMessage, duration: 8000, }, ); } }; const handleRemove = async (id: number, owner: string, name: string) => { try { await removeRepoMutation.mutateAsync(id); toast.success( t("templates.repo.removeSuccess", { owner, name, defaultValue: `已移除仓库 ${owner}/${name}`, }), ); } catch (e) { const errorMessage = e instanceof Error ? e.message : String(e); toast.error( t("templates.repo.removeFailed", { defaultValue: "移除仓库失败" }), { description: errorMessage, duration: 8000, }, ); } }; const handleToggle = async (id: number, enabled: boolean) => { try { await toggleRepoMutation.mutateAsync({ id, enabled }); toast.success( enabled ? t("templates.repo.enableSuccess", { defaultValue: "已启用仓库" }) : t("templates.repo.disableSuccess", { defaultValue: "已禁用仓库" }), ); } catch (e) { const errorMessage = e instanceof Error ? e.message : String(e); toast.error( t("templates.repo.toggleFailed", { defaultValue: "切换仓库状态失败", }), { description: errorMessage, duration: 8000, }, ); } }; const handleOpenRepo = async (owner: string, name: string) => { try { await settingsApi.openExternal(`https://github.com/${owner}/${name}`); } catch (error) { console.error("Failed to open URL:", error); } }; return ( {/* 添加仓库表单 */}

{t("templates.repo.addTitle", { defaultValue: "添加模板仓库" })}

setRepoUrl(e.target.value)} className="mt-2" />
setBranch(e.target.value)} className="mt-2" />
{error && (

{error}

)}
{/* 仓库列表 */}

{t("templates.repo.list", { defaultValue: "仓库列表" })}

{isLoading ? (
) : repos.length === 0 ? (

{t("templates.repo.empty", { defaultValue: "暂无仓库" })}

) : (
{repos.map((repo) => (
repo.id !== null && handleToggle(repo.id, checked) } disabled={toggleRepoMutation.isPending || repo.id === null} />
{repo.owner}/{repo.name}
{t("templates.repo.branch", { defaultValue: "分支" })}:{" "} {repo.branch} {repo.enabled ? t("templates.repo.enabled", { defaultValue: "已启用", }) : t("templates.repo.disabled", { defaultValue: "已禁用", })}
))}
)}
); }