Adds search by genre to WebUI (#238)
* add pagination to library and fix some prettier issues * add genre search support like tachiyomi android app * Search by genre like you do in tachiyomi mobile app --------- Co-authored-by: akxer <>
This commit is contained in:
@@ -41,19 +41,36 @@ const queryFilter = (query: NullAndUndefined<string>, { title }: IMangaCard): bo
|
|||||||
return title.toLowerCase().includes(query.toLowerCase());
|
return title.toLowerCase().includes(query.toLowerCase());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const queryGenreFilter = (query: NullAndUndefined<string>, { genre }: IMangaCard): boolean => {
|
||||||
|
if (!query) return true;
|
||||||
|
const queries = query.split(',').map((str) => str.toLowerCase().trim());
|
||||||
|
return queries.every((element) => genre.map((el) => el.toLowerCase()).includes(element));
|
||||||
|
};
|
||||||
|
|
||||||
const filterManga = (
|
const filterManga = (
|
||||||
manga: IMangaCard[],
|
manga: IMangaCard[],
|
||||||
query: NullAndUndefined<string>,
|
query: NullAndUndefined<string>,
|
||||||
unread: NullAndUndefined<boolean>,
|
unread: NullAndUndefined<boolean>,
|
||||||
downloaded: NullAndUndefined<boolean>,
|
downloaded: NullAndUndefined<boolean>,
|
||||||
): IMangaCard[] =>
|
): IMangaCard[] => {
|
||||||
manga.filter((m) => {
|
let filteredManga: IMangaCard[] = [];
|
||||||
if (query) {
|
if (query) {
|
||||||
return queryFilter(query, m);
|
const titleFilteredManga = manga.filter((m) => queryFilter(query, m));
|
||||||
|
const genreFilteredManga = manga.filter((m) => queryGenreFilter(query, m));
|
||||||
|
const unique = titleFilteredManga.concat(genreFilteredManga).reduce((acc: Record<number, IMangaCard>, obj) => {
|
||||||
|
const { id } = obj;
|
||||||
|
if (!acc[id]) {
|
||||||
|
acc[id] = obj;
|
||||||
}
|
}
|
||||||
|
return acc;
|
||||||
return downloadedFilter(downloaded, m) && unreadFilter(unread, m);
|
}, {});
|
||||||
});
|
filteredManga = Object.values(unique);
|
||||||
|
}
|
||||||
|
filteredManga = (filteredManga.length ? filteredManga : manga).filter(
|
||||||
|
(m) => downloadedFilter(downloaded, m) && unreadFilter(unread, m),
|
||||||
|
);
|
||||||
|
return filteredManga;
|
||||||
|
};
|
||||||
|
|
||||||
const sortByUnread = (a: IMangaCard, b: IMangaCard): number =>
|
const sortByUnread = (a: IMangaCard, b: IMangaCard): number =>
|
||||||
// eslint-disable-next-line implicit-arrow-linebreak
|
// eslint-disable-next-line implicit-arrow-linebreak
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export default function Reader() {
|
|||||||
id: +mangaId,
|
id: +mangaId,
|
||||||
title: '',
|
title: '',
|
||||||
thumbnailUrl: '',
|
thumbnailUrl: '',
|
||||||
|
genre: [],
|
||||||
});
|
});
|
||||||
const [chapter, setChapter] = useState<IChapter | IPartialChapter>(initialChapter());
|
const [chapter, setChapter] = useState<IChapter | IPartialChapter>(initialChapter());
|
||||||
const [curPage, setCurPage] = useState<number>(0);
|
const [curPage, setCurPage] = useState<number>(0);
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ export default function SourceMangas(props: { popular: boolean }) {
|
|||||||
thumbnailUrl: it.thumbnailUrl,
|
thumbnailUrl: it.thumbnailUrl,
|
||||||
id: it.id,
|
id: it.id,
|
||||||
inLibrary: it.inLibrary,
|
inLibrary: it.inLibrary,
|
||||||
|
genre: it.genre,
|
||||||
})),
|
})),
|
||||||
]);
|
]);
|
||||||
setHasNextPage(data.hasNextPage);
|
setHasNextPage(data.hasNextPage);
|
||||||
|
|||||||
1
src/typings.d.ts
vendored
1
src/typings.d.ts
vendored
@@ -78,6 +78,7 @@ type MetadataKeyValuePair = [AppMetadataKeys, AllowedMetadataValueTypes];
|
|||||||
interface IMangaCard {
|
interface IMangaCard {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
|
genre: string[];
|
||||||
thumbnailUrl: string;
|
thumbnailUrl: string;
|
||||||
unreadCount?: number;
|
unreadCount?: number;
|
||||||
downloadCount?: number;
|
downloadCount?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user