diff --git a/package.json b/package.json index adb3764281..050d52de02 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "electron-window-state": "^5.0.3", "epub": "patch:epub@npm%3A1.3.0#~/.yarn/patches/epub-npm-1.3.0-8325494ffe.patch", "fast-xml-parser": "^5.2.0", + "framer-motion": "^12.17.0", "franc-min": "^6.2.0", "fs-extra": "^11.2.0", "jsdom": "^26.0.0", diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index a327cef59d..94d3a564be 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -12,7 +12,6 @@ import { NotificationProvider } from './context/NotificationProvider' import StyleSheetManager from './context/StyleSheetManager' import { ThemeProvider } from './context/ThemeProvider' import NavigationHandler from './handler/NavigationHandler' -import MainSidebar from './pages/home/MainSidebar/MainSidebar' import Routes from './Routes' function App(): React.ReactElement { @@ -27,7 +26,6 @@ function App(): React.ReactElement { - diff --git a/src/renderer/src/Routes.tsx b/src/renderer/src/Routes.tsx index 410ce8d036..805cee726b 100644 --- a/src/renderer/src/Routes.tsx +++ b/src/renderer/src/Routes.tsx @@ -1,4 +1,7 @@ +import { AnimatePresence, motion } from 'framer-motion' +import { useEffect, useState } from 'react' import { Route, Routes, useLocation } from 'react-router-dom' +import styled from 'styled-components' import AgentsPage from './pages/agents/AgentsPage' import AppsPage from './pages/apps/AppsPage' @@ -10,27 +13,93 @@ import PaintingsRoutePage from './pages/paintings/PaintingsRoutePage' import SettingsPage from './pages/settings/SettingsPage' import TranslatePage from './pages/translate/TranslatePage' +const WILDCARD_ROUTES = ['/settings', '/paintings', '/mcp-servers'] + const RouteContainer = () => { const location = useLocation() const isHomePage = location.pathname === '/' + const [isReady, setIsReady] = useState(false) + + // 获取当前路径的主路由部分 + const mainPath = WILDCARD_ROUTES.find((route) => location.pathname.startsWith(route)) + + // 使用主路由作为 key,这样同一主路由下的切换不会触发动画 + const animationKey = mainPath || location.pathname + + // 路由变化时重置状态 + useEffect(() => { + setIsReady(false) + // 给一个很短的延迟,确保组件已经渲染 + const timer = setTimeout(() => setIsReady(true), 300) + return () => clearTimeout(timer) + }, [location.pathname]) return ( -
- -
- - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - -
-
+ + + + {!isHomePage && ( + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + )} + + ) } +const Container = styled.div` + position: relative; + width: 100%; + height: 100%; + min-width: 0; + overflow: hidden; +` + +const HomePageWrapper = styled(HomePage)` + display: flex; + width: 100%; + height: 100%; +` + +const PageContainer = styled(motion.div)` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--color-base); + display: flex; + width: 100%; + height: 100%; + z-index: 10; +` + +const pageTransition = { + type: 'tween', + duration: 0.25, + ease: 'easeInOut' +} + +const pageVariants = { + initial: { y: '100%' }, + animate: { y: 0 }, + exit: { y: '100%' } +} + export default RouteContainer diff --git a/src/renderer/src/components/app/Navbar.tsx b/src/renderer/src/components/app/Navbar.tsx index 384622c96f..d78b347194 100644 --- a/src/renderer/src/components/app/Navbar.tsx +++ b/src/renderer/src/components/app/Navbar.tsx @@ -5,7 +5,7 @@ import { CircleArrowLeft, X } from 'lucide-react' import type { FC, PropsWithChildren } from 'react' import type { HTMLAttributes } from 'react' import { useNavigate } from 'react-router-dom' -import styled from 'styled-components' +import styled, { keyframes } from 'styled-components' type Props = PropsWithChildren & HTMLAttributes @@ -38,6 +38,19 @@ export const NavbarMain: FC = ({ children, ...props }) => { ) } +const rotateAnimation = keyframes` + from { + transform: rotate(-180deg); + } + to { + transform: rotate(0); + } +` + +const AnimatedButton = styled(Button)` + animation: ${rotateAnimation} 0.4s ease-out; +` + const MacCloseIcon = () => { const navigate = useNavigate() @@ -45,7 +58,7 @@ const MacCloseIcon = () => { return null } - return