Refactor and fix sorting in library (#197)

This commit is contained in:
Valter Martinek
2022-11-24 21:04:30 +01:00
committed by GitHub
parent 154b357c40
commit 62816338f3
5 changed files with 75 additions and 76 deletions

View File

@@ -73,6 +73,7 @@ interface IProps {
manga: IMangaCard
gridLayout: number | undefined
dimensions: number
inLibraryIndicator?: boolean
}
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
const {
@@ -82,6 +83,7 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
},
gridLayout,
dimensions,
inLibraryIndicator,
} = props;
const { options: { showUnreadBadge, showDownloadBadge } } = useLibraryOptionsContext();
@@ -119,7 +121,7 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
>
<BadgeContainer>
{inLibrary && (
{inLibraryIndicator && inLibrary && (
<Typography
sx={{ backgroundColor: 'primary.dark', zIndex: '1' }}
>
@@ -145,7 +147,7 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
<SpinnerImage
alt={title}
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
imgStyle={inLibrary
imgStyle={inLibraryIndicator && inLibrary
? {
height: '100%',
width: '100%',

View File

@@ -26,12 +26,14 @@ export interface IMangaGridProps{
gridLayout?: number | undefined
horisontal?: boolean | undefined
noFaces?: boolean | undefined
inLibraryIndicator?: boolean
}
export default function MangaGrid(props: IMangaGridProps) {
const MangaGrid: React.FC<IMangaGridProps> = (props) => {
const {
mangas, isLoading, message, messageExtra,
hasNextPage, lastPageNum, setLastPageNum, gridLayout, horisontal, noFaces,
inLibraryIndicator,
} = props;
let mapped;
const lastManga = useRef<HTMLDivElement>(null);
@@ -90,27 +92,16 @@ export default function MangaGrid(props: IMangaGridProps) {
);
}
} else {
mapped = mangas.map((it, idx) => {
if (idx === mangas.length - 1) {
return (
<MangaCard
key={it.id}
manga={it}
ref={lastManga}
gridLayout={gridLayout}
dimensions={dimensions}
/>
);
}
return (
<MangaCard
key={it.id}
manga={it}
gridLayout={gridLayout}
dimensions={dimensions}
/>
);
});
mapped = mangas.map((it, idx) => (
<MangaCard
key={it.id}
manga={it}
ref={idx === mangas.length - 1 ? lastManga : undefined}
gridLayout={gridLayout}
dimensions={dimensions}
inLibraryIndicator={inLibraryIndicator}
/>
));
}
return (
@@ -135,9 +126,11 @@ export default function MangaGrid(props: IMangaGridProps) {
</Grid>
</div>
);
}
};
MangaGrid.defaultProps = {
message: '',
messageExtra: undefined,
};
export default MangaGrid;

View File

@@ -6,14 +6,14 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import React from 'react';
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';
function unreadFilter(unread: NullAndUndefined<boolean>, { unreadCount }: IMangaCard): boolean {
const unreadFilter = (unread: NullAndUndefined<boolean>, { unreadCount }: IMangaCard): boolean => {
switch (unread) {
case true:
return !!unreadCount && unreadCount >= 1;
@@ -22,10 +22,10 @@ function unreadFilter(unread: NullAndUndefined<boolean>, { unreadCount }: IManga
default:
return true;
}
}
};
function downloadedFilter(downloaded: NullAndUndefined<boolean>,
{ downloadCount }: IMangaCard): boolean {
const downloadedFilter = (downloaded: NullAndUndefined<boolean>,
{ downloadCount }: IMangaCard): boolean => {
switch (downloaded) {
case true:
return !!downloadCount && downloadCount >= 1;
@@ -34,70 +34,70 @@ function downloadedFilter(downloaded: NullAndUndefined<boolean>,
default:
return true;
}
}
};
function queryFilter(query: NullAndUndefined<string>, { title }: IMangaCard): boolean {
const queryFilter = (query: NullAndUndefined<string>, { title }: IMangaCard): boolean => {
if (!query) return true;
return title.toLowerCase().includes(query.toLowerCase());
}
};
function filterManga(mangas: IMangaCard[]): IMangaCard[] {
const [query] = useQueryParam('query', StringParam);
const filterManga = (
manga: IMangaCard[],
query: NullAndUndefined<string>,
unread: NullAndUndefined<boolean>,
downloaded: NullAndUndefined<boolean>,
): IMangaCard[] => manga.filter((m) => downloadedFilter(downloaded, m)
&& unreadFilter(unread, m)
&& queryFilter(query, m));
const { options: { downloaded, unread } } = useLibraryOptionsContext();
return mangas
.filter((manga) => downloadedFilter(downloaded, manga)
&& unreadFilter(unread, manga)
&& queryFilter(query, manga));
}
const sortByUnread = (a: IMangaCard, b: IMangaCard): number =>
// eslint-disable-next-line implicit-arrow-linebreak
(a.unreadCount ?? 0) - (b.unreadCount ?? 0);
function toReadSort(a: IMangaCard, b: IMangaCard): number {
if (!a.unreadCount) return -1;
if (!b.unreadCount) return 1;
return a.unreadCount > b.unreadCount ? 1 : -1;
}
const sortByTitle = (a: IMangaCard, b: IMangaCard): number => a.title.localeCompare(b.title);
function toSortAlph(a: IMangaCard, b: IMangaCard): number {
return a.title < b.title ? 1 : -1;
}
const sortById = (a: IMangaCard, b: IMangaCard): number => a.id - b.id;
function toSortID(a: IMangaCard, b: IMangaCard): number {
return a.id > b.id ? 1 : -1;
}
const sortManga = (
manga: IMangaCard[],
sort: NullAndUndefined<LibrarySortMode>,
desc: NullAndUndefined<boolean>,
): IMangaCard[] => {
const result = [...manga];
function sortManga(mangas: IMangaCard[]): IMangaCard[] {
const { options: { sorts, sortDesc } } = useLibraryOptionsContext();
return (sorts === 'sortID' || sorts === undefined) && !sortDesc ? mangas : mangas.sort((a, b) => {
const c = sortDesc === true ? b : a;
const d = sortDesc === true ? a : b;
if (sorts === 'sortToRead') { return toReadSort(c, d); }
if (sorts === 'sortAlph') { return toSortAlph(c, d); }
if (sorts === 'sortID' || sorts === undefined) { return toSortID(c, d); }
return 1;
});
}
switch (sort) {
case 'sortAlph': result.sort(sortByTitle); break;
case 'sortID': result.sort(sortById); break;
case 'sortToRead': result.sort(sortByUnread); break;
default: break;
}
export default function LibraryMangaGrid(props: IMangaGridProps) {
const {
mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message,
} = props;
if (desc === true) {
result.reverse();
}
return result;
};
const LibraryMangaGrid: React.FC<IMangaGridProps> = ({
mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message,
}) => {
const [query] = useQueryParam('query', StringParam);
const { options } = useLibraryOptionsContext();
const { unread, downloaded } = options;
const filteredManga = filterManga(mangas);
const sortedManga = sortManga(filteredManga);
const DoneManga = sortedManga.map((ele) => {
// eslint-disable-next-line no-param-reassign
ele.inLibrary = undefined;
return ele;
});
const sortedManga = useMemo(() => sortManga(mangas, options.sorts, options.sortDesc),
[mangas, options.sorts, options.sortDesc]);
const filteredManga = useMemo(() => filterManga(sortedManga, query, unread, downloaded),
[sortedManga, query, unread, downloaded]);
const showFilteredOutMessage = (unread != null || downloaded != null || query)
&& filteredManga.length === 0 && mangas.length > 0;
return (
<MangaGrid
mangas={DoneManga}
mangas={filteredManga}
isLoading={isLoading}
hasNextPage={hasNextPage}
lastPageNum={lastPageNum}
@@ -106,4 +106,6 @@ export default function LibraryMangaGrid(props: IMangaGridProps) {
gridLayout={options.gridLayout}
/>
);
}
};
export default LibraryMangaGrid;

View File

@@ -34,6 +34,7 @@ export default function SourceMangaGrid(props: IMangaGridProps) {
message={showFilteredOutMessage ? FILTERED_OUT_MESSAGE : message}
messageExtra={messageExtra}
gridLayout={gridLayout}
inLibraryIndicator
/>
);
}