Got rid of book list context. Now book content is served by serviceworker too

This commit is contained in:
Dmitriy Shishkov 2021-08-09 14:05:34 +03:00
parent 09da9a7d60
commit 4f558b8530
No known key found for this signature in database
GPG Key ID: 14358F96FCDD8060
4 changed files with 70 additions and 77 deletions

View File

@ -1,6 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Route, Switch } from "wouter"; import { Route, Switch } from "wouter";
import { BookListContextProvider } from "~/context";
import { Bookshelf } from "~/pages/Bookshelf"; import { Bookshelf } from "~/pages/Bookshelf";
import { BookView } from "~/pages/BookView"; import { BookView } from "~/pages/BookView";
@ -24,19 +23,17 @@ export const App = () => {
</div> </div>
)} )}
<Navbar /> <Navbar />
<BookListContextProvider> <Switch>
<Switch> <Route path="/upload">
<Route path="/upload"> <UploadForm setLoading={setLoading} loading={loading} />
<UploadForm setLoading={setLoading} loading={loading} /> </Route>
</Route> <Route path="/">
<Route path="/"> <Bookshelf setLoading={setLoading} loading={loading} />
<Bookshelf setLoading={setLoading} loading={loading} /> </Route>
</Route> <Route path="/:hash">
<Route path="/:hash"> <BookView setLoading={setLoading} loading={loading} />
<BookView setLoading={setLoading} loading={loading} /> </Route>
</Route> </Switch>
</Switch>
</BookListContextProvider>
</div> </div>
); );
}; };

View File

@ -1,19 +0,0 @@
import React from "react";
import { useLibrary, UseLibraryReturnTuple } from "./hooks/useLibrary";
import { BookT } from "./types/book";
export const BookListContext = React.createContext<UseLibraryReturnTuple>([
{},
(book: BookT) => {},
[],
]);
export const BookListContextProvider: React.FC = ({ children }) => {
const library = useLibrary();
return (
<BookListContext.Provider value={library}>
{children}
</BookListContext.Provider>
);
};

View File

@ -1,29 +1,52 @@
import React, { MouseEventHandler, useContext, useEffect, useRef } from "react"; import React, { MouseEventHandler, useState, useEffect, useRef } from "react";
import { Redirect, useRoute } from "wouter"; import { Redirect, useRoute } from "wouter";
import styles from "./BookView.module.css"; import styles from "./BookView.module.css";
import { BookListContext } from "~/context";
import { usePagination } from "~/hooks/usePagination"; import { usePagination } from "~/hooks/usePagination";
import { IPageProps } from "~/types/page"; import { IPageProps } from "~/types/page";
import { useBookState } from "~/hooks/useBookState"; import { useBookState } from "~/hooks/useBookState";
import { BookT } from "~/types/book";
import { API_URL } from "~/constants";
import { validateResponse } from "~/utils/api";
export const BookView = ({ setLoading, loading }: IPageProps) => { export const BookView = ({ setLoading, loading }: IPageProps) => {
useEffect(() => setLoading(true), []); useEffect(() => setLoading(true), []);
const [hasErr, setHasErr] = useState(false);
const [book, setBook] = useState<BookT>();
const [_, params] = useRoute("/:hash"); const [_, params] = useRoute("/:hash");
const [books] = useContext(BookListContext);
const contentRef = useRef<HTMLDivElement>(null); const contentRef = useRef<HTMLDivElement>(null);
const pageContainerRef = useRef<HTMLDivElement>(null); const pageContainerRef = useRef<HTMLDivElement>(null);
const pageRef = useRef<HTMLDivElement>(null); const pageRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (params?.hash) {
(async () => {
try {
const res = await fetch(API_URL + "/book/" + params.hash);
if (!res.ok) throw new Error(res.status + " " + res.statusText);
const book: unknown = await res.json();
if (validateResponse(book)) setBook(book);
} catch (err) {
if (process.env.NODE_ENV === "development") console.error(err);
setHasErr(true);
setLoading(false);
}
})();
}
}, []);
const [pagesReady, goToPage, currentPage, pagesNumber] = usePagination( const [pagesReady, goToPage, currentPage, pagesNumber] = usePagination(
contentRef, contentRef,
pageContainerRef, pageContainerRef,
pageRef, pageRef,
books && loading ? params?.hash : undefined, book ? params?.hash : undefined,
params?.hash && books && loading ? books[params.hash]?.content : undefined params?.hash ? book?.content : undefined
); );
const currentPageRef = useRef(currentPage); const currentPageRef = useRef(currentPage);
@ -68,35 +91,33 @@ export const BookView = ({ setLoading, loading }: IPageProps) => {
} }
}; };
if (books) { if (hasErr) return <Redirect to="/" />;
if (params?.hash && params.hash in books)
return ( return (
<> <>
<div <div
className={`${styles.border} ${styles.leftBorder}`} className={`${styles.border} ${styles.leftBorder}`}
onClick={goPrev} onClick={goPrev}
/> />
<div className={styles.content} ref={contentRef} /> <div className={styles.content} ref={contentRef} />
<div className={styles.pageContainer} ref={pageContainerRef}> <div className={styles.pageContainer} ref={pageContainerRef}>
<div className={styles.page} ref={pageRef} onClick={goNext} /> <div className={styles.page} ref={pageRef} onClick={goNext} />
</div> </div>
<div <div
className={`${styles.border} ${styles.rightBorder}`} className={`${styles.border} ${styles.rightBorder}`}
onClick={goNext} onClick={goNext}
/> />
<div className={styles.pageIndicator}> <div className={styles.pageIndicator}>
<button className={styles.pageSwitchArrow} onClick={goPrev}> <button className={styles.pageSwitchArrow} onClick={goPrev}>
{currentPage !== 0 && "←"} {currentPage !== 0 && "←"}
</button> </button>
<span className={styles.pageNumber} onClick={insertNumber}> <span className={styles.pageNumber} onClick={insertNumber}>
{currentPage + 1} / {pagesNumber} {currentPage + 1} / {pagesNumber}
</span> </span>
<button className={styles.pageSwitchArrow} onClick={goNext}> <button className={styles.pageSwitchArrow} onClick={goNext}>
{currentPage !== pagesNumber - 1 && "→"} {currentPage !== pagesNumber - 1 && "→"}
</button> </button>
</div> </div>
</> </>
); );
return <Redirect to="/" />;
} else return <></>;
}; };

View File

@ -1,18 +1,15 @@
import React, { useContext, useEffect, useState } from "react"; import React, { useState } from "react";
import { useLocation } from "wouter"; import { useLocation } from "wouter";
import PlusIcon from "~/assets/plus.svg"; import PlusIcon from "~/assets/plus.svg";
import styles from "./UploadForm.module.css"; import styles from "./UploadForm.module.css";
import { submitFile, validateResponse, validState } from "~/utils/api"; import { submitFile, validateResponse, validState } from "~/utils/api";
import { BookListContext } from "~/context";
import { IPageProps } from "~/types/page"; import { IPageProps } from "~/types/page";
export const UploadForm = ({ setLoading }: IPageProps) => { export const UploadForm = ({ setLoading }: IPageProps) => {
const [error, setError] = useState(""); const [error, setError] = useState("");
const [_, setLocation] = useLocation(); const [_, setLocation] = useLocation();
const [__, saveBook] = useContext(BookListContext);
const processFile = async (file: File | undefined) => { const processFile = async (file: File | undefined) => {
try { try {
if (validState(file)) { if (validState(file)) {
@ -22,10 +19,7 @@ export const UploadForm = ({ setLoading }: IPageProps) => {
const res = await submitFile(file); const res = await submitFile(file);
setLoading(false); setLoading(false);
if (validateResponse(res)) { if (validateResponse(res)) setLocation("/");
saveBook(res);
setLocation("/");
}
} }
} catch (err) { } catch (err) {
setLoading(false); setLoading(false);