Add support to load chapter lists from databases

This commit is contained in:
2026-02-18 10:27:27 +08:00
parent e160b1da53
commit a2dbabc5ae
7 changed files with 204 additions and 11 deletions

View File

@@ -1,8 +1,12 @@
import { Affix, Flex, Space, Tag, Typography, Switch } from "antd";
import { Affix, Flex, Space, Tag, Typography, Switch, Skeleton, Result, Button } from "antd";
import { useBookInfo } from "./BookInfoProvider";
import styles from './BookIndex.module.css';
import { useBookStatus } from "./BookStatusProvider";
import { loadChapterListsIfNeeded, useBookStatus } from "./BookStatusProvider";
import VolumesList from "./VolumesList";
import { useEffect, useState } from "react";
import { useDb } from "../dbProvider";
import type { Volume } from "../../qdtypes";
import { get_new_volumes } from "../../utils/qd";
const { Paragraph, Link } = Typography;
@@ -10,10 +14,30 @@ const QD_BOOK_TAG_COLOR = ['blue', 'cyan', 'orange'];
export default function BookIndex() {
const bookInfo = useBookInfo();
const db = useDb();
const [bookStatus, setBookStatus] = useBookStatus();
const [err, setErr] = useState<string | null>(null);
function setShowSavedOnly(showSavedOnly: boolean) {
setBookStatus({ ...bookStatus, showSavedOnly });
}
function handle() {
if (err) {
setErr(null);
}
loadChapterListsIfNeeded(bookInfo.id, bookStatus, setBookStatus, db).catch(e => {
console.log(e);
setErr(e instanceof Error ? e.message : String(e));
});
}
useEffect(() => {
handle();
}, [bookInfo.id]);
let vols: Volume[] = bookInfo.volumes;
if (bookStatus.chapterLists) {
vols = get_new_volumes(bookStatus.chapterLists, bookInfo.volumes, !bookStatus.showSavedOnly);
} else if (bookStatus.showSavedOnly) {
vols = [];
}
return (
<div className={styles.c}>
<Flex justify="center" align="center">
@@ -41,7 +65,9 @@ export default function BookIndex() {
<Switch checked={bookStatus.showSavedOnly} onChange={setShowSavedOnly} checkedChildren={"仅显示已保存章节"} unCheckedChildren={"显示所有章节"} />
</Flex>
</Affix>
{!bookStatus.showSavedOnly && <VolumesList bookId={bookInfo.id} volumes={bookInfo.volumes} />}
{bookStatus.showSavedOnly && err && <Result status="error" title="加载章节列表失败" subTitle={err} extra={<Button type="primary" onClick={handle}></Button>} />}
{bookStatus.showSavedOnly && !bookStatus.chapterLists && !err && <Skeleton active />}
{vols.length > 0 && <VolumesList bookId={bookInfo.id} volumes={vols} />}
</div>
);
}

View File

@@ -1,7 +1,10 @@
import { createContext, useContext, Dispatch } from "react";
import { createContext, useContext, Dispatch, SetStateAction } from "react";
import { QdChapterSimpleInfo } from "../../types";
import { Db } from "../../db/interfaces";
export type BookStatus = {
showSavedOnly: boolean;
chapterLists?: QdChapterSimpleInfo[];
}
export function createBookStatus(): BookStatus {
@@ -10,7 +13,18 @@ export function createBookStatus(): BookStatus {
}
}
export const BookStatusContext = createContext<[BookStatus, Dispatch<BookStatus>]>(null as any);
export async function loadChapterLists(bookId: number, setBookStatus: Dispatch<SetStateAction<BookStatus>>, db: Db) {
const list = await db.getChapterSimpleInfos(bookId);
setBookStatus((status) => ({ ...status, chapterLists: list }));
}
export async function loadChapterListsIfNeeded(bookId: number, bookStatus: BookStatus, setBookStatus: Dispatch<SetStateAction<BookStatus>>, db: Db) {
if (!bookStatus.chapterLists) {
await loadChapterLists(bookId, setBookStatus, db);
}
}
export const BookStatusContext = createContext<[BookStatus, Dispatch<SetStateAction<BookStatus>>]>(null as any);
export function useBookStatus() {
return useContext(BookStatusContext);