Refactor and fix sorting in library (#197)
This commit is contained in:
@@ -73,6 +73,7 @@ interface IProps {
|
|||||||
manga: IMangaCard
|
manga: IMangaCard
|
||||||
gridLayout: number | undefined
|
gridLayout: number | undefined
|
||||||
dimensions: number
|
dimensions: number
|
||||||
|
inLibraryIndicator?: boolean
|
||||||
}
|
}
|
||||||
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
|
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
|
||||||
const {
|
const {
|
||||||
@@ -82,6 +83,7 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
|
|||||||
},
|
},
|
||||||
gridLayout,
|
gridLayout,
|
||||||
dimensions,
|
dimensions,
|
||||||
|
inLibraryIndicator,
|
||||||
} = props;
|
} = props;
|
||||||
const { options: { showUnreadBadge, showDownloadBadge } } = useLibraryOptionsContext();
|
const { options: { showUnreadBadge, showDownloadBadge } } = useLibraryOptionsContext();
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
|
|||||||
>
|
>
|
||||||
|
|
||||||
<BadgeContainer>
|
<BadgeContainer>
|
||||||
{inLibrary && (
|
{inLibraryIndicator && inLibrary && (
|
||||||
<Typography
|
<Typography
|
||||||
sx={{ backgroundColor: 'primary.dark', zIndex: '1' }}
|
sx={{ backgroundColor: 'primary.dark', zIndex: '1' }}
|
||||||
>
|
>
|
||||||
@@ -145,7 +147,7 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
|
|||||||
<SpinnerImage
|
<SpinnerImage
|
||||||
alt={title}
|
alt={title}
|
||||||
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
|
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
|
||||||
imgStyle={inLibrary
|
imgStyle={inLibraryIndicator && inLibrary
|
||||||
? {
|
? {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|||||||
@@ -26,12 +26,14 @@ export interface IMangaGridProps{
|
|||||||
gridLayout?: number | undefined
|
gridLayout?: number | undefined
|
||||||
horisontal?: boolean | undefined
|
horisontal?: boolean | undefined
|
||||||
noFaces?: boolean | undefined
|
noFaces?: boolean | undefined
|
||||||
|
inLibraryIndicator?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MangaGrid(props: IMangaGridProps) {
|
const MangaGrid: React.FC<IMangaGridProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
mangas, isLoading, message, messageExtra,
|
mangas, isLoading, message, messageExtra,
|
||||||
hasNextPage, lastPageNum, setLastPageNum, gridLayout, horisontal, noFaces,
|
hasNextPage, lastPageNum, setLastPageNum, gridLayout, horisontal, noFaces,
|
||||||
|
inLibraryIndicator,
|
||||||
} = props;
|
} = props;
|
||||||
let mapped;
|
let mapped;
|
||||||
const lastManga = useRef<HTMLDivElement>(null);
|
const lastManga = useRef<HTMLDivElement>(null);
|
||||||
@@ -90,27 +92,16 @@ export default function MangaGrid(props: IMangaGridProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mapped = mangas.map((it, idx) => {
|
mapped = mangas.map((it, idx) => (
|
||||||
if (idx === mangas.length - 1) {
|
<MangaCard
|
||||||
return (
|
key={it.id}
|
||||||
<MangaCard
|
manga={it}
|
||||||
key={it.id}
|
ref={idx === mangas.length - 1 ? lastManga : undefined}
|
||||||
manga={it}
|
gridLayout={gridLayout}
|
||||||
ref={lastManga}
|
dimensions={dimensions}
|
||||||
gridLayout={gridLayout}
|
inLibraryIndicator={inLibraryIndicator}
|
||||||
dimensions={dimensions}
|
/>
|
||||||
/>
|
));
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<MangaCard
|
|
||||||
key={it.id}
|
|
||||||
manga={it}
|
|
||||||
gridLayout={gridLayout}
|
|
||||||
dimensions={dimensions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -135,9 +126,11 @@ export default function MangaGrid(props: IMangaGridProps) {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
MangaGrid.defaultProps = {
|
MangaGrid.defaultProps = {
|
||||||
message: '',
|
message: '',
|
||||||
messageExtra: undefined,
|
messageExtra: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default MangaGrid;
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* 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 MangaGrid, { IMangaGridProps } from 'components/MangaGrid';
|
||||||
import { useLibraryOptionsContext } from 'components/context/LibraryOptionsContext';
|
import { useLibraryOptionsContext } from 'components/context/LibraryOptionsContext';
|
||||||
import { StringParam, useQueryParam } from 'use-query-params';
|
import { StringParam, useQueryParam } from 'use-query-params';
|
||||||
|
|
||||||
const FILTERED_OUT_MESSAGE = 'There are no Manga matching this filter';
|
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) {
|
switch (unread) {
|
||||||
case true:
|
case true:
|
||||||
return !!unreadCount && unreadCount >= 1;
|
return !!unreadCount && unreadCount >= 1;
|
||||||
@@ -22,10 +22,10 @@ function unreadFilter(unread: NullAndUndefined<boolean>, { unreadCount }: IManga
|
|||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function downloadedFilter(downloaded: NullAndUndefined<boolean>,
|
const downloadedFilter = (downloaded: NullAndUndefined<boolean>,
|
||||||
{ downloadCount }: IMangaCard): boolean {
|
{ downloadCount }: IMangaCard): boolean => {
|
||||||
switch (downloaded) {
|
switch (downloaded) {
|
||||||
case true:
|
case true:
|
||||||
return !!downloadCount && downloadCount >= 1;
|
return !!downloadCount && downloadCount >= 1;
|
||||||
@@ -34,70 +34,70 @@ function downloadedFilter(downloaded: NullAndUndefined<boolean>,
|
|||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function queryFilter(query: NullAndUndefined<string>, { title }: IMangaCard): boolean {
|
const queryFilter = (query: NullAndUndefined<string>, { title }: IMangaCard): boolean => {
|
||||||
if (!query) return true;
|
if (!query) return true;
|
||||||
return title.toLowerCase().includes(query.toLowerCase());
|
return title.toLowerCase().includes(query.toLowerCase());
|
||||||
}
|
};
|
||||||
|
|
||||||
function filterManga(mangas: IMangaCard[]): IMangaCard[] {
|
const filterManga = (
|
||||||
const [query] = useQueryParam('query', StringParam);
|
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();
|
const sortByUnread = (a: IMangaCard, b: IMangaCard): number =>
|
||||||
return mangas
|
// eslint-disable-next-line implicit-arrow-linebreak
|
||||||
.filter((manga) => downloadedFilter(downloaded, manga)
|
(a.unreadCount ?? 0) - (b.unreadCount ?? 0);
|
||||||
&& unreadFilter(unread, manga)
|
|
||||||
&& queryFilter(query, manga));
|
|
||||||
}
|
|
||||||
|
|
||||||
function toReadSort(a: IMangaCard, b: IMangaCard): number {
|
const sortByTitle = (a: IMangaCard, b: IMangaCard): number => a.title.localeCompare(b.title);
|
||||||
if (!a.unreadCount) return -1;
|
|
||||||
if (!b.unreadCount) return 1;
|
|
||||||
return a.unreadCount > b.unreadCount ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toSortAlph(a: IMangaCard, b: IMangaCard): number {
|
const sortById = (a: IMangaCard, b: IMangaCard): number => a.id - b.id;
|
||||||
return a.title < b.title ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toSortID(a: IMangaCard, b: IMangaCard): number {
|
const sortManga = (
|
||||||
return a.id > b.id ? 1 : -1;
|
manga: IMangaCard[],
|
||||||
}
|
sort: NullAndUndefined<LibrarySortMode>,
|
||||||
|
desc: NullAndUndefined<boolean>,
|
||||||
|
): IMangaCard[] => {
|
||||||
|
const result = [...manga];
|
||||||
|
|
||||||
function sortManga(mangas: IMangaCard[]): IMangaCard[] {
|
switch (sort) {
|
||||||
const { options: { sorts, sortDesc } } = useLibraryOptionsContext();
|
case 'sortAlph': result.sort(sortByTitle); break;
|
||||||
return (sorts === 'sortID' || sorts === undefined) && !sortDesc ? mangas : mangas.sort((a, b) => {
|
case 'sortID': result.sort(sortById); break;
|
||||||
const c = sortDesc === true ? b : a;
|
case 'sortToRead': result.sort(sortByUnread); break;
|
||||||
const d = sortDesc === true ? a : b;
|
default: break;
|
||||||
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;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function LibraryMangaGrid(props: IMangaGridProps) {
|
if (desc === true) {
|
||||||
const {
|
result.reverse();
|
||||||
mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message,
|
}
|
||||||
} = props;
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const LibraryMangaGrid: React.FC<IMangaGridProps> = ({
|
||||||
|
mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message,
|
||||||
|
}) => {
|
||||||
const [query] = useQueryParam('query', StringParam);
|
const [query] = useQueryParam('query', StringParam);
|
||||||
const { options } = useLibraryOptionsContext();
|
const { options } = useLibraryOptionsContext();
|
||||||
const { unread, downloaded } = options;
|
const { unread, downloaded } = options;
|
||||||
const filteredManga = filterManga(mangas);
|
|
||||||
const sortedManga = sortManga(filteredManga);
|
const sortedManga = useMemo(() => sortManga(mangas, options.sorts, options.sortDesc),
|
||||||
const DoneManga = sortedManga.map((ele) => {
|
[mangas, options.sorts, options.sortDesc]);
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
ele.inLibrary = undefined;
|
const filteredManga = useMemo(() => filterManga(sortedManga, query, unread, downloaded),
|
||||||
return ele;
|
[sortedManga, query, unread, downloaded]);
|
||||||
});
|
|
||||||
const showFilteredOutMessage = (unread != null || downloaded != null || query)
|
const showFilteredOutMessage = (unread != null || downloaded != null || query)
|
||||||
&& filteredManga.length === 0 && mangas.length > 0;
|
&& filteredManga.length === 0 && mangas.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MangaGrid
|
<MangaGrid
|
||||||
mangas={DoneManga}
|
mangas={filteredManga}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
hasNextPage={hasNextPage}
|
hasNextPage={hasNextPage}
|
||||||
lastPageNum={lastPageNum}
|
lastPageNum={lastPageNum}
|
||||||
@@ -106,4 +106,6 @@ export default function LibraryMangaGrid(props: IMangaGridProps) {
|
|||||||
gridLayout={options.gridLayout}
|
gridLayout={options.gridLayout}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default LibraryMangaGrid;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export default function SourceMangaGrid(props: IMangaGridProps) {
|
|||||||
message={showFilteredOutMessage ? FILTERED_OUT_MESSAGE : message}
|
message={showFilteredOutMessage ? FILTERED_OUT_MESSAGE : message}
|
||||||
messageExtra={messageExtra}
|
messageExtra={messageExtra}
|
||||||
gridLayout={gridLayout}
|
gridLayout={gridLayout}
|
||||||
|
inLibraryIndicator
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ export default function SearchAll() {
|
|||||||
horisontal
|
horisontal
|
||||||
noFaces
|
noFaces
|
||||||
message={fetched[id] ? 'No manga was found!' : undefined}
|
message={fetched[id] ? 'No manga was found!' : undefined}
|
||||||
|
inLibraryIndicator
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user