Got rid of book list context. Now book content is served by serviceworker too
This commit is contained in:
parent
09da9a7d60
commit
4f558b8530
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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>
|
|
||||||
);
|
|
||||||
};
|
|
@ -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 <></>;
|
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user