11"use client" ;
22
3+ import { useEffect , useState } from "react" ;
4+ import { useAtom } from "jotai" ;
5+ import { directoryHandleAtom } from "../lib/store" ;
6+ import { useTranslations } from "@/components/LocaleProvider" ;
7+ import { useTransitionRouter } from "next-view-transitions" ;
8+ import { slideInOut } from "../lib/publicCutscene" ;
9+ import { motion , AnimatePresence } from "framer-motion" ;
310import FolderPicker from "../components/FolderPicker" ;
411import ScanControls from "../components/ScanControls" ;
512import ResultDisplay from "../components/ResultDisplay" ;
613import ThemeToggle from "../components/ThemeToggle" ;
714import VersionManager from "../components/VersionManager" ;
815import SettingsButton from "../components/SettingsModal" ;
9- import { useAtom } from "jotai" ;
10- import { directoryHandleAtom } from "../lib/store" ;
11- import { useTranslations } from "@/components/LocaleProvider" ;
12- import { useTransitionRouter } from "next-view-transitions" ;
13- import { slideInOut } from "../lib/publicCutscene" ;
16+ import BrowserCompatCheck from "../components/BrowserCompatCheck" ;
17+
1418export default function Home ( ) {
1519 const [ directoryHandle ] = useAtom ( directoryHandleAtom ) ;
1620 const { t } = useTranslations ( ) ;
1721 const router = useTransitionRouter ( ) ;
22+ const [ mounted , setMounted ] = useState ( false ) ;
23+ const [ showVersionModal , setShowVersionModal ] = useState ( false ) ;
24+
25+ // 确保组件在客户端挂载后才渲染,避免水合错误
26+ useEffect ( ( ) => {
27+ setMounted ( true ) ;
28+ } , [ ] ) ;
1829
1930 // 跳转到统计页面
2031 const handleGoToStatistics = ( ) => {
@@ -23,61 +34,175 @@ export default function Home() {
2334 } ) ;
2435 } ;
2536
37+ if ( ! mounted ) return null ;
38+
2639 return (
27- < div className = "min-h-screen bg-gray-50 dark:bg-gray-900 py-8 transition-colors duration-300" >
28- < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" >
29- < header className = "mb-8 flex justify-between items-center" >
30- < div >
31- < h1 className = "text-3xl font-bold text-gray-900 dark:text-white" >
32- { t ( "app.title" ) }
33- </ h1 >
34- < p className = "mt-2 text-lg text-gray-600 dark:text-gray-300" >
35- { t ( "app.description" ) }
36- </ p >
37- </ div >
38- < div className = "flex items-center space-x-3" >
39- { directoryHandle && (
40- < >
41- < VersionManager />
42- < button
43- onClick = { handleGoToStatistics }
44- className = "px-3 py-2 bg-teal-600 text-white rounded-md hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-teal-500 focus:ring-offset-2 transition-colors duration-300 flex items-center space-x-1"
45- title = "项目统计"
40+ < div className = "min-h-screen bg-gray-100 dark:bg-gray-900 transition-colors duration-300 flex flex-col" >
41+ { /* 浏览器兼容性检查组件 */ }
42+ < BrowserCompatCheck />
43+
44+ { /* Mac风格顶部导航栏 */ }
45+ < header className = "bg-white/80 dark:bg-gray-800/80 backdrop-blur-md border-b border-gray-200 dark:border-gray-700 transition-colors duration-300 sticky top-0 z-10" >
46+ < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-3" >
47+ < div className = "flex justify-between items-center" >
48+ { /* 左侧标题和Logo */ }
49+ < div className = "flex items-center" >
50+ < div className = "flex-shrink-0" >
51+ < svg
52+ xmlns = "http://www.w3.org/2000/svg"
53+ className = "h-8 w-8 text-blue-500"
54+ fill = "none"
55+ viewBox = "0 0 24 24"
56+ stroke = "currentColor"
4657 >
47- < svg
48- xmlns = "http://www.w3.org/2000/svg"
49- className = "h-5 w-5"
50- viewBox = "0 0 20 20"
51- fill = "currentColor"
58+ < path
59+ strokeLinecap = "round"
60+ strokeLinejoin = "round"
61+ strokeWidth = { 2 }
62+ d = "M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
63+ />
64+ </ svg >
65+ </ div >
66+ < h1 className = "ml-2 text-xl font-semibold text-gray-900 dark:text-white" >
67+ Folda-Scan
68+ </ h1 >
69+ </ div >
70+
71+ { /* 右侧工具区 */ }
72+ < div className = "flex items-center space-x-4" >
73+ < ThemeToggle />
74+ < SettingsButton />
75+
76+ { directoryHandle && (
77+ < >
78+ < button
79+ onClick = { handleGoToStatistics }
80+ className = "text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium flex items-center"
81+ >
82+ < svg
83+ xmlns = "http://www.w3.org/2000/svg"
84+ className = "h-5 w-5 mr-1"
85+ fill = "none"
86+ viewBox = "0 0 24 24"
87+ stroke = "currentColor"
88+ >
89+ < path
90+ strokeLinecap = "round"
91+ strokeLinejoin = "round"
92+ strokeWidth = { 2 }
93+ d = "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
94+ />
95+ </ svg >
96+ { t ( "nav.statistics" ) }
97+ </ button >
98+
99+ < button
100+ onClick = { ( ) => setShowVersionModal ( true ) }
101+ className = "px-4 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition-colors dark:bg-purple-700 dark:hover:bg-purple-800"
52102 >
53- < path d = "M2 10a8 8 0 018-8v8h8a8 8 0 11-16 0z" />
54- < path d = "M12 2.252A8.014 8.014 0 0117.748 8H12V2.252z" />
55- </ svg >
56- < span > 统计</ span >
57- </ button >
58- </ >
59- ) }
60- < SettingsButton />
61- < ThemeToggle />
103+ { t ( "versionManager.title" ) }
104+ </ button >
105+ </ >
106+ ) }
107+ </ div >
62108 </ div >
63- </ header >
64-
65- < main className = "space-y-6" >
66- < section className = "bg-white dark:bg-gray-800 p-6 rounded-lg shadow transition-colors duration-300" >
67- < h2 className = "text-xl font-semibold mb-4 text-gray-900 dark:text-white" >
68- { t ( "folderPicker.selectFolder" ) }
69- </ h2 >
70- < FolderPicker />
71- < ScanControls />
72- </ section >
73-
74- < ResultDisplay />
75- </ main >
76-
77- < footer className = "mt-12 text-center text-gray-500 dark:text-gray-400 text-sm" >
78- < p > { t ( "about.copyright" ) } </ p >
79- </ footer >
80- </ div >
109+ </ div >
110+ </ header >
111+
112+ < AnimatePresence mode = "wait" >
113+ { ! directoryHandle ? (
114+ /* 全屏文件夹选择界面 */
115+ < motion . div
116+ key = "folder-picker"
117+ initial = { { opacity : 0 } }
118+ animate = { { opacity : 1 } }
119+ exit = { { opacity : 0 } }
120+ className = "flex-1 flex items-center justify-center p-4"
121+ >
122+ < div className = "max-w-md w-full mx-auto" >
123+ < div className = "bg-white dark:bg-gray-800 rounded-2xl shadow-xl overflow-hidden transition-colors duration-300" >
124+ < div className = "p-8" >
125+ < div className = "text-center mb-8" >
126+ < div className = "inline-block p-4 bg-blue-50 dark:bg-blue-900/30 rounded-full mb-4" >
127+ < svg
128+ xmlns = "http://www.w3.org/2000/svg"
129+ className = "h-12 w-12 text-blue-500"
130+ fill = "none"
131+ viewBox = "0 0 24 24"
132+ stroke = "currentColor"
133+ >
134+ < path
135+ strokeLinecap = "round"
136+ strokeLinejoin = "round"
137+ strokeWidth = { 2 }
138+ d = "M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
139+ />
140+ </ svg >
141+ </ div >
142+ < h2 className = "text-2xl font-semibold text-gray-900 dark:text-white" >
143+ { t ( "folderPicker.welcomeTitle" ) }
144+ </ h2 >
145+ < p className = "mt-2 text-gray-600 dark:text-gray-300" >
146+ { t ( "folderPicker.welcomeDescription" ) }
147+ </ p >
148+ </ div >
149+
150+ < FolderPicker />
151+
152+ < div className = "mt-6 text-center text-sm text-gray-500 dark:text-gray-400" >
153+ < p > { t ( "folderPicker.privacyNote" ) } </ p >
154+ </ div >
155+ </ div >
156+ </ div >
157+ </ div >
158+ </ motion . div >
159+ ) : (
160+ /* 主应用界面 */
161+ < motion . main
162+ key = "main-content"
163+ initial = { { opacity : 0 , y : 20 } }
164+ animate = { { opacity : 1 , y : 0 } }
165+ exit = { { opacity : 0 } }
166+ className = "flex-1 max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-6"
167+ >
168+ < div className = "space-y-6" >
169+ < section className = "bg-white dark:bg-gray-800 rounded-xl shadow-md overflow-hidden transition-colors duration-300" >
170+ < div className = "p-6" >
171+ < div className = "flex items-center justify-between mb-4" >
172+ < FolderPicker />
173+ </ div >
174+ < ScanControls />
175+ </ div >
176+ </ section >
177+
178+ < ResultDisplay />
179+ </ div >
180+ </ motion . main >
181+ ) }
182+ </ AnimatePresence >
183+
184+ < footer className = "mt-auto py-4 text-center text-gray-500 dark:text-gray-400 text-sm" >
185+ < p > { t ( "about.copyright" ) } </ p >
186+ </ footer >
187+
188+ { directoryHandle && showVersionModal && (
189+ < div
190+ className = "fixed inset-0 z-[9999]"
191+ style = { {
192+ position : "fixed" ,
193+ top : 0 ,
194+ left : 0 ,
195+ right : 0 ,
196+ bottom : 0 ,
197+ display : "flex" ,
198+ alignItems : "center" ,
199+ justifyContent : "center" ,
200+ backgroundColor : "rgba(0, 0, 0, 0.5)" ,
201+ } }
202+ >
203+ < VersionManager onClose = { ( ) => setShowVersionModal ( false ) } />
204+ </ div >
205+ ) }
81206 </ div >
82207 ) ;
83208}
0 commit comments