diff --git a/components/DarkModeButton.js b/components/DarkModeButton.js index 9e433a81..362c99ef 100644 --- a/components/DarkModeButton.js +++ b/components/DarkModeButton.js @@ -1,16 +1,17 @@ -import { useTheme } from '@/lib/theme' -import localStorage from 'localStorage' +import { loadUserThemeFromCookies, saveTheme, useTheme } from '@/lib/theme' const DarkModeButton = () => { - const { theme, changeTheme } = useTheme() + const { changeTheme } = useTheme() + const userTheme = loadUserThemeFromCookies() // 用户手动设置主题 const handleChangeDarkMode = () => { - const newTheme = (theme === 'light' ? 'dark' : 'light') - localStorage.setItem('theme', newTheme) + const newTheme = (userTheme === 'light' ? 'dark' : 'light') + saveTheme(newTheme) changeTheme(newTheme) } return
- +
} export default DarkModeButton diff --git a/lib/theme.js b/lib/theme.js index 308cc825..430728f5 100644 --- a/lib/theme.js +++ b/lib/theme.js @@ -1,5 +1,5 @@ -import { useContext, createContext, useState, useEffect } from 'react' -import localStorage from 'localStorage' +import { useContext, createContext, useState, useEffect, useRef } from 'react' +import cookie from 'react-cookies' const ThemeContext = createContext() @@ -10,21 +10,38 @@ const ThemeContext = createContext() * @constructor */ export function ThemeProvider ({ children }) { - // 用户自定义主题设置在变量中 - const userTheme = localStorage.getItem('theme') - const [theme, changeTheme] = useState(userTheme) + const [theme, changeTheme] = useState(loadUserThemeFromCookies()) + + // 由于Server采用服务端静态渲染,无法获取前端Cookie配置,故在渲染hooks中做初始化主题 useEffect(() => { - const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches - if (prefersDarkMode) { - changeTheme('dark') - localStorage.setItem('theme', 'dark') - } else { - changeTheme(userTheme) + // 若用户当前会话无指定主题,将根据深色偏好及访问时间决定默认主题 + if (!theme) { + const date = new Date() + const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches + const useDark = prefersDarkMode || (date.getHours() >= 18 || date.getHours() < 6) + if (useDark) { + changeTheme('dark') + saveTheme('dark') + } + } + + const baseLayoutClass = document.getElementById('wrapper').classList + if (!baseLayoutClass.contains(theme)) { + baseLayoutClass.add(theme) } }) + return ( {children} ) } +export const loadUserThemeFromCookies = () => { + return cookie.load('theme') +} + +export const saveTheme = (newTheme) => { + cookie.save('theme', newTheme, { path: '/' }) +} + export const useTheme = () => useContext(ThemeContext) diff --git a/package.json b/package.json index 0789c1f3..293b2bb3 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "preact": "^10.5.13", "qrcode.react": "^1.0.1", "react": "17.0.2", + "react-cookies": "^0.1.1", "react-cusdis": "^2.0.1", "react-dom": "17.0.2", "react-notion-x": "^4.6.5", diff --git a/pages/_app.js b/pages/_app.js index 9c235ba4..3387ac80 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -17,7 +17,7 @@ import { ThemeProvider } from '@/lib/theme' const Ackee = dynamic(() => import('@/components/Ackee'), { ssr: false }) const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false }) -function MyApp ({ Component, pageProps }) { +const MyApp = ({ Component, pageProps }) => { return ( diff --git a/pages/index.js b/pages/index.js index 585a278a..153b379c 100644 --- a/pages/index.js +++ b/pages/index.js @@ -25,7 +25,7 @@ export async function getStaticProps () { } } -const index = ({ posts, tags, meta }) => { +const Index = ({ posts, tags, meta }) => { return (
@@ -36,4 +36,4 @@ const index = ({ posts, tags, meta }) => { ) } -export default index +export default Index