diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts index de901ab..a039101 100644 --- a/src/hooks/usePagination.ts +++ b/src/hooks/usePagination.ts @@ -1,14 +1,12 @@ import React, { useEffect, useState } from "react"; -type TextNode = Text & { nodeValue: string }; -type PositionElement = [number, TextNode]; -type IdPositions = Record; -type UsePaginationReturnTuple = [ - ready: boolean, - goToPage: (pageNum: number) => void, - currentPage: number, - pageNumber: number -]; +import { + IdPositions, + PositionElement, + TextNode, + UsePaginationReturnTuple, +} from "~/types/usePagination"; +import { loadPages, savePages } from "~/utils/localStorage"; const isTextNode = (el: Node): el is TextNode => el.nodeType === Node.TEXT_NODE; const isElementNode = (el: Node): el is HTMLElement => @@ -18,6 +16,7 @@ export const usePagination = ( contentEl: React.RefObject, pageContainerEl: React.RefObject, pageEl: React.RefObject, + hash?: string, bookContent?: string ): UsePaginationReturnTuple => { const [ready, setReady] = useState(false); @@ -57,7 +56,11 @@ export const usePagination = ( setIdPositions(idPositions); }; - const findPages = async (page: HTMLElement, pageContainer: HTMLElement) => { + const findPages = async ( + hash: string, + page: HTMLElement, + pageContainer: HTMLElement + ) => { const pages = []; pages.push(0); let jump = 100; @@ -79,6 +82,7 @@ export const usePagination = ( setPages(pages); setCurrentPage(0); + savePages(hash, window.innerHeight, window.innerWidth, pages); }; const findPage = ( @@ -216,16 +220,17 @@ export const usePagination = ( }; useEffect(() => { - if (contentEl.current && bookContent) { + if (contentEl.current && hash && bookContent) { contentEl.current.innerHTML = bookContent; computeStartPositionsOfElements(contentEl.current); } - }, [bookContent]); + }, [hash, bookContent]); useEffect(() => { - if (positions.length && pageEl.current && pageContainerEl.current) - findPages(pageEl.current, pageContainerEl.current); - }, [positions, idPositions]); + if (hash && positions.length && pageEl.current && pageContainerEl.current) + if (!loadPages(hash, window.innerHeight, window.innerWidth, setPages)) + findPages(hash, pageEl.current, pageContainerEl.current); + }, [hash, positions, idPositions]); useEffect(() => { if (pageEl.current && pages.length && !ready) @@ -235,7 +240,7 @@ export const usePagination = ( const makeDisplayPage = (page: React.RefObject) => { if (page.current) return (pageNum: number) => displayPage(pageNum, page.current!); - else return (pageNum: number) => {}; + else return () => {}; }; return [ready, makeDisplayPage(pageEl), currentPage, pages.length - 1]; diff --git a/src/pages/BookView/index.tsx b/src/pages/BookView/index.tsx index e167fd1..380e4b8 100644 --- a/src/pages/BookView/index.tsx +++ b/src/pages/BookView/index.tsx @@ -21,6 +21,7 @@ export const BookView = ({ setLoading, loading }: IPageProps) => { contentRef, pageContainerRef, pageRef, + books && loading ? params?.hash : undefined, params?.hash && books && loading ? books[params.hash]?.content : undefined ); diff --git a/src/types/usePagination.ts b/src/types/usePagination.ts new file mode 100644 index 0000000..ab7d6a8 --- /dev/null +++ b/src/types/usePagination.ts @@ -0,0 +1,9 @@ +export type TextNode = Text & { nodeValue: string }; +export type PositionElement = [number, TextNode]; +export type IdPositions = Record; +export type UsePaginationReturnTuple = [ + ready: boolean, + goToPage: (pageNum: number) => void, + currentPage: number, + pageNumber: number +]; diff --git a/src/types/utils.ts b/src/types/utils.ts index d1e430b..1f4eae1 100644 --- a/src/types/utils.ts +++ b/src/types/utils.ts @@ -5,3 +5,13 @@ export const isArrOfStr = (obj: unknown): obj is string[] => { } return false; }; + +export const isObject = (obj: unknown): obj is Record => { + if (obj && typeof obj === "object" && !Array.isArray(obj)) { + for (const key of Object.keys(obj)) + if (typeof key !== "string") return false; + return true; + } + + return false; +}; diff --git a/src/utils/localStorage.ts b/src/utils/localStorage.ts index a5ffd91..ec57d49 100644 --- a/src/utils/localStorage.ts +++ b/src/utils/localStorage.ts @@ -29,3 +29,41 @@ export const saveBook = (key: string, book: IBook) => export const updateHashList = (hashList: string[]) => localStorage.setItem("list", JSON.stringify(hashList)); + +const validatePages = (obj: unknown): obj is number[] => { + if (obj && Array.isArray(obj)) { + for (const el of obj) if (typeof el !== "number") return false; + return true; + } + return false; +}; + +export const hashStr = (hash: string, height: number, width: number) => + `pages-${hash}-${height}-${width}`; + +export const loadPages = ( + hash: string, + height: number, + width: number, + cb: (pages: number[]) => void +) => { + const str = localStorage.getItem(hashStr(hash, height, width)); + + if (str) { + const obj: unknown = JSON.parse(str); + + if (validatePages(obj)) { + cb(obj); + return true; + } + } + + return false; +}; + +export const savePages = ( + hash: string, + height: number, + width: number, + pages: number[] +) => localStorage.setItem(hashStr(hash, height, width), JSON.stringify(pages));