Add button to quickly select all chapters

This commit is contained in:
schroda
2023-12-18 21:40:56 +01:00
parent 226f2e170f
commit 90cec35358

View File

@@ -6,11 +6,12 @@
* 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 { Button, CircularProgress, Stack, styled } from '@mui/material'; import { CircularProgress, Stack, styled, Tooltip } from '@mui/material';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import React, { ComponentProps, useMemo, useState } from 'react'; import React, { ComponentProps, useMemo, useState } from 'react';
import { Virtuoso } from 'react-virtuoso'; import { Virtuoso } from 'react-virtuoso';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Checkbox from '@mui/material/Checkbox';
import { TChapter, TManga, TranslationKey } from '@/typings'; import { TChapter, TManga, TranslationKey } from '@/typings';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { ChapterCard } from '@/components/manga/ChapterCard'; import { ChapterCard } from '@/components/manga/ChapterCard';
@@ -24,6 +25,16 @@ import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts'; import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts'; import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';
const ChapterListHeader = styled(Stack)(({ theme }) => ({
margin: 8,
marginBottom: 0,
marginRight: '10px',
minHeight: 40,
[theme.breakpoints.down('md')]: {
marginRight: 0,
},
}));
const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({ const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({
listStyle: 'none', listStyle: 'none',
padding: 0, padding: 0,
@@ -97,6 +108,9 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
const nextChapterIndexToRead = (manga.lastReadChapter?.sourceOrder ?? 0) + 1; const nextChapterIndexToRead = (manga.lastReadChapter?.sourceOrder ?? 0) + 1;
const isLatestChapterRead = manga.chapters.totalCount === manga.lastReadChapter?.sourceOrder; const isLatestChapterRead = manga.chapters.totalCount === manga.lastReadChapter?.sourceOrder;
const areAllChaptersSelected = selection?.length === chapters.length;
const areNoneChaptersSelected = !selection;
const handleSelection = (index: number) => { const handleSelection = (index: number) => {
const chapter = visibleChapters[index]; const chapter = visibleChapters[index];
if (!chapter) return; if (!chapter) return;
@@ -111,14 +125,18 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
} }
}; };
const handleSelectAll = () => { const handleSelectAll = (event: React.ChangeEvent<HTMLInputElement>) => {
if (selection === null) return; const selectAll = event.target.checked;
setSelection(visibleChapters.map((c) => c.id)); switch (selectAll) {
}; case true:
setSelection(visibleChapters.map((c) => c.id));
const handleClear = () => { break;
if (selection === null) return; case false:
setSelection(null); setSelection(null);
break;
default:
break;
}
}; };
const handleFabAction: ComponentProps<typeof SelectionFAB>['onAction'] = (action, actionChapters) => { const handleFabAction: ComponentProps<typeof SelectionFAB>['onAction'] = (action, actionChapters) => {
@@ -219,36 +237,27 @@ export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
return ( return (
<> <>
<Stack direction="column" sx={{ position: 'relative' }}> <Stack direction="column" sx={{ position: 'relative' }}>
<Stack <ChapterListHeader direction="row" alignItems="center" justifyContent="space-between">
direction="row"
alignItems="center"
justifyContent="space-between"
sx={{
m: 1,
mb: 0,
mr: 2,
minHeight: 40,
}}
>
<Typography variant="h5"> <Typography variant="h5">
{`${visibleChapters.length} ${t('chapter.title', { {`${visibleChapters.length} ${t('chapter.title', {
count: visibleChapters.length, count: visibleChapters.length,
})}`} })}`}
</Typography> </Typography>
{selection === null ? ( <Stack direction="row" sx={{ paddingRight: '24px' }}>
<ChaptersToolbarMenu options={options} optionsDispatch={dispatch} /> <ChaptersToolbarMenu options={options} optionsDispatch={dispatch} />
) : ( <Tooltip
<Stack direction="row"> title={t(!areAllChaptersSelected ? 'global.button.select_all' : 'global.button.clear')}
<Button size="small" onClick={handleSelectAll}> >
{t('global.button.select_all')} <Checkbox
</Button> sx={{ padding: '8px' }}
<Button size="small" onClick={handleClear}> checked={areAllChaptersSelected}
{t('global.button.clear')} indeterminate={!areAllChaptersSelected && !areNoneChaptersSelected}
</Button> onChange={handleSelectAll}
</Stack> />
)} </Tooltip>
</Stack> </Stack>
</ChapterListHeader>
{noChaptersFound && <EmptyView message={t('chapter.error.label.no_chapter_found')} />} {noChaptersFound && <EmptyView message={t('chapter.error.label.no_chapter_found')} />}
{noChaptersMatchingFilter && <EmptyView message={t('chapter.error.label.no_matches')} />} {noChaptersMatchingFilter && <EmptyView message={t('chapter.error.label.no_matches')} />}