Skip to content

Commit 69bf5e4

Browse files
committed
[no]un
1 parent 9fe060f commit 69bf5e4

4 files changed

Lines changed: 243 additions & 0 deletions

File tree

src/app/page.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import KnowledgeModal from "../components/KnowledgeModal";
2222
import MultiThreadScanAlert from "../components/MultiThreadScanAlert";
2323
import IncrementalScanAlert from "../components/IncrementalScanAlert";
2424
import RssFeed from "../components/RssFeed";
25+
import GitHubDownloader from "../components/GitHubDownloader";
2526

2627
export default function Home() {
2728
const [directoryHandle] = useAtom(directoryHandleAtom);
@@ -429,6 +430,9 @@ export default function Home() {
429430
{/* 文件夹选择器 */}
430431
<FolderPicker />
431432

433+
{/* GitHub仓库下载功能 */}
434+
<GitHubDownloader />
435+
432436
{/* 快速启动区域 - 类似VSCode的欢迎页 */}
433437
<div className="mt-8 pt-6 border-t border-gray-200 dark:border-gray-600">
434438
<h3 className="text-sm font-medium text-gray-900 dark:text-white mb-4 flex items-center">
@@ -560,6 +564,9 @@ export default function Home() {
560564
{/* 增量扫描支持提示 */}
561565
<IncrementalScanAlert />
562566

567+
{/* GitHub仓库下载功能 */}
568+
<GitHubDownloader />
569+
563570
<section className="bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-hidden transition-colors duration-300 border border-gray-200 dark:border-gray-700">
564571
<div className="p-6">
565572
<div className="flex items-center justify-between mb-4">
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
"use client";
2+
3+
import { useState } from "react";
4+
import { motion, AnimatePresence } from "framer-motion";
5+
import { useTranslations } from "./LocaleProvider";
6+
import { IoChevronDown, IoChevronUp } from "react-icons/io5";
7+
import {
8+
FiGithub,
9+
FiDownload,
10+
FiAlertCircle,
11+
FiCheckCircle,
12+
} from "react-icons/fi";
13+
14+
export default function GitHubDownloader() {
15+
const { t } = useTranslations();
16+
const [isExpanded, setIsExpanded] = useState(false);
17+
const [username, setUsername] = useState("");
18+
const [repository, setRepository] = useState("");
19+
const [branch, setBranch] = useState("main");
20+
const [error, setError] = useState<string | null>(null);
21+
const [success, setSuccess] = useState(false);
22+
23+
// 处理展开/折叠
24+
const toggleExpand = () => {
25+
setIsExpanded(!isExpanded);
26+
// 重置状态
27+
if (!isExpanded) {
28+
setError(null);
29+
setSuccess(false);
30+
}
31+
};
32+
33+
// 验证表单
34+
const validateForm = (): boolean => {
35+
if (!username.trim()) {
36+
setError(t("github.invalidRepo"));
37+
return false;
38+
}
39+
if (!repository.trim()) {
40+
setError(t("github.invalidRepo"));
41+
return false;
42+
}
43+
return true;
44+
};
45+
46+
// 下载仓库
47+
const downloadRepository = () => {
48+
if (!validateForm()) return;
49+
50+
try {
51+
const downloadUrl = `https://api.github.com/${username}/${repository}/zip/${branch}`;
52+
53+
// 打开新窗口进行下载
54+
window.open(downloadUrl, "_blank");
55+
56+
// 显示成功消息
57+
setSuccess(true);
58+
59+
// 清除表单
60+
setTimeout(() => {
61+
setSuccess(false);
62+
}, 3000);
63+
} catch (err) {
64+
console.error("打开下载链接出错:", err);
65+
setError(t("github.networkError"));
66+
}
67+
};
68+
69+
// 渲染标题栏
70+
const renderHeader = () => (
71+
<div
72+
className="flex items-center justify-between p-4 bg-white dark:bg-gray-800 border-b-2 border-blue-500 dark:border-blue-600 rounded-t-lg cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-750 transition-colors shadow-sm"
73+
onClick={toggleExpand}
74+
>
75+
<h2 className="text-xl font-bold text-gray-800 dark:text-gray-100 flex items-center">
76+
<FiGithub className="h-6 w-6 mr-2 text-blue-600 dark:text-blue-500" />
77+
<span>{t("github.title")}</span>
78+
</h2>
79+
<div className="flex items-center">
80+
{isExpanded ? (
81+
<IoChevronUp className="h-5 w-5 text-gray-600 dark:text-gray-300" />
82+
) : (
83+
<IoChevronDown className="h-5 w-5 text-gray-600 dark:text-gray-300" />
84+
)}
85+
</div>
86+
</div>
87+
);
88+
89+
return (
90+
<div className="w-full mt-6">
91+
{renderHeader()}
92+
93+
<AnimatePresence>
94+
{isExpanded && (
95+
<motion.div
96+
initial={{ opacity: 0, height: 0 }}
97+
animate={{ opacity: 1, height: "auto" }}
98+
exit={{ opacity: 0, height: 0 }}
99+
transition={{ duration: 0.3 }}
100+
className="overflow-hidden bg-white dark:bg-gray-800 rounded-b-lg shadow-sm border border-t-0 border-gray-200 dark:border-gray-700"
101+
>
102+
<div className="p-4">
103+
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
104+
{t("github.description")}
105+
</p>
106+
107+
<div className="space-y-4">
108+
{/* 用户名/组织名输入 */}
109+
<div>
110+
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
111+
{t("github.username")}
112+
</label>
113+
<input
114+
type="text"
115+
value={username}
116+
onChange={(e) => setUsername(e.target.value)}
117+
placeholder={t("github.placeholder.username")}
118+
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
119+
/>
120+
</div>
121+
122+
{/* 仓库名输入 */}
123+
<div>
124+
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
125+
{t("github.repository")}
126+
</label>
127+
<input
128+
type="text"
129+
value={repository}
130+
onChange={(e) => setRepository(e.target.value)}
131+
placeholder={t("github.placeholder.repository")}
132+
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
133+
/>
134+
</div>
135+
136+
{/* 分支名输入 */}
137+
<div>
138+
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
139+
{t("github.branch")}
140+
<span className="ml-2 text-xs text-gray-500 dark:text-gray-400">
141+
{t("github.defaultBranch")}
142+
</span>
143+
</label>
144+
<input
145+
type="text"
146+
value={branch}
147+
onChange={(e) => setBranch(e.target.value)}
148+
placeholder={t("github.placeholder.branch")}
149+
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
150+
/>
151+
</div>
152+
153+
{/* 下载按钮 */}
154+
<div className="flex justify-end">
155+
<button
156+
onClick={downloadRepository}
157+
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 flex items-center"
158+
>
159+
<FiDownload className="mr-2" />
160+
{t("github.download")}
161+
</button>
162+
</div>
163+
164+
{/* 错误信息 */}
165+
{error && (
166+
<div className="mt-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 dark:border-red-600 p-4 rounded">
167+
<div className="flex">
168+
<FiAlertCircle className="h-5 w-5 text-red-500 dark:text-red-400 mr-2" />
169+
<span className="text-red-700 dark:text-red-400">
170+
{error}
171+
</span>
172+
</div>
173+
</div>
174+
)}
175+
176+
{/* 成功信息 */}
177+
{success && (
178+
<div className="mt-4 bg-green-50 dark:bg-green-900/20 border-l-4 border-green-500 dark:border-green-600 p-4 rounded">
179+
<div className="flex">
180+
<FiCheckCircle className="h-5 w-5 text-green-500 dark:text-green-400 mr-2" />
181+
<span className="text-green-700 dark:text-green-400">
182+
{t("github.success")}
183+
</span>
184+
</div>
185+
</div>
186+
)}
187+
</div>
188+
</div>
189+
</motion.div>
190+
)}
191+
</AnimatePresence>
192+
</div>
193+
);
194+
}

src/messages/en.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@
33
"title": "Folda-Scan",
44
"description": "Local Code Project Scanner & Monitor"
55
},
6+
"github": {
7+
"title": "Download from GitHub",
8+
"description": "Download and analyze repositories directly from GitHub",
9+
"username": "Username/Organization",
10+
"repository": "Repository Name",
11+
"branch": "Branch Name",
12+
"defaultBranch": "Default: main",
13+
"download": "Download",
14+
"downloading": "Downloading...",
15+
"cancel": "Cancel Download",
16+
"success": "Repository downloaded successfully",
17+
"error": "Failed to download repository",
18+
"networkError": "Network error, please try again",
19+
"invalidRepo": "Please enter valid username and repository name",
20+
"progress": "Download progress: {percent}%",
21+
"placeholder": {
22+
"username": "Enter GitHub username or organization",
23+
"repository": "Enter repository name",
24+
"branch": "Enter branch name (default: main)"
25+
}
26+
},
627
"nav": {
728
"statistics": "Statistics"
829
},

src/messages/zh.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,27 @@
33
"title": "Folda-Scan",
44
"description": "代码项目扫描与监控"
55
},
6+
"github": {
7+
"title": "从GitHub下载",
8+
"description": "直接从GitHub下载并分析仓库",
9+
"username": "用户名/组织名",
10+
"repository": "仓库名",
11+
"branch": "分支名",
12+
"defaultBranch": "默认: main",
13+
"download": "下载",
14+
"downloading": "下载中...",
15+
"cancel": "取消下载",
16+
"success": "仓库下载成功",
17+
"error": "仓库下载失败",
18+
"networkError": "网络错误,请重试",
19+
"invalidRepo": "请输入有效的用户名和仓库名",
20+
"progress": "下载进度: {percent}%",
21+
"placeholder": {
22+
"username": "输入GitHub用户名或组织名",
23+
"repository": "输入仓库名",
24+
"branch": "输入分支名 (默认: main)"
25+
}
26+
},
627
"nav": {
728
"statistics": "统计"
829
},

0 commit comments

Comments
 (0)