Added random sorting option for library (#1129)
* Update useGetVisibleLibraryMangas.ts Begin implementation of random sort * Update LibraryOptionsPanel.tsx Added random sort option * Update Library.types.ts Adding random to LibrarySortMode types * Moved sorting process to before filter Changed the order of the sorting/filter process. Now sorts through entries before filtering them. * Implementing Reviewer Feedback: Replacing Random Icon Replaced icon with Replay icon from mui. * Update SortRadioInput.tsx Replaced random icon with replay icon from mui to replicate mihon functionality * Fixed Formatting * Update CHANGELOG.md Added proposed changes from pull request. * Update CHANGELOG.md Co-authored-by: schroda <50052685+schroda@users.noreply.github.com> --------- Co-authored-by: jburkh10 <jburkh10@terpmail.umd.edu> Co-authored-by: schroda <50052685+schroda@users.noreply.github.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
import ArrowDownward from '@mui/icons-material/ArrowDownward';
|
||||
import ArrowUpward from '@mui/icons-material/ArrowUpward';
|
||||
import Replay from '@mui/icons-material/Replay';
|
||||
import { memo } from 'react';
|
||||
import type { RadioInputProps } from '@/base/components/inputs/RadioInput.tsx';
|
||||
import { RadioInput } from '@/base/components/inputs/RadioInput.tsx';
|
||||
@@ -22,3 +23,7 @@ export const SortRadioInput = memo(({ sortDescending, ...rest }: IProps) => (
|
||||
{...rest}
|
||||
/>
|
||||
));
|
||||
|
||||
export const SortRadioInputRandom = memo(({ sortDescending, ...rest }: IProps) => (
|
||||
<RadioInput checkedIcon={<Replay color="primary" />} {...rest} />
|
||||
));
|
||||
|
||||
@@ -28,7 +28,8 @@ export type LibrarySortMode =
|
||||
| 'dateAdded'
|
||||
| 'lastRead'
|
||||
| 'latestFetchedChapter'
|
||||
| 'latestUploadedChapter';
|
||||
| 'latestUploadedChapter'
|
||||
| 'random';
|
||||
|
||||
export interface LibraryOptions {
|
||||
// sort options
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useMemo } from 'react';
|
||||
import uniqBy from 'lodash/fp/uniqBy';
|
||||
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
|
||||
import { RadioInput } from '@/base/components/inputs/RadioInput.tsx';
|
||||
import { SortRadioInput } from '@/base/components/inputs/SortRadioInput.tsx';
|
||||
import { SortRadioInput, SortRadioInputRandom } from '@/base/components/inputs/SortRadioInput.tsx';
|
||||
import { ThreeStateCheckboxInput } from '@/base/components/inputs/ThreeStateCheckboxInput.tsx';
|
||||
import { OptionsTabs } from '@/base/components/modals/OptionsTabs.tsx';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
@@ -51,6 +51,7 @@ const SORT_OPTIONS: [LibrarySortMode, MessageDescriptor][] = [
|
||||
['lastRead', msg`Recently read`],
|
||||
['latestFetchedChapter', msg`Latest fetched chapter`],
|
||||
['latestUploadedChapter', msg`Latest uploaded chapter`],
|
||||
['random', msg`Random`],
|
||||
];
|
||||
|
||||
export const LibraryOptionsPanel = ({
|
||||
@@ -174,19 +175,33 @@ export const LibraryOptionsPanel = ({
|
||||
);
|
||||
}
|
||||
if (key === 'sort') {
|
||||
return SORT_OPTIONS.map(([mode, label]) => (
|
||||
<SortRadioInput
|
||||
key={mode}
|
||||
label={t(label)}
|
||||
checked={categoryLibraryOptions.sortBy === mode}
|
||||
sortDescending={categoryLibraryOptions.sortDesc}
|
||||
onClick={() =>
|
||||
mode !== categoryLibraryOptions.sortBy
|
||||
? updateCategoryLibraryOptions('sortBy', mode)
|
||||
: updateCategoryLibraryOptions('sortDesc', !categoryLibraryOptions.sortDesc)
|
||||
}
|
||||
/>
|
||||
));
|
||||
return SORT_OPTIONS.map(([mode, label]) =>
|
||||
mode === 'random' ? (
|
||||
<SortRadioInputRandom
|
||||
key={mode}
|
||||
label={t(label)}
|
||||
checked={categoryLibraryOptions.sortBy === mode}
|
||||
sortDescending={categoryLibraryOptions.sortDesc}
|
||||
onClick={() =>
|
||||
mode !== categoryLibraryOptions.sortBy
|
||||
? updateCategoryLibraryOptions('sortBy', mode)
|
||||
: updateCategoryLibraryOptions('sortDesc', !categoryLibraryOptions.sortDesc)
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<SortRadioInput
|
||||
key={mode}
|
||||
label={t(label)}
|
||||
checked={categoryLibraryOptions.sortBy === mode}
|
||||
sortDescending={categoryLibraryOptions.sortDesc}
|
||||
onClick={() =>
|
||||
mode !== categoryLibraryOptions.sortBy
|
||||
? updateCategoryLibraryOptions('sortBy', mode)
|
||||
: updateCategoryLibraryOptions('sortDesc', !categoryLibraryOptions.sortDesc)
|
||||
}
|
||||
/>
|
||||
),
|
||||
);
|
||||
}
|
||||
if (key === 'display') {
|
||||
return (
|
||||
|
||||
@@ -182,6 +182,8 @@ const sortByNumber = (a: number | string = 0, b: number | string = 0) => Number(
|
||||
|
||||
const sortByString = (a: string, b: string): number => a.localeCompare(b, undefined, { sensitivity: 'base' });
|
||||
|
||||
const sortByRandom = () => Math.floor(Math.random() * 3 - 1);
|
||||
|
||||
type TMangaSort = MangaTitleInfo &
|
||||
MangaInLibraryInfo &
|
||||
MangaUnreadInfo &
|
||||
@@ -213,6 +215,8 @@ const sortManga = <Manga extends TMangaSort>(
|
||||
return (a, b) => sortByNumber(a.latestFetchedChapter?.fetchedAt, b.latestFetchedChapter?.fetchedAt);
|
||||
case 'totalChapters':
|
||||
return (a, b) => sortByNumber(a.chapters.totalCount, b.chapters.totalCount);
|
||||
case 'random':
|
||||
return () => sortByRandom();
|
||||
default:
|
||||
return () => 0;
|
||||
}
|
||||
@@ -256,14 +260,19 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
||||
} = options;
|
||||
const { settings } = useMetadataServerSettings();
|
||||
|
||||
const sortedMangas = useMemo(
|
||||
() => sortManga(mangas, options.sortBy, options.sortDesc),
|
||||
[mangas, options.sortBy, options.sortDesc],
|
||||
);
|
||||
|
||||
const filteredMangas = useMemo(
|
||||
() =>
|
||||
filterMangas(mangas, query, {
|
||||
filterMangas(sortedMangas, query, {
|
||||
...options,
|
||||
ignoreFilters: settings.ignoreFilters,
|
||||
}),
|
||||
[
|
||||
mangas,
|
||||
sortedMangas,
|
||||
query,
|
||||
hasUnreadChapters,
|
||||
hasReadChapters,
|
||||
@@ -276,10 +285,6 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
||||
settings.ignoreFilters,
|
||||
],
|
||||
);
|
||||
const sortedMangas = useMemo(
|
||||
() => sortManga(filteredMangas, options.sortBy, options.sortDesc),
|
||||
[filteredMangas, options.sortBy, options.sortDesc],
|
||||
);
|
||||
|
||||
const isATrackFilterActive = Object.values(options.hasTrackerBinding).some(
|
||||
(trackFilterState) => trackFilterState != null,
|
||||
@@ -299,7 +304,7 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
||||
mangas.length > 0;
|
||||
|
||||
return {
|
||||
visibleMangas: sortedMangas,
|
||||
visibleMangas: filteredMangas,
|
||||
showFilteredOutMessage,
|
||||
filterKey: `${JSON.stringify(options)}${settings.ignoreFilters}`,
|
||||
};
|
||||
|
||||
@@ -2942,6 +2942,10 @@ msgstr "Queued"
|
||||
msgid "Quick settings"
|
||||
msgstr "Quick settings"
|
||||
|
||||
#: src/features/library/components/LibraryOptionsPanel.tsx
|
||||
msgid "Random"
|
||||
msgstr "Random"
|
||||
|
||||
#: src/features/reader/settings/screens/GlobalReaderSettings.tsx
|
||||
#: src/features/settings/screens/Settings.tsx
|
||||
msgid "Reader"
|
||||
|
||||
Reference in New Issue
Block a user