diff --git a/themes/Medium/LayoutCategory.js b/themes/Medium/LayoutCategory.js index caa5c5a8..070184d0 100644 --- a/themes/Medium/LayoutCategory.js +++ b/themes/Medium/LayoutCategory.js @@ -1,8 +1,8 @@ import LayoutBase from './LayoutBase' -import BlogPostListPage from './components/BlogPostListPage' +import BlogPostListScroll from './components/BlogPostListScroll' export const LayoutCategory = (props) => { return - + } diff --git a/themes/Medium/LayoutSearch.js b/themes/Medium/LayoutSearch.js index cd66e5e8..4fcbfee6 100644 --- a/themes/Medium/LayoutSearch.js +++ b/themes/Medium/LayoutSearch.js @@ -4,6 +4,7 @@ import SearchInput from './components/SearchInput' import { useGlobal } from '@/lib/global' import TagGroups from './components/TagGroups' import CategoryGroup from './components/CategoryGroup' +import BlogPostListScroll from './components/BlogPostListScroll' export const LayoutSearch = (props) => { const { locale } = useGlobal() @@ -19,6 +20,6 @@ export const LayoutSearch = (props) => { - + } diff --git a/themes/Medium/LayoutTag.js b/themes/Medium/LayoutTag.js index d0d5b556..fe99c6b0 100644 --- a/themes/Medium/LayoutTag.js +++ b/themes/Medium/LayoutTag.js @@ -1,8 +1,8 @@ import LayoutBase from './LayoutBase' -import BlogPostListPage from './components/BlogPostListPage' +import BlogPostListScroll from './components/BlogPostListScroll' export const LayoutTag = (props) => { return - + } diff --git a/themes/Medium/components/BlogPostCard.js b/themes/Medium/components/BlogPostCard.js index 76ab1933..ee9014e5 100644 --- a/themes/Medium/components/BlogPostCard.js +++ b/themes/Medium/components/BlogPostCard.js @@ -4,7 +4,7 @@ import { faAngleRight } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Link from 'next/link' import React from 'react' -import { Code, Collection, CollectionRow, Equation, NotionRenderer } from 'react-notion-x' +import { Code, Collection, Equation, NotionRenderer } from 'react-notion-x' import CONFIG_MEDIUM from '../config_medium' const BlogPostCard = ({ post, showSummary }) => { @@ -36,7 +36,6 @@ const BlogPostCard = ({ post, showSummary }) => { components={{ equation: Equation, code: Code, - collectionRow: CollectionRow, collection: Collection }} /> diff --git a/themes/Medium/components/BlogPostListPage.js b/themes/Medium/components/BlogPostListPage.js index 0c6b56b8..bac8ab88 100644 --- a/themes/Medium/components/BlogPostListPage.js +++ b/themes/Medium/components/BlogPostListPage.js @@ -13,17 +13,7 @@ import { useRouter } from 'next/router' * @constructor */ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => { - let filteredPosts = Object.assign(posts) - const searchKey = getSearchKey() - if (searchKey) { - filteredPosts = posts.filter(post => { - const tagContent = post.tags ? post.tags.join(' ') : '' - const searchContent = post.title + post.summary + tagContent - return searchContent.toLowerCase().includes(searchKey.toLowerCase()) - }) - } - const filteredPostsCount = filteredPosts.length - const totalPage = Math.ceil(filteredPostsCount / BLOG.POSTS_PER_PAGE) + const totalPage = Math.ceil(postCount / BLOG.POSTS_PER_PAGE) if (!posts || posts.length === 0) { return @@ -31,7 +21,7 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => { return (
{/* 文章列表 */} - {filteredPosts.map(post => ( + {posts.map(post => ( ))} @@ -40,12 +30,4 @@ const BlogPostListPage = ({ page = 1, posts = [], postCount }) => { } } -function getSearchKey () { - const router = useRouter() - if (router.query && router.query.s) { - return router.query.s - } - return null -} - export default BlogPostListPage diff --git a/themes/Medium/components/BlogPostListScroll.js b/themes/Medium/components/BlogPostListScroll.js new file mode 100644 index 00000000..1b2334cc --- /dev/null +++ b/themes/Medium/components/BlogPostListScroll.js @@ -0,0 +1,106 @@ +import BLOG from '@/blog.config' +import BlogPostCard from './BlogPostCard' +import BlogPostListEmpty from './BlogPostListEmpty' +import { useGlobal } from '@/lib/global' +import throttle from 'lodash.throttle' +import React, { useCallback, useEffect, useRef, useState } from 'react' +import { useRouter } from 'next/router' + +/** + * 博客列表滚动分页 + * @param posts 所有文章 + * @param tags 所有标签 + * @returns {JSX.Element} + * @constructor + */ +const BlogPostListScroll = ({ posts = [], currentSearch }) => { + const postsPerPage = BLOG.POSTS_PER_PAGE + const [page, updatePage] = useState(1) + let filteredPosts = Object.assign(posts) + const searchKey = getSearchKey() + if (searchKey) { + filteredPosts = posts.filter(post => { + const tagContent = post.tags ? post.tags.join(' ') : '' + const searchContent = post.title + post.summary + tagContent + return searchContent.toLowerCase().includes(searchKey.toLowerCase()) + }) + } + const postsToShow = getPostByPage(page, filteredPosts, postsPerPage) + + let hasMore = false + if (filteredPosts) { + const totalCount = filteredPosts.length + hasMore = page * postsPerPage < totalCount + } + + const handleGetMore = () => { + if (!hasMore) return + updatePage(page + 1) + } + + // 监听滚动自动分页加载 + const scrollTrigger = useCallback(throttle(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }, 500)) + + // 监听滚动 + useEffect(() => { + window.addEventListener('scroll', scrollTrigger) + return () => { + window.removeEventListener('scroll', scrollTrigger) + } + }) + + const targetRef = useRef(null) + const { locale } = useGlobal() + + if (!postsToShow || postsToShow.length === 0) { + return + } else { + return
+ + {/* 文章列表 */} +
+ {postsToShow.map(post => ( + + ))} +
+ +
+
{ + handleGetMore() + }} + className='w-full my-4 py-4 text-center cursor-pointer glassmorphism shadow-xl rounded-xl dark:text-gray-200' + > {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}
+
+
+ } +} + +/** + * 获取从第1页到指定页码的文章 + * @param page 第几页 + * @param totalPosts 所有文章 + * @param postsPerPage 每页文章数量 + * @returns {*} + */ +const getPostByPage = function (page, totalPosts, postsPerPage) { + return totalPosts.slice( + 0, + postsPerPage * page + ) +} + +function getSearchKey () { + const router = useRouter() + if (router.query && router.query.s) { + return router.query.s + } + return null +} + +export default BlogPostListScroll