From dee6c86d15cb44946521c032296fc1bd92c76510 Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Sat, 26 Oct 2024 15:43:03 +0500 Subject: [PATCH] monograph: add table of contents on mobile --- .../app/components/monographpost/index.tsx | 416 ++++++++++++------ 1 file changed, 286 insertions(+), 130 deletions(-) diff --git a/apps/monograph/app/components/monographpost/index.tsx b/apps/monograph/app/components/monographpost/index.tsx index 1966159b47..ac820ec0fb 100644 --- a/apps/monograph/app/components/monographpost/index.tsx +++ b/apps/monograph/app/components/monographpost/index.tsx @@ -35,7 +35,13 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { NNCrypto } from "../../utils/nncrypto.client"; import { hashNavigate } from "../../utils/use-hash-location"; import { Icon } from "@notesnook/ui"; -import { mdiAlertCircleOutline, mdiArrowUp, mdiLockOutline } from "@mdi/js"; +import { + mdiAlertCircleOutline, + mdiArrowUp, + mdiClose, + mdiListBoxOutline, + mdiLockOutline +} from "@mdi/js"; import { Footer } from "../footer"; import ReportDialog from "./report-modal"; @@ -80,7 +86,7 @@ function generateTableOfContents() { currentHeading < headingLevel ? level + 1 : currentHeading > headingLevel - ? level - 1 + ? headingLevel : level; currentHeading = headingLevel; @@ -103,41 +109,10 @@ export const MonographPage = ({ }) => { const [reportDialogVisible, setReportDialogVisible] = useState(false); const [tableOfContents, setTableOfContents] = useState([]); - const [activeHeadings, setActiveHeadings] = useState(); const [content, setContent] = useState(monograph.content); - const [showScrollToTop, setShowScrollToTop] = useState(false); + const [showTableOfContents, setShowTableOfContents] = useState(false); const editorContainer = useRef(null); - useEffect(() => { - function onScroll() { - const scrollTop = window.scrollY; - const height = window.innerHeight || 0; - const viewportHeight = scrollTop + height - 30; - const documentOffset = editorContainer.current?.offsetTop || 0; - const active = tableOfContents.filter((t, i, array) => { - const next = array.at(i + 1); - const headingOffset = - documentOffset + t.node.offsetTop + t.node.clientHeight; - const lessThanNext = next - ? scrollTop <= - next.node.offsetTop + documentOffset + next.node.clientHeight - : true; - const isInViewport = - headingOffset > scrollTop && headingOffset < viewportHeight; - const isActive = scrollTop >= headingOffset && lessThanNext; - return isInViewport || isActive; - }); - - setShowScrollToTop(scrollTop > 120); - setActiveHeadings(active.map((a) => a.id)); - } - onScroll(); - window.addEventListener("scroll", onScroll); - return () => { - window.removeEventListener("scroll", onScroll); - }; - }, [tableOfContents]); - if (!content && monograph.encryptedContent) return ( }> @@ -158,68 +133,69 @@ export const MonographPage = ({ + - - Monograph - + + + {monograph.title} - - - - {formatDate(monograph.datePublished, { - type: "date-time", - dateFormat: "YYYY-MM-DD", - timeFormat: "24-hour" - })} - - {monograph.encryptedContent ? ( - - - - End-to-end encrypted - - - ) : null} - - - {monograph.encryptedContent ? null : ( + + + {formatDate(monograph.datePublished, { + type: "date-time", + dateFormat: "YYYY-MM-DD", + timeFormat: "24-hour" + })} + + {monograph.encryptedContent ? ( + + + + End-to-end encrypted + + + ) : ( )} + - {showScrollToTop && } + - - CONTENTS - - {tableOfContents.length === 0 ? ( + {showTableOfContents ? ( <> - - This monograph has no table of contents. + + CONTENTS + ) : null} - {tableOfContents.map((item) => ( - - ))} - + + + setShowTableOfContents(false)} + /> + + ) : null}