Fix/manga screen prevent fab from overlaying last chapter in list (#298)

* Introduce "StyledFAb"

MUI "Fab" with the "default" styling applied

* Prevent FAB from overlaying last chapter in list of Manga details page
This commit is contained in:
schroda
2023-05-15 18:23:26 +02:00
committed by GitHub
parent 5aaf0854fe
commit 0a0d902bd2
5 changed files with 51 additions and 24 deletions

View File

@@ -21,6 +21,7 @@ import ChaptersToolbarMenu from 'components/manga/ChaptersToolbarMenu';
import SelectionFAB from 'components/manga/SelectionFAB'; import SelectionFAB from 'components/manga/SelectionFAB';
import { BatchChaptersChange, IChapter, IDownloadChapter, IQueue, TranslationKey } from 'typings'; import { BatchChaptersChange, IChapter, IDownloadChapter, IQueue, TranslationKey } from 'typings';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { DEFAULT_FULL_FAB_HEIGHT } from 'components/util/StyledFab';
const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({ const StyledVirtuoso = styled(Virtuoso)(({ theme }) => ({
listStyle: 'none', listStyle: 'none',
@@ -252,15 +253,29 @@ const ChapterList: React.FC<IProps> = ({ mangaId }) => {
// 900 is the md breakpoint in MUI // 900 is the md breakpoint in MUI
overflowY: window.innerWidth < 900 ? 'visible' : 'auto', overflowY: window.innerWidth < 900 ? 'visible' : 'auto',
}} }}
totalCount={visibleChapters.length} totalCount={visibleChapters.length + 1}
itemContent={(index: number) => ( itemContent={(index: number) => {
<ChapterCard // hacky way of adding padding to the bottom of the list, so the FAB doesn't overlay the last chapter
{...chaptersWithMeta[index]} // since I was unable to find another solution on how to achieve this
showChapterNumber={options.showChapterNumber} if (index === visibleChapters.length) {
triggerChaptersUpdate={() => mutate()} return (
onSelect={() => handleSelection(index)} <div
/> style={{
)} paddingBottom: DEFAULT_FULL_FAB_HEIGHT,
}}
/>
);
}
return (
<ChapterCard
{...chaptersWithMeta[index]}
showChapterNumber={options.showChapterNumber}
triggerChaptersUpdate={() => mutate()}
onSelect={() => handleSelection(index)}
/>
);
}}
useWindowScroll={window.innerWidth < 900} useWindowScroll={window.innerWidth < 900}
overscan={window.innerHeight * 0.5} overscan={window.innerHeight * 0.5}
/> />

View File

@@ -6,12 +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 React from 'react'; import React from 'react';
import { Fab } from '@mui/material';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { PlayArrow } from '@mui/icons-material'; import { PlayArrow } from '@mui/icons-material';
import { BACK } from 'util/useBackTo'; import { BACK } from 'util/useBackTo';
import { IChapter } from 'typings'; import { IChapter } from 'typings';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import StyledFab from 'components/util/StyledFab';
interface ResumeFABProps { interface ResumeFABProps {
chapter: IChapter; chapter: IChapter;
@@ -26,8 +26,7 @@ export default function ResumeFab(props: ResumeFABProps) {
mangaId, mangaId,
} = props; } = props;
return ( return (
<Fab <StyledFab
sx={{ position: 'fixed', bottom: '2em', right: '3em' }}
component={Link} component={Link}
variant="extended" variant="extended"
color="primary" color="primary"
@@ -38,6 +37,6 @@ export default function ResumeFab(props: ResumeFABProps) {
> >
<PlayArrow /> <PlayArrow />
{index === 1 ? t('global.button.start') : t('global.button.resume')} {index === 1 ? t('global.button.start') : t('global.button.resume')}
</Fab> </StyledFab>
); );
} }

View File

@@ -12,6 +12,7 @@ import React, { useRef, useState } from 'react';
import type { IChapterWithMeta } from 'components/manga/ChapterList'; import type { IChapterWithMeta } from 'components/manga/ChapterList';
import SelectionFABActionItem from 'components/manga/SelectionFABActionItem'; import SelectionFABActionItem from 'components/manga/SelectionFABActionItem';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { DEFAULT_FAB_STYLE } from 'components/util/StyledFab';
export type SelectionAction = 'download' | 'delete' | 'bookmark' | 'unbookmark' | 'mark_as_read' | 'mark_as_unread'; export type SelectionAction = 'download' | 'delete' | 'bookmark' | 'unbookmark' | 'mark_as_read' | 'mark_as_unread';
@@ -38,9 +39,8 @@ const SelectionFAB: React.FC<SelectionFABProps> = (props) => {
return ( return (
<Box <Box
sx={{ sx={{
position: 'fixed', ...DEFAULT_FAB_STYLE,
bottom: '2em', height: `calc(${DEFAULT_FAB_STYLE.height} + 1)`,
right: '3em',
pt: 1, pt: 1,
}} }}
ref={anchorEl} ref={anchorEl}

View File

@@ -7,7 +7,7 @@
*/ */
import FilterListIcon from '@mui/icons-material/FilterList'; import FilterListIcon from '@mui/icons-material/FilterList';
import { Button, Fab, Stack } from '@mui/material'; import { Button, Stack } from '@mui/material';
import { Box } from '@mui/system'; import { Box } from '@mui/system';
import OptionsPanel from 'components/molecules/OptionsPanel'; import OptionsPanel from 'components/molecules/OptionsPanel';
import React from 'react'; import React from 'react';
@@ -23,6 +23,7 @@ import GroupFilter from 'components/source/filters/GroupFilter';
import SeperatorFilter from 'components/source/filters/SeparatorFilter'; import SeperatorFilter from 'components/source/filters/SeparatorFilter';
import { ISourceFilters, IState } from 'typings'; import { ISourceFilters, IState } from 'typings';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import StyledFab from 'components/util/StyledFab';
interface IFilters { interface IFilters {
sourceFilter: ISourceFilters[]; sourceFilter: ISourceFilters[];
@@ -160,15 +161,10 @@ export default function SourceOptions({
return ( return (
<> <>
<Fab <StyledFab onClick={() => setFilterOptions(!FilterOptions)} variant="extended" color="primary">
sx={{ position: 'fixed', bottom: '2em', right: '3em' }}
onClick={() => setFilterOptions(!FilterOptions)}
variant="extended"
color="primary"
>
<FilterListIcon /> <FilterListIcon />
{t('global.button.filter')} {t('global.button.filter')}
</Fab> </StyledFab>
<OptionsPanel open={FilterOptions} onClose={() => setFilterOptions(false)}> <OptionsPanel open={FilterOptions} onClose={() => setFilterOptions(false)}>
<Box sx={{ display: 'flex', p: 2, pb: 0 }}> <Box sx={{ display: 'flex', p: 2, pb: 0 }}>

View File

@@ -0,0 +1,17 @@
import { Fab } from '@mui/material';
import { styled } from '@mui/system';
export const DEFAULT_FAB_STYLE = {
position: 'fixed',
height: '48px',
right: '3em',
bottom: '2em',
} as const;
export const DEFAULT_FULL_FAB_HEIGHT = `calc(${DEFAULT_FAB_STYLE.bottom} + ${DEFAULT_FAB_STYLE.height})`;
const StyledFab = styled(Fab)({
...DEFAULT_FAB_STYLE,
}) as typeof Fab;
export default StyledFab;