MCPcopy
hub / github.com/shiyi-0x7f/o-lib / FavoritesPage

Function FavoritesPage

src/pages/FavoritesPage.tsx:48–396  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

46}
47
48export default function FavoritesPage() {
49 const [favorites, setFavorites] = useState<FavoriteBook[]>([]);
50 const [loading, setLoading] = useState(true);
51 const [removingIds, setRemovingIds] = useState<Set<string>>(new Set());
52 const [downloadingIds, setDownloadingIds] = useState<Set<string>>(new Set());
53 const [selectedBook, setSelectedBook] = useState<any>(null);
54 const [limitError, setLimitError] = useState<string | null>(null);
55 const [searchQuery, setSearchQuery] = useState("");
56
57 const { getCoverUrl: getCoverUrlRaw, handleCoverError } = useCoverCache();
58
59 useEffect(() => {
60 loadFavorites();
61 }, []);
62
63
64
65 const getCoverUrl = (book: FavoriteBook): string | undefined => {
66 return getCoverUrlRaw(book.book_id, book.cover);
67 };
68
69 const loadFavorites = async () => {
70 setLoading(true);
71 try {
72 const result: FavoriteBook[] = await invoke("get_favorites", { page: 1, limit: 200 });
73 setFavorites(result);
74 } catch (err) {
75 console.error("Failed to load favorites:", err);
76 }
77 setLoading(false);
78 };
79
80 const handleRemove = async (bookId: string) => {
81 setRemovingIds(prev => new Set(prev).add(bookId));
82 try {
83 await invoke("remove_favorite", { bookId });
84 setFavorites(prev => prev.filter(f => f.book_id !== bookId));
85 toast.success("已取消收藏");
86 } catch (err) {
87 console.error("Failed to remove favorite:", err);
88 toast.error("取消收藏失败");
89 }
90 setRemovingIds(prev => { const n = new Set(prev); n.delete(bookId); return n; });
91 };
92
93 const handleDownload = async (book: FavoriteBook) => {
94 if (downloadingIds.has(book.book_id)) return;
95 setDownloadingIds(prev => new Set(prev).add(book.book_id));
96 try {
97 const result = await invoke("download_book", {
98 bookId: book.book_id, hashId: book.hash || "",
99 title: book.title || "Unknown", extension: book.extension || "pdf",
100 }) as string;
101 if (result.startsWith("dispatched:")) {
102 const method = result.split(":")[1];
103 const labels: Record<string, string> = {
104 browser: "已发送到浏览器",
105 idm: "已发送到 IDM",

Callers

nothing calls this directly

Calls 8

useCoverCacheFunction · 0.90
loadFavoritesFunction · 0.85
getCoverUrlFunction · 0.85
handleRemoveFunction · 0.85
toBookObjFunction · 0.85
handleDownloadFunction · 0.70
formatSizeFunction · 0.70
formatDateFunction · 0.70

Tested by

no test coverage detected