mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-21 15:09:43 +00:00
@@ -1,19 +1,17 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import * as ThemeMap from '@/themes'
|
||||
import { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import Select from './Select'
|
||||
import { ALL_THEME } from '@/lib/theme'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
/**
|
||||
*
|
||||
* @returns 调试面板
|
||||
*/
|
||||
export function DebugPanel () {
|
||||
const [show, setShow] = useState(false)
|
||||
const GlobalConfig = useGlobal()
|
||||
const router = useRouter()
|
||||
const { theme, setTheme } = GlobalConfig
|
||||
const { theme, changeTheme, switchTheme } = useGlobal()
|
||||
|
||||
const themeOptions = []
|
||||
ALL_THEME.forEach(t => {
|
||||
themeOptions.push({ value: t, text: t })
|
||||
@@ -23,19 +21,6 @@ export function DebugPanel () {
|
||||
setShow(!show)
|
||||
}
|
||||
|
||||
function switchTheme () {
|
||||
const currentIndex = ALL_THEME.indexOf(theme)
|
||||
const newIndex = currentIndex < ALL_THEME.length - 1 ? currentIndex + 1 : 0
|
||||
changeTheme(ALL_THEME[newIndex])
|
||||
}
|
||||
/**
|
||||
* 切换主题
|
||||
*/
|
||||
function changeTheme (theme) {
|
||||
router.query.theme = ''
|
||||
setTheme(theme)
|
||||
}
|
||||
|
||||
function filterResult (text) {
|
||||
switch (text) {
|
||||
case 'true':
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable no-undef */
|
||||
import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { loadExternalResource } from '@/lib/utils'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
@@ -8,6 +9,7 @@ export default function Live2D () {
|
||||
return <></>
|
||||
}
|
||||
const [init, setInit] = useState()
|
||||
const { switchTheme } = useGlobal()
|
||||
|
||||
// if (typeof window !== 'undefined' && !hasLoad) {
|
||||
// initLive2D()
|
||||
@@ -21,7 +23,7 @@ export default function Live2D () {
|
||||
}
|
||||
}, [init])
|
||||
|
||||
return <canvas id="live2d" className='animate__slideInUp animate__animated' width="280" height="250"/>
|
||||
return <canvas id="live2d" className='animate__slideInUp animate__animated cursor-pointer' width="280" height="250" onClick={switchTheme} alt='切换主题' title='切换主题'/>
|
||||
}
|
||||
|
||||
function initLive2D () {
|
||||
|
||||
@@ -1,33 +1,11 @@
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import { useRouter } from 'next/router'
|
||||
import { ALL_THEME } from '@/lib/theme'
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns 主题切换
|
||||
*/
|
||||
export function ThemeSwitch () {
|
||||
const GlobalConfig = useGlobal()
|
||||
const router = useRouter()
|
||||
const { theme, setTheme } = GlobalConfig
|
||||
const themeOptions = []
|
||||
ALL_THEME.forEach(t => {
|
||||
themeOptions.push({ value: t, text: t })
|
||||
})
|
||||
|
||||
function switchTheme () {
|
||||
const currentIndex = ALL_THEME.indexOf(theme)
|
||||
const newIndex = currentIndex < ALL_THEME.length - 1 ? currentIndex + 1 : 0
|
||||
changeTheme(ALL_THEME[newIndex])
|
||||
}
|
||||
/**
|
||||
* 切换主题
|
||||
*/
|
||||
function changeTheme (theme) {
|
||||
router.query.theme = ''
|
||||
setTheme(theme)
|
||||
}
|
||||
|
||||
const { theme, switchTheme } = useGlobal()
|
||||
return (
|
||||
<div draggable="true" className="fixed left-4 bottom-12 text-white bg-black rounded z-50">
|
||||
<div className="p-2 cursor-pointer" onClick={switchTheme}>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { generateLocaleDict, initLocale } from './lang'
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import Router from 'next/router'
|
||||
import BLOG from '@/blog.config'
|
||||
import { ALL_THEME, initDarkMode } from '@/lib/theme'
|
||||
import { ALL_THEME, initDarkMode, initTheme, saveThemeToCookies } from '@/lib/theme'
|
||||
|
||||
const GlobalContext = createContext()
|
||||
let hasInit = false
|
||||
@@ -26,6 +26,22 @@ export function GlobalContextProvider ({ children }) {
|
||||
changeLoadingState(false)
|
||||
})
|
||||
|
||||
function switchTheme () {
|
||||
const currentIndex = ALL_THEME.indexOf(theme)
|
||||
const newIndex = currentIndex < ALL_THEME.length - 1 ? currentIndex + 1 : 0
|
||||
changeTheme(ALL_THEME[newIndex])
|
||||
}
|
||||
|
||||
function changeTheme (theme) {
|
||||
Router.query.theme = ''
|
||||
if (ALL_THEME.indexOf(theme) > -1) {
|
||||
setTheme(theme)
|
||||
} else {
|
||||
setTheme(BLOG.THEME)
|
||||
}
|
||||
saveThemeToCookies(theme)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasInit) {
|
||||
const userTheme = getQueryVariable('theme')
|
||||
@@ -34,12 +50,13 @@ export function GlobalContextProvider ({ children }) {
|
||||
}
|
||||
initLocale(locale, updateLocale)
|
||||
initDarkMode(isDarkMode, updateDarkMode)
|
||||
initTheme(theme, changeTheme)
|
||||
hasInit = true
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<GlobalContext.Provider value={{ onLoading, locale, updateLocale, isDarkMode, updateDarkMode, theme, setTheme }}>
|
||||
<GlobalContext.Provider value={{ onLoading, locale, updateLocale, isDarkMode, updateDarkMode, theme, setTheme, switchTheme, changeTheme }}>
|
||||
{children}
|
||||
</GlobalContext.Provider>
|
||||
)
|
||||
|
||||
32
lib/theme.js
32
lib/theme.js
@@ -19,6 +19,18 @@ export const initDarkMode = (isDarkMode, updateDarkMode) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从cookie中读取 用户默认主题
|
||||
* @param {*} theme
|
||||
* @param {*} changeTheme
|
||||
*/
|
||||
export const initTheme = (theme, changeTheme) => {
|
||||
const userTheme = loadThemeFromCookies()
|
||||
if (userTheme !== theme) {
|
||||
changeTheme(userTheme)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否优先深色模式
|
||||
* @returns {*}
|
||||
@@ -37,10 +49,26 @@ export function isPreferDark () {
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取默认主题
|
||||
* 读取深色模式
|
||||
* @returns {*}
|
||||
*/
|
||||
export const loadDarkModeFromCookies = () => {
|
||||
return cookie.load('darkMode')
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存深色模式
|
||||
* @param newTheme
|
||||
*/
|
||||
export const saveDarkModeToCookies = (newTheme) => {
|
||||
cookie.save('darkMode', newTheme, { path: '/' })
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取默认主题
|
||||
* @returns {*}
|
||||
*/
|
||||
export const loadThemeFromCookies = () => {
|
||||
return cookie.load('theme')
|
||||
}
|
||||
|
||||
@@ -48,6 +76,6 @@ export const loadDarkModeFromCookies = () => {
|
||||
* 保存默认主题
|
||||
* @param newTheme
|
||||
*/
|
||||
export const saveDarkModeToCookies = (newTheme) => {
|
||||
export const saveThemeToCookies = (newTheme) => {
|
||||
cookie.save('theme', newTheme, { path: '/' })
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import CommonHead from '@/components/CommonHead'
|
||||
import Live2D from '@/components/Live2D'
|
||||
import Link from 'next/link'
|
||||
|
||||
import React from 'react'
|
||||
import BLOG from '@/blog.config'
|
||||
/**
|
||||
* 基础布局 采用左右两侧布局,移动端使用顶部导航栏
|
||||
|
||||
@@ -9,6 +11,9 @@ import Link from 'next/link'
|
||||
*/
|
||||
const LayoutBase = props => {
|
||||
const { children, meta } = props
|
||||
const d = new Date()
|
||||
const currentYear = d.getFullYear()
|
||||
const startYear = BLOG.SINCE && BLOG.SINCE !== currentYear && BLOG.SINCE + '-'
|
||||
return (
|
||||
<div>
|
||||
<CommonHead meta={meta} />
|
||||
@@ -18,18 +23,30 @@ const LayoutBase = props => {
|
||||
<Link href="/">
|
||||
<a>首页</a>
|
||||
</Link>
|
||||
<Link href="/category">
|
||||
<a>分类</a>
|
||||
</Link>
|
||||
<Link href="/tag">
|
||||
<a>标签</a>
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
{/* 内容主体 */}
|
||||
<main id="wrapper" className="flex justify-center flex-1 pb-12">
|
||||
<div className="max-w-6xl px-3">{children}</div>
|
||||
<div className="max-w-4xl px-3">{children}</div>
|
||||
<div><Live2D/></div>
|
||||
</main>
|
||||
<footer
|
||||
className='font-sans dark:bg-gray-900 flex-shrink-0 justify-center text-center m-auto w-full leading-6 text-sm p-6'
|
||||
>
|
||||
<i className='fas fa-copyright' /> {`${startYear}${currentYear}`} <span><i className='mx-1 animate-pulse fas fa-heart'/> <a href={BLOG.LINK} className='underline font-bold dark:text-gray-300 '>{BLOG.AUTHOR}</a>.
|
||||
<br/>
|
||||
|
||||
<span>Powered by <a href='https://notion.so' className='underline font-bold dark:text-gray-300'>Notion</a> & <a href='https://github.com/tangly1024/NotionNext' className='underline font-bold dark:text-gray-300'>NotionNext {BLOG.VERSION}</a>.</span></span>
|
||||
|
||||
{BLOG.BEI_AN && <><br /><i className='fas fa-shield-alt' /> <a href='https://beian.miit.gov.cn/' className='mr-2'>{BLOG.BEI_AN}</a><br/></>}
|
||||
<br/>
|
||||
<span className='hidden busuanzi_container_site_pv'>
|
||||
<i className='fas fa-eye'/><span className='px-1 busuanzi_value_site_pv'> </span> </span>
|
||||
<span className='pl-2 hidden busuanzi_container_site_uv'>
|
||||
<i className='fas fa-users'/> <span className='px-1 busuanzi_value_site_uv'> </span> </span>
|
||||
<br/>
|
||||
<h1>{meta?.title || BLOG.TITLE}</h1>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutIndex = props => {
|
||||
const { posts } = props
|
||||
const { posts, postCount } = props
|
||||
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE)
|
||||
|
||||
const page = 1
|
||||
const showNext = page < totalPage && posts.length === BLOG.POSTS_PER_PAGE && posts.length < postCount
|
||||
|
||||
const currentPage = +page
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
{posts.map(p => (
|
||||
@@ -13,6 +25,28 @@ export const LayoutIndex = props => {
|
||||
<div>{p.summary}</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className='my-10 flex justify-between font-medium text-black dark:text-gray-100 space-x-2'>
|
||||
<Link
|
||||
href={ {
|
||||
pathname: (currentPage === 2 ? `${BLOG.PATH || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
} } passHref >
|
||||
<a
|
||||
rel='prev'
|
||||
className={`${currentPage === 1 ? 'invisible' : 'visible'} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
|
||||
>
|
||||
← {locale.PAGINATION.PREV}
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={ { pathname: `/page/${currentPage + 1}`, query: router.query.s ? { s: router.query.s } : {} } } passHref>
|
||||
<a
|
||||
rel='next'
|
||||
className={`${showNext ? 'visible' : 'invisible'} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
|
||||
>
|
||||
{locale.PAGINATION.NEXT} →
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,52 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { useGlobal } from '@/lib/global'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import LayoutBase from './LayoutBase'
|
||||
|
||||
export const LayoutPage = (props) => {
|
||||
const { page } = props
|
||||
return <LayoutBase {...props}>
|
||||
Page - {page}
|
||||
</LayoutBase>
|
||||
const { posts, postCount } = props
|
||||
|
||||
const { locale } = useGlobal()
|
||||
const router = useRouter()
|
||||
const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE)
|
||||
|
||||
const showNext = page < totalPage && posts.length === BLOG.POSTS_PER_PAGE && posts.length < postCount
|
||||
|
||||
const currentPage = +page
|
||||
return (
|
||||
<LayoutBase {...props}>
|
||||
{posts.map(p => (
|
||||
<div key={p.id} className='border my-12'>
|
||||
<Link href={`/article/${p.slug}`}>
|
||||
<a className='underline cursor-pointer'>{p.title}</a>
|
||||
</Link>
|
||||
<div>{p.summary}</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className='my-10 flex justify-between font-medium text-black dark:text-gray-100 space-x-2'>
|
||||
<Link
|
||||
href={ {
|
||||
pathname: (currentPage === 2 ? `${BLOG.PATH || '/'}` : `/page/${currentPage - 1}`), query: router.query.s ? { s: router.query.s } : {}
|
||||
} } passHref >
|
||||
<a
|
||||
rel='prev'
|
||||
className={`${currentPage === 1 ? 'invisible' : 'visible'} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
|
||||
>
|
||||
← {locale.PAGINATION.PREV}
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={ { pathname: `/page/${currentPage + 1}`, query: router.query.s ? { s: router.query.s } : {} } } passHref>
|
||||
<a
|
||||
rel='next'
|
||||
className={`${showNext ? 'visible' : 'invisible'} text-center w-full duration-200 px-4 py-2 hover:border-black border-b-2 hover:font-bold`}
|
||||
>
|
||||
{locale.PAGINATION.NEXT} →
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</LayoutBase>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,12 +11,12 @@ export default function ArticleAround ({ prev, next }) {
|
||||
}
|
||||
return <section className='text-gray-800 h-28 flex items-center justify-between space-x-5 my-4'>
|
||||
<Link href={`/article/${prev.slug}`} passHref>
|
||||
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-40 hover:bg-gray-700 hover:text-white duration-300'>
|
||||
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-white bg-opacity-40 hover:bg-gray-500 hover:text-white duration-300'>
|
||||
<i className='mr-1 fas fa-angle-double-left' />{prev.title}
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={`/article/${next.slug}`} passHref>
|
||||
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-gray-400 bg-opacity-40 hover:bg-gray-700 hover:text-white duration-300'>{next.title}
|
||||
<a className='text-sm cursor-pointer justify-center items-center flex w-full h-full bg-white bg-opacity-40 hover:bg-gray-500 hover:text-white duration-300'>{next.title}
|
||||
<i className='ml-1 my-1 fas fa-angle-double-right' />
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user