import { Link, useLocation } from 'react-router-dom'; import { Sun, Moon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useConfigStore } from '../../stores/useConfigStore'; function Navbar() { const location = useLocation(); const { t, i18n } = useTranslation(); const { config, saveConfig } = useConfigStore(); const navItems = [ { path: '/', label: t('nav.dashboard') }, { path: '/accounts', label: t('nav.accounts') }, { path: '/api-proxy', label: t('nav.proxy') }, { path: '/settings', label: t('nav.settings') }, ]; const isActive = (path: string) => { if (path === '/') { return location.pathname === '/'; } return location.pathname.startsWith(path); }; const toggleTheme = async (event: React.MouseEvent) => { if (!config) return; const newTheme = config.theme === 'light' ? 'dark' : 'light'; // 如果浏览器支持 View Transition API if ('startViewTransition' in document) { const x = event.clientX; const y = event.clientY; const endRadius = Math.hypot( Math.max(x, window.innerWidth - x), Math.max(y, window.innerHeight - y) ); // @ts-ignore const transition = document.startViewTransition(async () => { await saveConfig({ ...config, theme: newTheme, language: config.language }); }); transition.ready.then(() => { const clipPath = [ `circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)` ]; document.documentElement.animate( { clipPath: clipPath }, { duration: 500, easing: 'ease-in-out', pseudoElement: '::view-transition-new(root)' } ); }); } else { // 降级方案:直接切换 await saveConfig({ ...config, theme: newTheme, language: config.language }); } }; const toggleLanguage = async () => { if (!config) return; const newLang = config.language === 'zh' ? 'en' : 'zh'; await saveConfig({ ...config, language: newLang, theme: config.theme }); i18n.changeLanguage(newLang); }; return ( ); } export default Navbar;