diff --git a/web/src/components/HeaderBar.js b/web/src/components/HeaderBar.js index f6388959..7bf31748 100644 --- a/web/src/components/HeaderBar.js +++ b/web/src/components/HeaderBar.js @@ -136,7 +136,6 @@ const HeaderBar = () => { }, [i18n]); useEffect(() => { - // 模拟加载用户状态的过程 const timer = setTimeout(() => { setIsLoading(false); }, 500); @@ -152,17 +151,25 @@ const HeaderBar = () => { if (itemKey === 'home') { styleDispatch({ type: 'SET_INNER_PADDING', payload: false }); styleDispatch({ type: 'SET_SIDER', payload: false }); - } else { - styleDispatch({ type: 'SET_INNER_PADDING', payload: true }); - if (!styleState.isMobile) { - styleDispatch({ type: 'SET_SIDER', payload: true }); - } } setMobileMenuOpen(false); }; - const renderNavLinks = (isMobileView = false) => - mainNavLinks.map((link) => { + const renderNavLinks = (isMobileView = false, isLoading = false) => { + if (isLoading) { + const skeletonLinkClasses = isMobileView + ? 'flex items-center gap-1 p-3 w-full rounded-md' + : 'flex items-center gap-1 p-2 rounded-md'; + return Array(4) + .fill(null) + .map((_, index) => ( +
+ +
+ )); + } + + return mainNavLinks.map((link) => { const commonLinkClasses = isMobileView ? 'flex items-center gap-1 p-3 w-full text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors font-semibold' : 'flex items-center gap-1 p-2 text-sm text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors rounded-md font-semibold'; @@ -196,6 +203,7 @@ const HeaderBar = () => { ); }); + }; const renderUserArea = () => { if (isLoading) { @@ -349,7 +357,7 @@ const HeaderBar = () => {
@@ -496,7 +504,7 @@ const HeaderBar = () => { `} > diff --git a/web/src/context/Style/index.js b/web/src/context/Style/index.js index db9b0dd1..cb6d2339 100644 --- a/web/src/context/Style/index.js +++ b/web/src/context/Style/index.js @@ -1,21 +1,34 @@ // contexts/User/index.jsx -import React, { useState, useEffect } from 'react'; -import { isMobile } from '../../helpers/index.js'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useLocation } from 'react-router-dom'; +import { isMobile as getIsMobile } from '../../helpers/index.js'; export const StyleContext = React.createContext({ dispatch: () => null, }); export const StyleProvider = ({ children }) => { + const location = useLocation(); + const initialIsMobile = getIsMobile(); + + const initialPathname = location.pathname; + let initialShowSiderValue = false; + let initialInnerPaddingValue = false; + + if (initialPathname.includes('/console')) { + initialShowSiderValue = !initialIsMobile; + initialInnerPaddingValue = true; + } + const [state, setState] = useState({ - isMobile: isMobile(), - showSider: false, + isMobile: initialIsMobile, + showSider: initialShowSiderValue, siderCollapsed: false, - shouldInnerPadding: false, + shouldInnerPadding: initialInnerPaddingValue, }); - const dispatch = (action) => { + const dispatch = useCallback((action) => { if ('type' in action) { switch (action.type) { case 'TOGGLE_SIDER': @@ -39,64 +52,40 @@ export const StyleProvider = ({ children }) => { } else { setState((prev) => ({ ...prev, ...action })); } - }; + }, []); useEffect(() => { - const updateIsMobile = () => { - const mobileDetected = isMobile(); - dispatch({ type: 'SET_MOBILE', payload: mobileDetected }); - - // If on mobile, we might want to auto-hide the sidebar - if (mobileDetected && state.showSider) { - dispatch({ type: 'SET_SIDER', payload: false }); - } + const updateMobileStatus = () => { + dispatch({ type: 'SET_MOBILE', payload: getIsMobile() }); }; + window.addEventListener('resize', updateMobileStatus); + return () => window.removeEventListener('resize', updateMobileStatus); + }, [dispatch]); - updateIsMobile(); + useEffect(() => { + if (state.isMobile && state.showSider) { + dispatch({ type: 'SET_SIDER', payload: false }); + } + }, [state.isMobile, state.showSider, dispatch]); - const updateShowSider = () => { - // check pathname - const pathname = window.location.pathname; - if ( - pathname === '' || - pathname === '/' || - pathname.includes('/home') || - pathname.includes('/chat') - ) { - dispatch({ type: 'SET_SIDER', payload: false }); - dispatch({ type: 'SET_INNER_PADDING', payload: false }); - } else if (pathname === '/setup') { - dispatch({ type: 'SET_SIDER', payload: false }); - dispatch({ type: 'SET_INNER_PADDING', payload: false }); - } else { - // Only show sidebar on non-mobile devices by default - dispatch({ type: 'SET_SIDER', payload: !isMobile() }); - dispatch({ type: 'SET_INNER_PADDING', payload: true }); - } - }; + useEffect(() => { + const currentPathname = location.pathname; + const currentlyMobile = getIsMobile(); - updateShowSider(); + if (currentPathname === '/console' || currentPathname.startsWith('/console/')) { + dispatch({ type: 'SET_SIDER', payload: !currentlyMobile }); + dispatch({ type: 'SET_INNER_PADDING', payload: true }); + } else { + dispatch({ type: 'SET_SIDER', payload: false }); + dispatch({ type: 'SET_INNER_PADDING', payload: false }); + } + }, [location.pathname, dispatch]); - const updateSiderCollapsed = () => { - const isCollapsed = - localStorage.getItem('default_collapse_sidebar') === 'true'; - dispatch({ type: 'SET_SIDER_COLLAPSED', payload: isCollapsed }); - }; - - updateSiderCollapsed(); - - // Add event listeners to handle window resize - const handleResize = () => { - updateIsMobile(); - }; - - window.addEventListener('resize', handleResize); - - // Cleanup event listener on component unmount - return () => { - window.removeEventListener('resize', handleResize); - }; - }, []); + useEffect(() => { + const isCollapsed = + localStorage.getItem('default_collapse_sidebar') === 'true'; + dispatch({ type: 'SET_SIDER_COLLAPSED', payload: isCollapsed }); + }, [dispatch]); return (