Added pages cache

This commit is contained in:
Dmitriy Shishkov 2021-07-16 19:24:37 +05:00
parent 620852b536
commit a3d24c373c
No known key found for this signature in database
GPG Key ID: 14358F96FCDD8060
5 changed files with 79 additions and 16 deletions

View File

@ -1,14 +1,12 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
type TextNode = Text & { nodeValue: string }; import {
type PositionElement = [number, TextNode]; IdPositions,
type IdPositions = Record<string, number>; PositionElement,
type UsePaginationReturnTuple = [ TextNode,
ready: boolean, UsePaginationReturnTuple,
goToPage: (pageNum: number) => void, } from "~/types/usePagination";
currentPage: number, import { loadPages, savePages } from "~/utils/localStorage";
pageNumber: number
];
const isTextNode = (el: Node): el is TextNode => el.nodeType === Node.TEXT_NODE; const isTextNode = (el: Node): el is TextNode => el.nodeType === Node.TEXT_NODE;
const isElementNode = (el: Node): el is HTMLElement => const isElementNode = (el: Node): el is HTMLElement =>
@ -18,6 +16,7 @@ export const usePagination = (
contentEl: React.RefObject<HTMLDivElement>, contentEl: React.RefObject<HTMLDivElement>,
pageContainerEl: React.RefObject<HTMLDivElement>, pageContainerEl: React.RefObject<HTMLDivElement>,
pageEl: React.RefObject<HTMLDivElement>, pageEl: React.RefObject<HTMLDivElement>,
hash?: string,
bookContent?: string bookContent?: string
): UsePaginationReturnTuple => { ): UsePaginationReturnTuple => {
const [ready, setReady] = useState(false); const [ready, setReady] = useState(false);
@ -57,7 +56,11 @@ export const usePagination = (
setIdPositions(idPositions); setIdPositions(idPositions);
}; };
const findPages = async (page: HTMLElement, pageContainer: HTMLElement) => { const findPages = async (
hash: string,
page: HTMLElement,
pageContainer: HTMLElement
) => {
const pages = []; const pages = [];
pages.push(0); pages.push(0);
let jump = 100; let jump = 100;
@ -79,6 +82,7 @@ export const usePagination = (
setPages(pages); setPages(pages);
setCurrentPage(0); setCurrentPage(0);
savePages(hash, window.innerHeight, window.innerWidth, pages);
}; };
const findPage = ( const findPage = (
@ -216,16 +220,17 @@ export const usePagination = (
}; };
useEffect(() => { useEffect(() => {
if (contentEl.current && bookContent) { if (contentEl.current && hash && bookContent) {
contentEl.current.innerHTML = bookContent; contentEl.current.innerHTML = bookContent;
computeStartPositionsOfElements(contentEl.current); computeStartPositionsOfElements(contentEl.current);
} }
}, [bookContent]); }, [hash, bookContent]);
useEffect(() => { useEffect(() => {
if (positions.length && pageEl.current && pageContainerEl.current) if (hash && positions.length && pageEl.current && pageContainerEl.current)
findPages(pageEl.current, pageContainerEl.current); if (!loadPages(hash, window.innerHeight, window.innerWidth, setPages))
}, [positions, idPositions]); findPages(hash, pageEl.current, pageContainerEl.current);
}, [hash, positions, idPositions]);
useEffect(() => { useEffect(() => {
if (pageEl.current && pages.length && !ready) if (pageEl.current && pages.length && !ready)
@ -235,7 +240,7 @@ export const usePagination = (
const makeDisplayPage = (page: React.RefObject<HTMLDivElement>) => { const makeDisplayPage = (page: React.RefObject<HTMLDivElement>) => {
if (page.current) if (page.current)
return (pageNum: number) => displayPage(pageNum, page.current!); return (pageNum: number) => displayPage(pageNum, page.current!);
else return (pageNum: number) => {}; else return () => {};
}; };
return [ready, makeDisplayPage(pageEl), currentPage, pages.length - 1]; return [ready, makeDisplayPage(pageEl), currentPage, pages.length - 1];

View File

@ -21,6 +21,7 @@ export const BookView = ({ setLoading, loading }: IPageProps) => {
contentRef, contentRef,
pageContainerRef, pageContainerRef,
pageRef, pageRef,
books && loading ? params?.hash : undefined,
params?.hash && books && loading ? books[params.hash]?.content : undefined params?.hash && books && loading ? books[params.hash]?.content : undefined
); );

View File

@ -0,0 +1,9 @@
export type TextNode = Text & { nodeValue: string };
export type PositionElement = [number, TextNode];
export type IdPositions = Record<string, number>;
export type UsePaginationReturnTuple = [
ready: boolean,
goToPage: (pageNum: number) => void,
currentPage: number,
pageNumber: number
];

View File

@ -5,3 +5,13 @@ export const isArrOfStr = (obj: unknown): obj is string[] => {
} }
return false; return false;
}; };
export const isObject = (obj: unknown): obj is Record<string, unknown> => {
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;
};

View File

@ -29,3 +29,41 @@ export const saveBook = (key: string, book: IBook) =>
export const updateHashList = (hashList: string[]) => export const updateHashList = (hashList: string[]) =>
localStorage.setItem("list", JSON.stringify(hashList)); 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));