'use client' import { AdSlot } from '@/components/GoogleAdsense' import Live2D from '@/components/Live2D' import LoadingCover from '@/components/LoadingCover' import dynamic from 'next/dynamic' import { createContext, useContext, useEffect, useRef, useState } from 'react' import { siteConfig } from '@/lib/config' import { useGlobal } from '@/lib/global' import { useRouter } from 'next/router' import { getShortId } from '@/lib/utils/pageId' import Announcement from '../components/Announcement' import ArticleInfo from '../components/ArticleInfo' import BottomMenuBar from '../components/BottomMenuBar' import Catalog from '../components/Catalog' import Footer from '../components/Footer' import Header from '../components/Header' import InfoCard from '../components/InfoCard' import JumpToTopButton from '../components/JumpToTopButton' import NavPostList from '../components/NavPostList' import PageNavDrawer from '../components/PageNavDrawer' import RevolverMaps from '../components/RevolverMaps' import CONFIG from '../config' import { Style } from '../style' const AlgoliaSearchModal = dynamic( () => import('@/components/AlgoliaSearchModal'), { ssr: false } ) const WWAds = dynamic(() => import('@/components/WWAds'), { ssr: false }) // 主題全域變數 const ThemeGlobalGitbook = createContext() const useGitBookGlobal = () => useContext(ThemeGlobalGitbook) /** * 為最新文章加入紅點標記 */ function getNavPagesWithLatest(allNavPages, latestPosts, post) { // localStorage 儲存 id 與上次閱讀時間戳: posts_read_time = {"${post.id}":"Date()"} const postReadTime = JSON.parse( localStorage.getItem('post_read_time') || '{}' ) if (post) { postReadTime[getShortId(post.id)] = new Date().getTime() } // 更新記錄 localStorage.setItem('post_read_time', JSON.stringify(postReadTime)) return allNavPages?.map(item => { const res = { short_id: item.short_id, title: item.title || '', pageCoverThumbnail: item.pageCoverThumbnail || '', category: item.category || null, tags: item.tags || null, summary: item.summary || null, slug: item.slug, href: item.href, pageIcon: item.pageIcon || '', lastEditedDate: item.lastEditedDate } // 屬於最新的文章通常 6 篇 &&(無閱讀紀錄 || 最近更新時間大於上次閱讀時間) if ( latestPosts.some(post => post?.id.indexOf(item?.short_id) === 14) && (!postReadTime[item.short_id] || postReadTime[item.short_id] < new Date(item.lastEditedDate).getTime()) ) { return { ...res, isLatest: true } } else { return res } }) } /** * 基礎佈局 * 左右雙欄,手機版改為頂部導覽列 */ const LayoutBase = props => { const { children, post, allNavPages, latestPosts, slotLeft, slotRight, slotTop } = props const { fullWidth } = useGlobal() const router = useRouter() const [tocVisible, changeTocVisible] = useState(false) const [pageNavVisible, changePageNavVisible] = useState(false) const [filteredNavPages, setFilteredNavPages] = useState(allNavPages) const searchModal = useRef(null) useEffect(() => { setFilteredNavPages(getNavPagesWithLatest(allNavPages, latestPosts, post)) }, [router]) const GITBOOK_LOADING_COVER = siteConfig( 'GITBOOK_LOADING_COVER', true, CONFIG ) return (