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:
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
- (**Reader**) Add setting to keep the screen on while reading
|
- (**Reader**) Add setting to keep the screen on while reading
|
||||||
- (**Extension**) Support installing external JARs
|
- (**Extension**) Support installing external JARs
|
||||||
- (**Reader**) Add auto background color setting
|
- (**Reader**) Add auto background color setting
|
||||||
|
- (**Library**) Add random sort option to library
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import ArrowDownward from '@mui/icons-material/ArrowDownward';
|
import ArrowDownward from '@mui/icons-material/ArrowDownward';
|
||||||
import ArrowUpward from '@mui/icons-material/ArrowUpward';
|
import ArrowUpward from '@mui/icons-material/ArrowUpward';
|
||||||
|
import Replay from '@mui/icons-material/Replay';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import type { RadioInputProps } from '@/base/components/inputs/RadioInput.tsx';
|
import type { RadioInputProps } from '@/base/components/inputs/RadioInput.tsx';
|
||||||
import { RadioInput } 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}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
export const SortRadioInputRandom = memo(({ sortDescending, ...rest }: IProps) => (
|
||||||
|
<RadioInput checkedIcon={<Replay color="primary" />} {...rest} />
|
||||||
|
));
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ export type LibrarySortMode =
|
|||||||
| 'dateAdded'
|
| 'dateAdded'
|
||||||
| 'lastRead'
|
| 'lastRead'
|
||||||
| 'latestFetchedChapter'
|
| 'latestFetchedChapter'
|
||||||
| 'latestUploadedChapter';
|
| 'latestUploadedChapter'
|
||||||
|
| 'random';
|
||||||
|
|
||||||
export interface LibraryOptions {
|
export interface LibraryOptions {
|
||||||
// sort options
|
// sort options
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { useMemo } from 'react';
|
|||||||
import uniqBy from 'lodash/fp/uniqBy';
|
import uniqBy from 'lodash/fp/uniqBy';
|
||||||
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
|
import { CheckboxInput } from '@/base/components/inputs/CheckboxInput.tsx';
|
||||||
import { RadioInput } from '@/base/components/inputs/RadioInput.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 { ThreeStateCheckboxInput } from '@/base/components/inputs/ThreeStateCheckboxInput.tsx';
|
||||||
import { OptionsTabs } from '@/base/components/modals/OptionsTabs.tsx';
|
import { OptionsTabs } from '@/base/components/modals/OptionsTabs.tsx';
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
@@ -51,6 +51,7 @@ const SORT_OPTIONS: [LibrarySortMode, MessageDescriptor][] = [
|
|||||||
['lastRead', msg`Recently read`],
|
['lastRead', msg`Recently read`],
|
||||||
['latestFetchedChapter', msg`Latest fetched chapter`],
|
['latestFetchedChapter', msg`Latest fetched chapter`],
|
||||||
['latestUploadedChapter', msg`Latest uploaded chapter`],
|
['latestUploadedChapter', msg`Latest uploaded chapter`],
|
||||||
|
['random', msg`Random`],
|
||||||
];
|
];
|
||||||
|
|
||||||
export const LibraryOptionsPanel = ({
|
export const LibraryOptionsPanel = ({
|
||||||
@@ -174,7 +175,20 @@ export const LibraryOptionsPanel = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (key === 'sort') {
|
if (key === 'sort') {
|
||||||
return SORT_OPTIONS.map(([mode, label]) => (
|
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
|
<SortRadioInput
|
||||||
key={mode}
|
key={mode}
|
||||||
label={t(label)}
|
label={t(label)}
|
||||||
@@ -186,7 +200,8 @@ export const LibraryOptionsPanel = ({
|
|||||||
: updateCategoryLibraryOptions('sortDesc', !categoryLibraryOptions.sortDesc)
|
: updateCategoryLibraryOptions('sortDesc', !categoryLibraryOptions.sortDesc)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (key === 'display') {
|
if (key === 'display') {
|
||||||
return (
|
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 sortByString = (a: string, b: string): number => a.localeCompare(b, undefined, { sensitivity: 'base' });
|
||||||
|
|
||||||
|
const sortByRandom = () => Math.floor(Math.random() * 3 - 1);
|
||||||
|
|
||||||
type TMangaSort = MangaTitleInfo &
|
type TMangaSort = MangaTitleInfo &
|
||||||
MangaInLibraryInfo &
|
MangaInLibraryInfo &
|
||||||
MangaUnreadInfo &
|
MangaUnreadInfo &
|
||||||
@@ -213,6 +215,8 @@ const sortManga = <Manga extends TMangaSort>(
|
|||||||
return (a, b) => sortByNumber(a.latestFetchedChapter?.fetchedAt, b.latestFetchedChapter?.fetchedAt);
|
return (a, b) => sortByNumber(a.latestFetchedChapter?.fetchedAt, b.latestFetchedChapter?.fetchedAt);
|
||||||
case 'totalChapters':
|
case 'totalChapters':
|
||||||
return (a, b) => sortByNumber(a.chapters.totalCount, b.chapters.totalCount);
|
return (a, b) => sortByNumber(a.chapters.totalCount, b.chapters.totalCount);
|
||||||
|
case 'random':
|
||||||
|
return () => sortByRandom();
|
||||||
default:
|
default:
|
||||||
return () => 0;
|
return () => 0;
|
||||||
}
|
}
|
||||||
@@ -256,14 +260,19 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
|||||||
} = options;
|
} = options;
|
||||||
const { settings } = useMetadataServerSettings();
|
const { settings } = useMetadataServerSettings();
|
||||||
|
|
||||||
|
const sortedMangas = useMemo(
|
||||||
|
() => sortManga(mangas, options.sortBy, options.sortDesc),
|
||||||
|
[mangas, options.sortBy, options.sortDesc],
|
||||||
|
);
|
||||||
|
|
||||||
const filteredMangas = useMemo(
|
const filteredMangas = useMemo(
|
||||||
() =>
|
() =>
|
||||||
filterMangas(mangas, query, {
|
filterMangas(sortedMangas, query, {
|
||||||
...options,
|
...options,
|
||||||
ignoreFilters: settings.ignoreFilters,
|
ignoreFilters: settings.ignoreFilters,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
mangas,
|
sortedMangas,
|
||||||
query,
|
query,
|
||||||
hasUnreadChapters,
|
hasUnreadChapters,
|
||||||
hasReadChapters,
|
hasReadChapters,
|
||||||
@@ -276,10 +285,6 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
|||||||
settings.ignoreFilters,
|
settings.ignoreFilters,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
const sortedMangas = useMemo(
|
|
||||||
() => sortManga(filteredMangas, options.sortBy, options.sortDesc),
|
|
||||||
[filteredMangas, options.sortBy, options.sortDesc],
|
|
||||||
);
|
|
||||||
|
|
||||||
const isATrackFilterActive = Object.values(options.hasTrackerBinding).some(
|
const isATrackFilterActive = Object.values(options.hasTrackerBinding).some(
|
||||||
(trackFilterState) => trackFilterState != null,
|
(trackFilterState) => trackFilterState != null,
|
||||||
@@ -299,7 +304,7 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
|||||||
mangas.length > 0;
|
mangas.length > 0;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
visibleMangas: sortedMangas,
|
visibleMangas: filteredMangas,
|
||||||
showFilteredOutMessage,
|
showFilteredOutMessage,
|
||||||
filterKey: `${JSON.stringify(options)}${settings.ignoreFilters}`,
|
filterKey: `${JSON.stringify(options)}${settings.ignoreFilters}`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2942,6 +2942,10 @@ msgstr "Queued"
|
|||||||
msgid "Quick settings"
|
msgid "Quick settings"
|
||||||
msgstr "Quick settings"
|
msgstr "Quick settings"
|
||||||
|
|
||||||
|
#: src/features/library/components/LibraryOptionsPanel.tsx
|
||||||
|
msgid "Random"
|
||||||
|
msgstr "Random"
|
||||||
|
|
||||||
#: src/features/reader/settings/screens/GlobalReaderSettings.tsx
|
#: src/features/reader/settings/screens/GlobalReaderSettings.tsx
|
||||||
#: src/features/settings/screens/Settings.tsx
|
#: src/features/settings/screens/Settings.tsx
|
||||||
msgid "Reader"
|
msgid "Reader"
|
||||||
|
|||||||
Reference in New Issue
Block a user