import axios from "axios";
import { useEffect, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router";
import "./reader.css";
import OutlinedButton from "../md-components/OutlinedButton";
import FilledButton from "../md-components/FilledButton";
import Contents from "../components/contents/Contents";
import Icon from "../md-components/Icon";
import { Link } from "react-router-dom";
import Skeleton from "react-loading-skeleton";
import LinearProgress from "../md-components/LinearProgress";
import {
addBook,
getBook,
getReadBook,
putReadBook,
removeBook,
saveReadBook,
updateReadBook,
} from "../db";
import IconButton from "../md-components/IconButton";
const ReaderFB2 = () => {
const { id } = useParams();
const readerRef = useRef();
const containerRef = useRef();
const progressRef = useRef();
const contentsRef = useRef();
const contentsBackdropRef = useRef();
const navigate = useNavigate();
const [totalHeight, setTotalHeight] = useState(0);
const [currentHeight, setCurrentHeight] = useState(0);
const [readerHeight, setReaderHeight] = useState(0);
const [totalPages, setTotalPages] = useState(1);
const [currentPage, setCurrentPage] = useState(0);
const [isLocal, setIsLocal] = useState(false);
const [onBookshelf, setOnBookshelf] = useState(false);
const [bookInfo, setBookInfo] = useState({ title: "" });
const [contents, setContents] = useState([]);
function nextPage() {
setCurrentPage((prev) => {
if (totalPages - prev < 1) {
return prev;
}
return prev + 1;
});
}
function prevPage() {
setCurrentPage((prev) => {
if (prev <= 1) {
return prev;
}
return prev - 1;
});
}
const leftRef = useRef();
const rightRef = useRef();
function keyboardPagination(e) {
if (!(leftRef.current && rightRef.current)) {
console.log("harakiri");
document.removeEventListener("keydown", keyboardPagination, false);
return;
}
if (e.key === "ArrowRight") {
rightRef.current.click();
}
if (e.key === "ArrowLeft") {
leftRef.current.click();
}
}
useEffect(() => {
if (!(leftRef.current && rightRef.current)) return;
console.log("add listener");
document.addEventListener("keydown", keyboardPagination, false);
}, [leftRef, rightRef]);
function toggleFloatingContents() {
if (!contentsRef.current || !contentsBackdropRef.current) return;
contentsRef.current.classList.toggle("show");
contentsBackdropRef.current.classList.toggle("show");
}
useEffect(() => {
if (currentPage === 0) return;
if (readerHeight === totalHeight) return;
setCurrentHeight(readerHeight * (currentPage - 1));
readerRef.current.scrollTop = readerHeight * (currentPage - 1);
progressRef.current.style.width = `${(currentPage / totalPages) * 100}%`;
//console.log(readerHeight * (currentPage-1) / totalHeight, "update read book", currentPage)
//console.log(readerHeight, currentPage, totalHeight)
updateReadBook(id, (readerHeight * (currentPage - 1)) / totalHeight);
}, [currentPage]);
async function loadBook() {
let readBook = await getReadBook(id);
if (readBook) {
setOnBookshelf(readBook.onBookshelf === true);
}
let caches = undefined;
let localHTML = undefined;
if (window.caches !== undefined) {
caches = await window.caches.open("books");
localHTML = await caches.match(`/api/book/${id}/reader`);
}
let localBook = await getBook(id);
let innerHTML = "";
if (localBook !== undefined && localHTML !== undefined) {
setIsLocal(true);
setBookInfo(localBook);
setContents(localBook.contents);
await localHTML.text().then((html) => {
innerHTML = html;
});
} else {
if (!window.onLine) {
localStorage.removeItem("lastReadBook");
navigate("/offline");
}
setIsLocal(false);
axios
.get(`/book/${id}`)
.then((res) => setBookInfo(res.data))
.catch(() => navigate("/notfound"));
axios.get(`/book/${id}/contents`).then((res) => setContents(res.data));
await axios.get(`/book/${id}/reader`).then((res) => {
innerHTML = res.data;
});
}
localStorage.setItem("lastReadBook", id);
readerRef.current.innerHTML =
innerHTML +
"
".repeat(Math.floor(containerRef.current.clientHeight / 23) * 2); // заполнение двух страниц пустотой для возможности прокрутки не до конца
resizingReader(true);
}
async function resizingReader(firstLoad) {
if (!readerRef.current) return;
if (readerRef.current.scrollHeight === 0) return;
let progressRatio;
if (firstLoad) {
let readBook = await getReadBook(id);
if (readBook === undefined) {
progressRatio = 0;
updateReadBook(id, 0);
} else {
progressRatio = readBook.progress;
}
}
readerRef.current.style.height = `${
Math.floor(containerRef.current.clientHeight / 23) * 23 - 23
}px`; // подгоняем блок контента под окно ридера, и не забывает учитывать прогресс
setTotalHeight(readerRef.current.scrollHeight);
setReaderHeight(readerRef.current.clientHeight);
setTotalPages(
Math.ceil(
readerRef.current.scrollHeight / readerRef.current.clientHeight
) - 2
);
setCurrentPage(
Math.ceil(
Math.floor(progressRatio * readerRef.current.scrollHeight) /
readerRef.current.clientHeight
) + 1
);
}
useEffect(() => {
if (!readerRef.current) return;
loadBook();
}, [id]);
// изменение размера изображений для соответствия с шириной строки (23px)
useEffect(() => {
if (!readerRef.current) return;
let images = Array.from(readerRef.current.getElementsByTagName("img"));
images.map((img) => {
img.height = Math.floor(img.height / 23) * 23;
});
}, [totalHeight]);
return (
<>