forked from tangly1024/NotionNext
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a91fb21
commit 463b356
Showing
29 changed files
with
1,387 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { isBrowser } from '@/lib/utils' | ||
import React, { useState } from 'react' | ||
|
||
/** | ||
* 全屏按钮 | ||
* @returns | ||
*/ | ||
const FullScreenButton = () => { | ||
const [isFullScreen, setIsFullScreen] = useState(false) | ||
|
||
const handleFullScreenClick = () => { | ||
if (!isBrowser()) { | ||
return | ||
} | ||
const element = document.documentElement | ||
if (!isFullScreen) { | ||
if (element.requestFullscreen) { | ||
element.requestFullscreen() | ||
} else if (element.webkitRequestFullscreen) { | ||
element.webkitRequestFullscreen() | ||
} else if (element.mozRequestFullScreen) { | ||
element.mozRequestFullScreen() | ||
} else if (element.msRequestFullscreen) { | ||
element.msRequestFullscreen() | ||
} | ||
setIsFullScreen(true) | ||
} else { | ||
if (document.exitFullscreen) { | ||
document.exitFullscreen() | ||
} else if (document.webkitExitFullscreen) { | ||
document.webkitExitFullscreen() | ||
} else if (document.mozCancelFullScreen) { | ||
document.mozCancelFullScreen() | ||
} else if (document.msExitFullscreen) { | ||
document.msExitFullscreen() | ||
} | ||
setIsFullScreen(false) | ||
} | ||
} | ||
|
||
return ( | ||
<button onClick={handleFullScreenClick} className='dark:text-gray-300'> | ||
{isFullScreen ? '退出全屏' : <i className="fa-solid fa-expand"></i>} | ||
</button> | ||
) | ||
} | ||
|
||
export default FullScreenButton |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import dynamic from 'next/dynamic' | ||
|
||
const NotionPage = dynamic(() => import('@/components/NotionPage')) | ||
|
||
const Announcement = ({ notice, className }) => { | ||
if (notice?.blockMap) { | ||
return <div className={className}> | ||
<section id='announcement-wrapper' className='mb-10'> | ||
{notice && (<div id="announcement-content"> | ||
<NotionPage post={notice} className='text-center ' /> | ||
</div>)} | ||
</section> | ||
</div> | ||
} else { | ||
return null | ||
} | ||
} | ||
export default Announcement |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import BLOG from '@/blog.config' | ||
import { useRouter } from 'next/router' | ||
import { useGlobal } from '@/lib/global' | ||
|
||
/** | ||
* 加密文章校验组件 | ||
* @param {password, validPassword} props | ||
* @param password 正确的密码 | ||
* @param validPassword(bool) 回调函数,校验正确回调入参为true | ||
* @returns | ||
*/ | ||
export const ArticleFooter = props => { | ||
const router = useRouter() | ||
const { locale } = useGlobal() | ||
|
||
return <div className="flex justify-between font-medium text-gray-500 dark:text-gray-400"> | ||
<a> | ||
<button | ||
onClick={() => router.push(BLOG.path || '/')} | ||
className="mt-2 cursor-pointer hover:text-black dark:hover:text-gray-100" | ||
> | ||
← {locale.POST.BACK} | ||
</button> | ||
</a> | ||
<a> | ||
<button | ||
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} | ||
className="mt-2 cursor-pointer hover:text-black dark:hover:text-gray-100" | ||
> | ||
↑ {locale.POST.TOP} | ||
</button> | ||
</a> | ||
</div> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
|
||
import formatDate from '@/lib/formatDate' | ||
import Image from 'next/image' | ||
import BLOG from '@/blog.config' | ||
import TagItem from './TagItem' | ||
import md5 from 'js-md5' | ||
|
||
export const ArticleInfo = (props) => { | ||
const { post } = props | ||
|
||
const emailHash = md5(BLOG.CONTACT_EMAIL) | ||
|
||
return <section className="flex-wrap flex mt-2 text-gray--600 dark:text-gray-400 font-light leading-8"> | ||
<div> | ||
|
||
<div className="font-bold text-3xl text-black dark:text-white"> | ||
{post?.title} | ||
</div> | ||
|
||
{post?.type !== 'Page' && <> | ||
<nav className="flex mt-7 items-start text-gray-500 dark:text-gray-400"> | ||
<div className="flex mb-4"> | ||
<a href={BLOG.CONTACT_GITHUB || '#'} className="flex"> | ||
<Image | ||
alt={BLOG.author} | ||
width={24} | ||
height={24} | ||
src={`https://gravatar.com/avatar/${emailHash}`} | ||
className="rounded-full" | ||
/> | ||
<p className="ml-2 md:block">{BLOG.author}</p> | ||
</a> | ||
<span className="block"> / </span> | ||
</div> | ||
<div className="mr-2 mb-4 md:ml-0"> | ||
{formatDate( | ||
post?.publishTime || post?.createdTime, | ||
BLOG.LANG | ||
)} | ||
</div> | ||
{post.tags && ( | ||
<div className="flex flex-nowrap max-w-full overflow-x-auto article-tags"> | ||
{post?.tags.map(tag => ( | ||
<TagItem key={tag} tag={tag} /> | ||
))} | ||
</div> | ||
)} | ||
<span className="hidden busuanzi_container_page_pv mr-2"> | ||
<i className='mr-1 fas fa-eye' /> | ||
| ||
<span className="mr-2 busuanzi_value_page_pv" /> | ||
</span> | ||
</nav> | ||
</>} | ||
|
||
</div> | ||
|
||
</section> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { useGlobal } from '@/lib/global' | ||
import { useEffect, useRef } from 'react' | ||
|
||
/** | ||
* 加密文章校验组件 | ||
* @param {password, validPassword} props | ||
* @param password 正确的密码 | ||
* @param validPassword(bool) 回调函数,校验正确回调入参为true | ||
* @returns | ||
*/ | ||
export const ArticleLock = props => { | ||
const { validPassword } = props | ||
const { locale } = useGlobal() | ||
|
||
const submitPassword = () => { | ||
const p = document.getElementById('password') | ||
if (!validPassword(p?.value)) { | ||
const tips = document.getElementById('tips') | ||
if (tips) { | ||
tips.innerHTML = '' | ||
tips.innerHTML = `<div class='text-red-500 animate__shakeX animate__animated'>${locale.COMMON.PASSWORD_ERROR}</div>` | ||
} | ||
} | ||
} | ||
|
||
const passwordInputRef = useRef(null) | ||
useEffect(() => { | ||
// 选中密码输入框并将其聚焦 | ||
passwordInputRef.current.focus() | ||
}, []) | ||
|
||
return <div id='container' className='w-full flex justify-center items-center h-96 font-sans'> | ||
<div className='text-center space-y-3'> | ||
<div className='font-bold'>{locale.COMMON.ARTICLE_LOCK_TIPS}</div> | ||
<div className='flex'> | ||
<input id="password" type='password' | ||
onKeyDown={(e) => { | ||
if (e.key === 'Enter') { | ||
submitPassword() | ||
} | ||
}} | ||
ref={passwordInputRef} // 绑定ref到passwordInputRef变量 | ||
className='outline-none w-full text-sm pl-5 rounded-l transition focus:shadow-lg font-light leading-10 text-black dark:bg-gray-500 bg-gray-50' | ||
></input> | ||
<div onClick={submitPassword} className="px-3 whitespace-nowrap cursor-pointer items-center justify-center py-2 rounded-r duration-300 bg-gray-300" > | ||
<i className={'duration-200 cursor-pointer fas fa-key dark:text-black'} > {locale.COMMON.SUBMIT}</i> | ||
</div> | ||
</div> | ||
<div id='tips'> | ||
</div> | ||
</div> | ||
</div> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import BLOG from '@/blog.config' | ||
import Link from 'next/link' | ||
|
||
/** | ||
* 归档分组文章 | ||
* @param {*} param0 | ||
* @returns | ||
*/ | ||
export default function BlogArchiveItem({ archiveTitle, archivePosts }) { | ||
return ( | ||
<div key={archiveTitle}> | ||
<div id={archiveTitle} className="pt-16 pb-4 text-3xl dark:text-gray-300" > | ||
{archiveTitle} | ||
</div> | ||
|
||
<ul> | ||
{archivePosts[archiveTitle].map(post => ( | ||
<li | ||
key={post.id} | ||
className="border-l-2 p-1 text-xs md:text-base items-center hover:scale-x-105 hover:border-gray-500 dark:hover:border-gray-300 dark:border-gray-400 transform duration-500" | ||
> | ||
<div id={post?.publishTime}> | ||
<span className="text-gray-400"> | ||
{post.date?.start_date} | ||
</span>{' '} | ||
| ||
<Link | ||
href={`${BLOG.SUB_PATH}/${post.slug}`} | ||
passHref | ||
className="dark:text-gray-400 dark:hover:text-gray-300 overflow-x-hidden hover:underline cursor-pointer text-gray-600"> | ||
|
||
{post.title} | ||
|
||
</Link> | ||
</div> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Tags from './Tags' | ||
|
||
export default function BlogListBar(props) { | ||
const { tag, setFilterKey } = props | ||
const handleSearchChange = (val) => { | ||
setFilterKey(val) | ||
} | ||
if (tag) { | ||
return (<div className="mb-4"> | ||
<div className='relative'> | ||
<input | ||
type="text" | ||
placeholder={ | ||
tag ? `Search in #${tag}` : 'Search Articles' | ||
} | ||
className="outline-none block w-full border px-4 py-2 border-black bg-white text-black dark:bg-night dark:border-white dark:text-white" | ||
onChange={e => handleSearchChange(e.target.value)} | ||
/> | ||
<svg | ||
className="absolute right-3 top-3 h-5 w-5 text-black dark:text-white" | ||
xmlns="http://www.w3.org/2000/svg" | ||
fill="none" | ||
viewBox="0 0 24 24" | ||
stroke="currentColor" | ||
> | ||
<path | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
strokeWidth="2" | ||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" | ||
></path> | ||
</svg> | ||
</div> | ||
<Tags {...props} /> | ||
</div>) | ||
} else { | ||
return <></> | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
import BLOG from '@/blog.config' | ||
import { useGlobal } from '@/lib/global' | ||
import { useRouter } from 'next/router' | ||
import Link from 'next/link' | ||
import BlogPost from './BlogPost' | ||
|
||
export const BlogListPage = props => { | ||
const { page = 1, posts, postCount } = props | ||
const { locale } = useGlobal() | ||
const router = useRouter() | ||
const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) | ||
const currentPage = +page | ||
|
||
const showPrev = currentPage > 1 | ||
const showNext = page < totalPage | ||
const pagePrefix = router.asPath.split('?')[0].replace(/\/page\/[1-9]\d*/, '').replace(/\/$/, '') | ||
|
||
return ( | ||
<div className="w-full"> | ||
|
||
<div id="posts-wrapper" className='grid lg:grid-cols-3 grid-cols-2'> | ||
{posts?.map(post => ( | ||
<BlogPost key={post.id} post={post} {...props}/> | ||
))} | ||
</div> | ||
|
||
<div className="flex justify-between text-xs"> | ||
<Link | ||
href={{ pathname: currentPage - 1 === 1 ? `${pagePrefix}/` : `${pagePrefix}/page/${currentPage - 1}`, query: router.query.s ? { s: router.query.s } : {} }} | ||
className={`${showPrev ? ' ' : ' invisible block pointer-events-none '}no-underline py-2 px-3 rounded`}> | ||
|
||
<button rel="prev" className="block cursor-pointer"> | ||
← {locale.PAGINATION.PREV} | ||
</button> | ||
|
||
</Link> | ||
<Link | ||
href={{ pathname: `${pagePrefix}/page/${currentPage + 1}`, query: router.query.s ? { s: router.query.s } : {} }} | ||
className={`${showNext ? ' ' : 'invisible pointer-events-none '} no-underline py-2 px-3 rounded`}> | ||
|
||
<button rel="next" className="block cursor-pointer"> | ||
{locale.PAGINATION.NEXT} → | ||
</button> | ||
|
||
</Link> | ||
</div> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.