import { createContext, useContext, useState, useEffect } from 'react' import { theme } from 'antd' import PropTypes from 'prop-types' const ThemeContext = createContext() export const ThemeProvider = ({ children }) => { const [isSystem, setIsSystem] = useState(() => { const savedSystem = sessionStorage.getItem('isSystem') return savedSystem ? JSON.parse(savedSystem) : true }) const [isDarkMode, setIsDarkMode] = useState(() => { const savedTheme = sessionStorage.getItem('isDarkMode') return savedTheme ? JSON.parse(savedTheme) : true }) const [isCompact, setIsCompact] = useState(() => { const savedCompact = sessionStorage.getItem('isCompact') return savedCompact ? JSON.parse(savedCompact) : false }) // System theme detection useEffect(() => { const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') const handleSystemThemeChange = (e) => { if (isSystem) { setIsDarkMode(e.matches) } } // Set initial value if (isSystem) { setIsDarkMode(mediaQuery.matches) } // Add listener mediaQuery.addEventListener('change', handleSystemThemeChange) // Cleanup return () => mediaQuery.removeEventListener('change', handleSystemThemeChange) }, [isSystem]) useEffect(() => { sessionStorage.setItem('isSystem', JSON.stringify(isSystem)) }, [isSystem]) useEffect(() => { sessionStorage.setItem('isDarkMode', JSON.stringify(isDarkMode)) }, [isDarkMode]) useEffect(() => { sessionStorage.setItem('isCompact', JSON.stringify(isCompact)) }, [isCompact]) const toggleTheme = () => { if (isSystem) { setIsSystem(false) } setIsDarkMode(!isDarkMode) } const toggleSystem = () => { setIsSystem(!isSystem) if (!isSystem) { // When enabling system theme, update to match system preference setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches) } } const toggleCompact = () => { setIsCompact(!isCompact) } const getThemeAlgorithm = () => { var baseAlgorithm if (isDarkMode == true) { baseAlgorithm = theme.darkAlgorithm } else { baseAlgorithm = theme.defaultAlgorithm } return isCompact ? [theme.compactAlgorithm, baseAlgorithm] : [baseAlgorithm] } const colors = { colorPrimary: '#0091FF', colorSuccess: '#30D158', colorWarning: '#FF9230', colorError: '#FF4245', colorInfo: '#0A84FF', colorLink: '#5AC8F5', colorCyan: '#5AC8F5', colorPink: '#FF69B4', colorPurple: '#800080', colorMagenta: '#FF00FF', colorVolcano: '#FF4500' } const getColors = () => { return colors } const themeConfig = { algorithm: getThemeAlgorithm(), token: { ...colors, borderRadius: '12px' }, components: { Layout: { headerBg: isDarkMode ? '#141414' : '#ffffff' } } } return ( {children} ) } ThemeProvider.propTypes = { children: PropTypes.node.isRequired } // eslint-disable-next-line react-refresh/only-export-components export const useThemeContext = () => { const context = useContext(ThemeContext) if (!context) { throw new Error('useThemeContext must be used within a ThemeProvider') } return context }