Merge manga action menus (#527)

This commit is contained in:
schroda
2023-12-30 14:26:50 +01:00
committed by GitHub
parent a3a52064cc
commit ecea80f41e
8 changed files with 225 additions and 249 deletions

View File

@@ -12,7 +12,6 @@ import Typography from '@mui/material/Typography';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Avatar, Box, CardContent, Stack, styled, Tooltip } from '@mui/material'; import { Avatar, Box, CardContent, Stack, styled, Tooltip } from '@mui/material';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import React from 'react';
import PopupState, { bindMenu } from 'material-ui-popup-state'; import PopupState, { bindMenu } from 'material-ui-popup-state';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext'; import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
@@ -21,7 +20,8 @@ import { TManga, TPartialManga } from '@/typings.ts';
import { ContinueReadingButton } from '@/components/manga/ContinueReadingButton.tsx'; import { ContinueReadingButton } from '@/components/manga/ContinueReadingButton.tsx';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts'; import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { MangaOptionButton } from '@/components/manga/MangaOptionButton.tsx'; import { MangaOptionButton } from '@/components/manga/MangaOptionButton.tsx';
import { MangaActionMenu } from '@/components/manga/MangaActionMenu.tsx'; import { MangaActionMenuItems, SingleModeProps } from '@/components/manga/MangaActionMenuItems.tsx';
import { Menu } from '@/components/manga/Menu.tsx';
const BottomGradient = styled('div')({ const BottomGradient = styled('div')({
position: 'absolute', position: 'absolute',
@@ -270,11 +270,16 @@ export const MangaCard = (props: IProps) => {
</Box> </Box>
</Link> </Link>
{!!handleSelection && popupState.isOpen && ( {!!handleSelection && popupState.isOpen && (
<MangaActionMenu <Menu {...bindMenu(popupState)}>
{...bindMenu(popupState)} {(onClose, setHideMenu) => (
manga={manga as React.ComponentProps<typeof MangaActionMenu>['manga']} <MangaActionMenuItems
handleSelection={handleSelection} manga={manga as SingleModeProps['manga']}
/> handleSelection={handleSelection}
onClose={onClose}
setHideMenu={setHideMenu}
/>
)}
</Menu>
)} )}
</> </>
)} )}
@@ -380,11 +385,16 @@ export const MangaCard = (props: IProps) => {
</CardActionArea> </CardActionArea>
</Card> </Card>
{!!handleSelection && popupState.isOpen && ( {!!handleSelection && popupState.isOpen && (
<MangaActionMenu <Menu {...bindMenu(popupState)}>
{...bindMenu(popupState)} {(onClose, setHideMenu) => (
manga={manga as React.ComponentProps<typeof MangaActionMenu>['manga']} <MangaActionMenuItems
handleSelection={handleSelection} manga={manga as SingleModeProps['manga']}
/> handleSelection={handleSelection}
onClose={onClose}
setHideMenu={setHideMenu}
/>
)}
</Menu>
)} )}
</> </>
)} )}

View File

@@ -1,117 +0,0 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import Menu from '@mui/material/Menu';
import CheckBoxOutlineBlank from '@mui/icons-material/CheckBoxOutlineBlank';
import Delete from '@mui/icons-material/Delete';
import Download from '@mui/icons-material/Download';
import RemoveDone from '@mui/icons-material/RemoveDone';
import Done from '@mui/icons-material/Done';
import { useTranslation } from 'react-i18next';
import { bindMenu } from 'material-ui-popup-state';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import Label from '@mui/icons-material/Label';
import { useState } from 'react';
import { TManga } from '@/typings.ts';
import { MangaAction, MangaDownloadInfo, Mangas, MangaUnreadInfo } from '@/lib/data/Mangas.ts';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx';
import { MenuItem } from '@/components/manga/MenuItem.tsx';
export const MangaActionMenu = ({
manga,
handleSelection,
...bindMenuProps
}: {
manga: Pick<TManga, 'id'> & MangaDownloadInfo & MangaUnreadInfo;
handleSelection?: SelectableCollectionReturnType<TManga['id']>['handleSelection'];
} & ReturnType<typeof bindMenu>) => {
const { t } = useTranslation();
const [isCategorySelectOpen, setIsCategorySelectOpen] = useState(false);
const isFullyDownloaded = manga.downloadCount === manga.chapters.totalCount;
const hasDownloadedChapters = !!manga.downloadCount;
const hasUnreadChapters = !!manga.unreadCount;
const hasReadChapters = manga.unreadCount !== manga.chapters.totalCount;
const handleSelect = () => {
handleSelection?.(manga.id, true);
bindMenuProps.onClose();
};
const performAction = (action: MangaAction) => {
Mangas.performAction(action, [manga.id], {
wasManuallyMarkedAsRead: true,
}).catch(() => {});
bindMenuProps.onClose();
};
return (
<>
<Menu {...bindMenuProps} open={bindMenuProps.open && !isCategorySelectOpen}>
{!!handleSelection && (
<MenuItem
onClick={handleSelect}
Icon={CheckBoxOutlineBlank}
title={t('chapter.action.label.select')}
/>
)}
{!isFullyDownloaded && (
<MenuItem
onClick={() => performAction('download')}
Icon={Download}
title={t('chapter.action.download.add.label.action')}
/>
)}
{hasDownloadedChapters && (
<MenuItem
onClick={() => performAction('delete')}
Icon={Delete}
title={t('chapter.action.download.delete.label.action')}
/>
)}
{hasUnreadChapters && (
<MenuItem
onClick={() => performAction('mark_as_read')}
Icon={Done}
title={t('chapter.action.mark_as_read.add.label.action.current')}
/>
)}
{hasReadChapters && (
<MenuItem
onClick={() => performAction('mark_as_unread')}
Icon={RemoveDone}
title={t('chapter.action.mark_as_read.remove.label.action')}
/>
)}
<MenuItem
onClick={() => setIsCategorySelectOpen(true)}
Icon={Label}
title={t('manga.action.category.label.action')}
/>
<MenuItem
onClick={() => performAction('remove_from_library')}
Icon={FavoriteBorderIcon}
title={t('manga.action.library.remove.label.action')}
/>
</Menu>
{isCategorySelectOpen && (
<CategorySelect
open={isCategorySelectOpen}
onClose={() => {
setIsCategorySelectOpen(false);
bindMenuProps.onClose();
}}
mangaId={manga.id}
/>
)}
</>
);
};

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import CheckBoxOutlineBlank from '@mui/icons-material/CheckBoxOutlineBlank';
import Delete from '@mui/icons-material/Delete';
import Download from '@mui/icons-material/Download';
import RemoveDone from '@mui/icons-material/RemoveDone';
import Done from '@mui/icons-material/Done';
import { useTranslation } from 'react-i18next';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import Label from '@mui/icons-material/Label';
import { useMemo, useState } from 'react';
import { t as translate } from 'i18next';
import { TManga } from '@/typings.ts';
import { actionToTranslationKey, MangaAction, MangaDownloadInfo, Mangas, MangaUnreadInfo } from '@/lib/data/Mangas.ts';
import { SelectableCollectionReturnType } from '@/components/collection/useSelectableCollection.ts';
import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx';
import { MenuItem } from '@/components/manga/MenuItem.tsx';
const ACTION_DISABLES_SELECTION_MODE: MangaAction[] = ['remove_from_library'] as const;
const createGetMenuItemTitle =
(isSingleMode: boolean) =>
(action: MangaAction, count: number): string => {
const countSuffix = count > 0 ? ` (${count})` : '';
return `${translate(
actionToTranslationKey[action].action[isSingleMode ? 'single' : 'selected'],
)}${countSuffix}`;
};
const createShouldShowMenuItem =
(isSingleMode: boolean) =>
(shouldBeVisible: boolean = false): boolean =>
isSingleMode ? shouldBeVisible : true;
const createIsMenuItemDisabled =
(isSingleMode: boolean) =>
(shouldBeDisabled: boolean): boolean =>
isSingleMode ? false : shouldBeDisabled;
type BaseProps = { onClose: (selectionModeState: boolean) => void; setHideMenu: (hide: boolean) => void };
export type SingleModeProps = {
manga: Pick<TManga, 'id'> & MangaDownloadInfo & MangaUnreadInfo;
handleSelection?: SelectableCollectionReturnType<TManga['id']>['handleSelection'];
};
type SelectModeProps = {
selectedMangas: TManga[];
};
type Props =
| (BaseProps & SingleModeProps & PropertiesNever<SelectModeProps>)
| (BaseProps & PropertiesNever<SingleModeProps> & SelectModeProps);
export const MangaActionMenuItems = ({ manga, handleSelection, selectedMangas = [], onClose, setHideMenu }: Props) => {
const { t } = useTranslation();
const [isCategorySelectOpen, setIsCategorySelectOpen] = useState(false);
const isSingleMode = !!manga;
const getMenuItemTitle = createGetMenuItemTitle(isSingleMode);
const shouldShowMenuItem = createShouldShowMenuItem(isSingleMode);
const isMenuItemDisabled = createIsMenuItemDisabled(isSingleMode);
const isFullyDownloaded = !!manga && manga.downloadCount === manga.chapters.totalCount;
const hasDownloadedChapters = !!manga?.downloadCount;
const hasUnreadChapters = !!manga?.unreadCount;
const hasReadChapters = !!manga && manga.unreadCount !== manga.chapters.totalCount;
const handleSelect = () => {
handleSelection?.(manga.id, true);
onClose(true);
};
const performAction = (action: MangaAction, mangas: TManga[]) => {
Mangas.performAction(action, manga ? [manga.id] : Mangas.getIds(mangas), {
wasManuallyMarkedAsRead: true,
}).catch(() => {});
onClose(!ACTION_DISABLES_SELECTION_MODE.includes(action));
};
const { downloadableMangas, downloadedMangas, unreadMangas, readMangas } = useMemo(
() => ({
downloadableMangas: [
...Mangas.getNotDownloaded(selectedMangas),
...Mangas.getPartiallyDownloaded(selectedMangas),
],
downloadedMangas: [
...Mangas.getPartiallyDownloaded(selectedMangas),
...Mangas.getFullyDownloaded(selectedMangas),
],
unreadMangas: [...Mangas.getUnread(selectedMangas), ...Mangas.getPartiallyRead(selectedMangas)],
readMangas: [...Mangas.getPartiallyRead(selectedMangas), ...Mangas.getFullyRead(selectedMangas)],
}),
[selectedMangas],
);
return (
<>
{!!handleSelection && isSingleMode && (
<MenuItem onClick={handleSelect} Icon={CheckBoxOutlineBlank} title={t('chapter.action.label.select')} />
)}
{shouldShowMenuItem(!isFullyDownloaded) && (
<MenuItem
Icon={Download}
isDisabled={isMenuItemDisabled(!downloadableMangas.length)}
onClick={() => performAction('download', downloadableMangas)}
title={getMenuItemTitle('download', downloadableMangas.length)}
/>
)}
{shouldShowMenuItem(hasDownloadedChapters) && (
<MenuItem
Icon={Delete}
isDisabled={isMenuItemDisabled(!downloadedMangas.length)}
onClick={() => performAction('delete', downloadedMangas)}
title={getMenuItemTitle('delete', downloadedMangas.length)}
/>
)}
{shouldShowMenuItem(hasUnreadChapters) && (
<MenuItem
Icon={Done}
isDisabled={isMenuItemDisabled(!unreadMangas.length)}
onClick={() => performAction('mark_as_read', unreadMangas)}
title={getMenuItemTitle('mark_as_read', unreadMangas.length)}
/>
)}
{shouldShowMenuItem(hasReadChapters) && (
<MenuItem
Icon={RemoveDone}
isDisabled={isMenuItemDisabled(!readMangas.length)}
onClick={() => performAction('mark_as_unread', readMangas)}
title={getMenuItemTitle('mark_as_unread', readMangas.length)}
/>
)}
<MenuItem
onClick={() => {
setIsCategorySelectOpen(true);
setHideMenu(true);
}}
Icon={Label}
title={t('manga.action.category.label.action')}
/>
<MenuItem
onClick={() => performAction('remove_from_library', selectedMangas)}
Icon={FavoriteBorderIcon}
title={t('manga.action.library.remove.label.action')}
/>
{isCategorySelectOpen && (
<CategorySelect
open={isCategorySelectOpen}
onClose={() => {
setIsCategorySelectOpen(false);
onClose(true);
}}
mangaId={manga?.id as undefined} // either mangaId or mangaIds is undefined, however, ts is not able to infer it correctly and raises an error
mangaIds={Mangas.getIds(selectedMangas)}
/>
)}
</>
);
};

View File

@@ -1,109 +0,0 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import Download from '@mui/icons-material/Download';
import Delete from '@mui/icons-material/Delete';
import Done from '@mui/icons-material/Done';
import RemoveDone from '@mui/icons-material/RemoveDone';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import Label from '@mui/icons-material/Label';
import { useMemo, useState } from 'react';
import { t as translate } from 'i18next';
import { MenuItem } from '@/components/manga/MenuItem.tsx';
import { TManga } from '@/typings.ts';
import { actionToTranslationKey, MangaAction, Mangas } from '@/lib/data/Mangas.ts';
import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx';
const ACTION_DISABLES_SELECTION_MODE: MangaAction[] = ['remove_from_library'] as const;
const getMenuItemTitle = (action: MangaAction, count: number): string => {
const countSuffix = count > 0 ? ` (${count})` : '';
return `${translate(actionToTranslationKey[action].action.selected)}${countSuffix}`;
};
export const MangasSelectionFABActionItems = ({
selectedMangas,
handleClose,
}: {
selectedMangas: TManga[];
handleClose: (selectionModeState: boolean) => void;
}) => {
const [isCategorySelectOpen, setIsCategorySelectOpen] = useState(false);
const handleAction = (action: MangaAction, mangas: TManga[]) => {
Mangas.performAction(action, Mangas.getIds(mangas), {
wasManuallyMarkedAsRead: true,
}).catch(() => {});
handleClose(!ACTION_DISABLES_SELECTION_MODE.includes(action));
};
const { downloadableMangas, downloadedMangas, unreadMangas, readMangas } = useMemo(
() => ({
downloadableMangas: [
...Mangas.getNotDownloaded(selectedMangas),
...Mangas.getPartiallyDownloaded(selectedMangas),
],
downloadedMangas: [
...Mangas.getPartiallyDownloaded(selectedMangas),
...Mangas.getFullyDownloaded(selectedMangas),
],
unreadMangas: [...Mangas.getUnread(selectedMangas), ...Mangas.getPartiallyRead(selectedMangas)],
readMangas: [...Mangas.getPartiallyRead(selectedMangas), ...Mangas.getFullyRead(selectedMangas)],
}),
[selectedMangas],
);
return (
<>
<MenuItem
Icon={Download}
isDisabled={!downloadableMangas.length}
onClick={() => handleAction('download', downloadableMangas)}
title={getMenuItemTitle('download', downloadableMangas.length)}
/>
<MenuItem
Icon={Delete}
isDisabled={!downloadedMangas.length}
onClick={() => handleAction('delete', downloadedMangas)}
title={getMenuItemTitle('delete', downloadedMangas.length)}
/>
<MenuItem
Icon={Done}
isDisabled={!unreadMangas.length}
onClick={() => handleAction('mark_as_read', unreadMangas)}
title={getMenuItemTitle('mark_as_read', unreadMangas.length)}
/>
<MenuItem
Icon={RemoveDone}
isDisabled={!readMangas.length}
onClick={() => handleAction('mark_as_unread', readMangas)}
title={getMenuItemTitle('mark_as_unread', readMangas.length)}
/>
<MenuItem
Icon={Label}
onClick={() => handleAction('change_categories', selectedMangas)}
title={getMenuItemTitle('change_categories', selectedMangas.length)}
/>
<MenuItem
Icon={FavoriteBorderIcon}
onClick={() => handleAction('remove_from_library', selectedMangas)}
title={getMenuItemTitle('remove_from_library', selectedMangas.length)}
/>
{isCategorySelectOpen && (
<CategorySelect
open={isCategorySelectOpen}
onClose={() => {
setIsCategorySelectOpen(false);
handleClose(true);
}}
mangaIds={Mangas.getIds(selectedMangas)}
/>
)}
</>
);
};

View File

@@ -8,14 +8,29 @@
import { MenuProps } from '@mui/material/Menu/Menu'; import { MenuProps } from '@mui/material/Menu/Menu';
import { Menu as MuiMenu } from '@mui/material'; import { Menu as MuiMenu } from '@mui/material';
import { useState } from 'react';
export const Menu = ({ export const Menu = ({
children, children,
onClose, onClose,
...props ...props
}: Omit<MenuProps, 'children' | 'onClose'> & }: Omit<MenuProps, 'children' | 'onClose'> &
Required<Pick<MenuProps, 'onClose'>> & { children: (onClose: () => void) => JSX.Element }) => ( Required<Pick<MenuProps, 'onClose'>> & {
<MuiMenu {...props} onClose={onClose}> children: (onClose: () => void, setHideMenu: (hide: boolean) => void) => JSX.Element;
{children(() => onClose({}, 'backdropClick'))} }) => {
</MuiMenu> const [shouldHideMenu, setShouldHideMenu] = useState(false);
);
return (
<MuiMenu
{...props}
open={props.open}
onClose={onClose}
sx={{ visibility: !props.open || shouldHideMenu ? 'hidden' : 'visible' }}
>
{children(() => {
onClose({}, 'backdropClick');
setShouldHideMenu(false);
}, setShouldHideMenu)}
</MuiMenu>
);
};

View File

@@ -16,7 +16,7 @@ import { TranslationKey } from '@/typings.ts';
import { Menu } from '@/components/manga/Menu.tsx'; import { Menu } from '@/components/manga/Menu.tsx';
interface SelectionFABProps { interface SelectionFABProps {
children: (handleClose: () => void) => JSX.Element; children: (handleClose: () => void, setHideMenu: (hide: boolean) => void) => JSX.Element;
selectedItemsCount: number; selectedItemsCount: number;
title: TranslationKey; title: TranslationKey;
} }
@@ -53,7 +53,7 @@ export const SelectionFAB: React.FC<SelectionFABProps> = ({ children, selectedIt
'aria-labelledby': 'selectionMenuButton', 'aria-labelledby': 'selectionMenuButton',
}} }}
> >
{(onClose) => children(onClose)} {(onClose, setHideMenu) => children(onClose, setHideMenu)}
</Menu> </Menu>
</> </>
)} )}

View File

@@ -28,6 +28,7 @@ export type MangaAction =
export const actionToTranslationKey: { export const actionToTranslationKey: {
[key in MangaAction]: { [key in MangaAction]: {
action: { action: {
single: TranslationKey;
selected: TranslationKey; selected: TranslationKey;
}; };
success: TranslationKey; success: TranslationKey;
@@ -36,6 +37,7 @@ export const actionToTranslationKey: {
} = { } = {
download: { download: {
action: { action: {
single: 'chapter.action.download.add.label.action',
selected: 'chapter.action.download.add.button.selected', selected: 'chapter.action.download.add.button.selected',
}, },
success: 'chapter.action.download.add.label.success', success: 'chapter.action.download.add.label.success',
@@ -43,6 +45,7 @@ export const actionToTranslationKey: {
}, },
delete: { delete: {
action: { action: {
single: 'chapter.action.download.delete.label.action',
selected: 'chapter.action.download.delete.button.selected', selected: 'chapter.action.download.delete.button.selected',
}, },
success: 'chapter.action.download.delete.label.success', success: 'chapter.action.download.delete.label.success',
@@ -50,6 +53,7 @@ export const actionToTranslationKey: {
}, },
mark_as_read: { mark_as_read: {
action: { action: {
single: 'chapter.action.mark_as_read.add.label.action.current',
selected: 'chapter.action.mark_as_read.add.button.selected', selected: 'chapter.action.mark_as_read.add.button.selected',
}, },
success: 'chapter.action.mark_as_read.add.label.success', success: 'chapter.action.mark_as_read.add.label.success',
@@ -57,6 +61,7 @@ export const actionToTranslationKey: {
}, },
mark_as_unread: { mark_as_unread: {
action: { action: {
single: 'chapter.action.mark_as_read.remove.label.action',
selected: 'chapter.action.mark_as_read.remove.button.selected', selected: 'chapter.action.mark_as_read.remove.button.selected',
}, },
success: 'chapter.action.mark_as_read.remove.label.success', success: 'chapter.action.mark_as_read.remove.label.success',
@@ -64,6 +69,7 @@ export const actionToTranslationKey: {
}, },
remove_from_library: { remove_from_library: {
action: { action: {
single: 'manga.action.library.remove.label.action',
selected: 'manga.action.library.remove.button.selected', selected: 'manga.action.library.remove.button.selected',
}, },
success: 'manga.action.library.remove.label.success', success: 'manga.action.library.remove.label.success',
@@ -71,6 +77,7 @@ export const actionToTranslationKey: {
}, },
change_categories: { change_categories: {
action: { action: {
single: 'manga.action.category.label.action',
selected: 'manga.action.category.button.selected', selected: 'manga.action.category.button.selected',
}, },
success: 'manga.action.category.label.success', success: 'manga.action.category.label.success',

View File

@@ -25,8 +25,8 @@ import { TManga } from '@/typings.ts';
import { SelectableCollectionSelectMode } from '@/components/collection/SelectableCollectionSelectMode.tsx'; import { SelectableCollectionSelectMode } from '@/components/collection/SelectableCollectionSelectMode.tsx';
import { useGetVisibleLibraryMangas } from '@/components/library/useGetVisibleLibraryMangas.ts'; import { useGetVisibleLibraryMangas } from '@/components/library/useGetVisibleLibraryMangas.ts';
import { SelectionFAB } from '@/components/manga/SelectionFAB.tsx'; import { SelectionFAB } from '@/components/manga/SelectionFAB.tsx';
import { MangasSelectionFABActionItems } from '@/components/manga/MangasSelectionFABActionItems.tsx';
import { PARTIAL_MANGA_FIELDS } from '@/lib/graphql/Fragments.ts'; import { PARTIAL_MANGA_FIELDS } from '@/lib/graphql/Fragments.ts';
import { MangaActionMenuItems } from '@/components/manga/MangaActionMenuItems.tsx';
const StyledGridWrapper = styled(Box)(({ theme }) => ({ const StyledGridWrapper = styled(Box)(({ theme }) => ({
// TabsMenu height + TabsMenu bottom padding - grid item top padding // TabsMenu height + TabsMenu bottom padding - grid item top padding
@@ -264,13 +264,14 @@ export function Library() {
</StyledGridWrapper> </StyledGridWrapper>
{isSelectModeActive && ( {isSelectModeActive && (
<SelectionFAB selectedItemsCount={selectedItemIds.length} title="manga.title"> <SelectionFAB selectedItemsCount={selectedItemIds.length} title="manga.title">
{(handleClose) => ( {(handleClose, setHideMenu) => (
<MangasSelectionFABActionItems <MangaActionMenuItems
selectedMangas={selectedMangas} selectedMangas={selectedMangas}
handleClose={(selectionModeState) => { onClose={(selectionModeState) => {
handleClose(); handleClose();
setIsSelectModeActive(selectionModeState); setIsSelectModeActive(selectionModeState);
}} }}
setHideMenu={setHideMenu}
/> />
)} )}
</SelectionFAB> </SelectionFAB>