/* * Copyright (C) Contributors to the Suwayomi project * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import React, { useMemo } from 'react'; import MangaGrid, { IMangaGridProps } from 'components/MangaGrid'; import { useLibraryOptionsContext } from 'components/context/LibraryOptionsContext'; import { StringParam, useQueryParam } from 'use-query-params'; const FILTERED_OUT_MESSAGE = 'There are no Manga matching this filter'; const unreadFilter = (unread: NullAndUndefined, { unreadCount }: IMangaCard): boolean => { switch (unread) { case true: return !!unreadCount && unreadCount >= 1; case false: return unreadCount === 0; default: return true; } }; const downloadedFilter = ( downloaded: NullAndUndefined, { downloadCount }: IMangaCard, ): boolean => { switch (downloaded) { case true: return !!downloadCount && downloadCount >= 1; case false: return downloadCount === 0; default: return true; } }; const queryFilter = (query: NullAndUndefined, { title }: IMangaCard): boolean => { if (!query) return true; return title.toLowerCase().includes(query.toLowerCase()); }; const filterManga = ( manga: IMangaCard[], query: NullAndUndefined, unread: NullAndUndefined, downloaded: NullAndUndefined, ): IMangaCard[] => manga.filter((m) => { if (query) { return queryFilter(query, m); } return downloadedFilter(downloaded, m) && unreadFilter(unread, m); }); const sortByUnread = (a: IMangaCard, b: IMangaCard): number => // eslint-disable-next-line implicit-arrow-linebreak (a.unreadCount ?? 0) - (b.unreadCount ?? 0); const sortByTitle = (a: IMangaCard, b: IMangaCard): number => a.title.localeCompare(b.title); const sortById = (a: IMangaCard, b: IMangaCard): number => a.id - b.id; const sortManga = ( manga: IMangaCard[], sort: NullAndUndefined, desc: NullAndUndefined, ): IMangaCard[] => { const result = [...manga]; switch (sort) { case 'sortAlph': result.sort(sortByTitle); break; case 'sortID': result.sort(sortById); break; case 'sortToRead': result.sort(sortByUnread); break; default: break; } if (desc === true) { result.reverse(); } return result; }; const LibraryMangaGrid: React.FC = ({ mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message, lastLibraryUpdate, }) => { const [query] = useQueryParam('query', StringParam); const { options } = useLibraryOptionsContext(); const { unread, downloaded } = options; const sortedManga = useMemo( () => sortManga(mangas, options.sorts, options.sortDesc), [mangas, lastLibraryUpdate, options.sorts, options.sortDesc], ); const filteredManga = useMemo( () => filterManga(sortedManga, query, unread, downloaded), [sortedManga, lastLibraryUpdate, query, unread, downloaded], ); const showFilteredOutMessage = (unread != null || downloaded != null || query) && filteredManga.length === 0 && mangas.length > 0; return ( ); }; export default LibraryMangaGrid;