Improve memoization of reader "progress bar slot" rendering
This commit is contained in:
@@ -71,6 +71,8 @@ const BaseReaderProgressBar = ({
|
||||
}) => {
|
||||
const progressBarRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const currentPagesIndex = useMemo(() => getPage(currentPageIndex, pages).pagesIndex, [currentPageIndex, pages]);
|
||||
|
||||
const isHorizontalPosition = getProgressBarPositionInfo(progressBarPosition).isHorizontal;
|
||||
const currentPage = useMemo(() => getPage(currentPageIndex, pages), [currentPageIndex, pages]);
|
||||
const getOptionForDirection = useCallback(
|
||||
@@ -157,14 +159,19 @@ const BaseReaderProgressBar = ({
|
||||
<ReaderProgressBarSlotsContainer {...slotProps?.progressBarSlotsContainer}>
|
||||
{pages.map((page, pagesIndex) => (
|
||||
<ReaderProgressBarSlotWrapper
|
||||
{...slotProps?.progressBarSlot}
|
||||
key={page.primary.index}
|
||||
page={page}
|
||||
pagesIndex={pagesIndex}
|
||||
pageLoadStates={pageLoadStates}
|
||||
isCurrentPage={pagesIndex === currentPagesIndex}
|
||||
isLeadingPage={pagesIndex < currentPagesIndex}
|
||||
isTrailingPage={pagesIndex > currentPagesIndex}
|
||||
totalPages={pages.length}
|
||||
primaryPageLoadState={pageLoadStates[page.primary.index].loaded}
|
||||
secondaryPageLoadState={
|
||||
!!page.secondary && pageLoadStates[page.secondary.index].loaded
|
||||
}
|
||||
createProgressBarSlot={createProgressBarSlot}
|
||||
{...slotProps?.progressBarSlot}
|
||||
isFirstPage={pagesIndex === 0}
|
||||
isLastPage={pagesIndex === pages.length - 1}
|
||||
/>
|
||||
))}
|
||||
<ProgressBarHighlightReadPages
|
||||
|
||||
@@ -7,42 +7,87 @@
|
||||
*/
|
||||
|
||||
import Box, { BoxProps } from '@mui/material/Box';
|
||||
import { memo, ReactNode } from 'react';
|
||||
import { memo, ReactNode, useMemo } from 'react';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { ReaderProgressBarProps } from '@/modules/reader/types/ReaderProgressBar.types.ts';
|
||||
import { shouldForwardProp } from '@/modules/core/utils/ShouldForwardProp.ts';
|
||||
|
||||
type StyledWrapperProps = {
|
||||
isFirstPage: boolean;
|
||||
isLastPage: boolean;
|
||||
};
|
||||
const StyledWrapper = memo(
|
||||
styled(Box, {
|
||||
shouldForwardProp: shouldForwardProp<StyledWrapperProps>(['isFirstPage', 'isLastPage']),
|
||||
})<BoxProps & StyledWrapperProps>(({ isFirstPage, isLastPage }) => ({
|
||||
flexGrow: 1,
|
||||
height: '100%',
|
||||
cursor: 'pointer',
|
||||
borderLeftWidth: isFirstPage ? 0 : undefined,
|
||||
borderRightWidth: isLastPage ? 0 : undefined,
|
||||
})),
|
||||
);
|
||||
|
||||
export const ReaderProgressBarSlotWrapper = memo(
|
||||
({
|
||||
page,
|
||||
pagesIndex,
|
||||
pageLoadStates,
|
||||
isFirstPage,
|
||||
isLastPage,
|
||||
isCurrentPage,
|
||||
isLeadingPage,
|
||||
isTrailingPage,
|
||||
totalPages,
|
||||
primaryPageLoadState,
|
||||
secondaryPageLoadState,
|
||||
createProgressBarSlot,
|
||||
...boxProps
|
||||
}: {
|
||||
page: ReaderProgressBarProps['pages'][number];
|
||||
pagesIndex: number;
|
||||
pageLoadStates: ReaderProgressBarProps['pageLoadStates'];
|
||||
isFirstPage: boolean;
|
||||
isLastPage: boolean;
|
||||
isCurrentPage: boolean;
|
||||
isLeadingPage: boolean;
|
||||
isTrailingPage: boolean;
|
||||
totalPages: number;
|
||||
primaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'];
|
||||
secondaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'];
|
||||
createProgressBarSlot: (
|
||||
page: ReaderProgressBarProps['pages'][number],
|
||||
pageLoadStates: ReaderProgressBarProps['pageLoadStates'],
|
||||
pagesIndex: number,
|
||||
primaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'],
|
||||
secondaryPageLoadState: ReaderProgressBarProps['pageLoadStates'][number]['loaded'],
|
||||
isCurrentPage: boolean,
|
||||
isLeadingPage: boolean,
|
||||
isTrailingPage: boolean,
|
||||
totalPages: number,
|
||||
) => ReactNode;
|
||||
} & BoxProps) => (
|
||||
<Box
|
||||
{...boxProps}
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
height: '100%',
|
||||
cursor: 'pointer',
|
||||
...boxProps?.sx,
|
||||
borderLeftWidth: isFirstPage ? 0 : undefined,
|
||||
borderRightWidth: isLastPage ? 0 : undefined,
|
||||
}}
|
||||
>
|
||||
{createProgressBarSlot(page, pageLoadStates, pagesIndex)}
|
||||
</Box>
|
||||
),
|
||||
} & BoxProps) => {
|
||||
const slot = useMemo(
|
||||
() =>
|
||||
createProgressBarSlot(
|
||||
page,
|
||||
pagesIndex,
|
||||
primaryPageLoadState,
|
||||
secondaryPageLoadState,
|
||||
isCurrentPage,
|
||||
isLeadingPage,
|
||||
isTrailingPage,
|
||||
totalPages,
|
||||
),
|
||||
[
|
||||
page,
|
||||
pagesIndex,
|
||||
primaryPageLoadState,
|
||||
secondaryPageLoadState,
|
||||
isCurrentPage,
|
||||
isLeadingPage,
|
||||
isTrailingPage,
|
||||
totalPages,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledWrapper {...boxProps} isFirstPage={pagesIndex === 0} isLastPage={pagesIndex === totalPages - 1}>
|
||||
{slot}
|
||||
</StyledWrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -12,13 +12,13 @@ import SkipNextIcon from '@mui/icons-material/SkipNext';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { alpha } from '@mui/material/styles';
|
||||
import Box from '@mui/material/Box';
|
||||
import { memo, useLayoutEffect } from 'react';
|
||||
import { memo, useCallback, useLayoutEffect } from 'react';
|
||||
import { ReaderProgressBar } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx';
|
||||
import { ReaderProgressBarSlot } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarSlot.tsx';
|
||||
import { userReaderStatePagesContext } from '@/modules/reader/contexts/state/ReaderStatePagesContext.tsx';
|
||||
import { useReaderStateChaptersContext } from '@/modules/reader/contexts/state/ReaderStateChaptersContext.tsx';
|
||||
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
||||
import { getNextIndexFromPage, getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
||||
import { getPage } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
||||
import { getOptionForDirection } from '@/modules/theme/services/ThemeCreator.ts';
|
||||
import { ProgressBarPosition, ReaderResumeMode, ReaderStateChapters } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { ReaderProgressBarDirectionWrapper } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarDirectionWrapper.tsx';
|
||||
@@ -75,39 +75,42 @@ const BaseMobileReaderProgressBar = ({
|
||||
<ReaderProgressBar
|
||||
progressBarPosition={ProgressBarPosition.BOTTOM}
|
||||
{...pagesState}
|
||||
createProgressBarSlot={(page) => (
|
||||
<ReaderProgressBarSlot
|
||||
pageName={page.name}
|
||||
progressBarPosition={ProgressBarPosition.BOTTOM}
|
||||
slotProps={{
|
||||
box: {
|
||||
sx: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'end',
|
||||
position: 'relative',
|
||||
backgroundColor: 'background.default',
|
||||
createProgressBarSlot={useCallback(
|
||||
(page, pagesIndex, _, __, ___, ____, isTrailingPage) => (
|
||||
<ReaderProgressBarSlot
|
||||
pageName={page.name}
|
||||
progressBarPosition={ProgressBarPosition.BOTTOM}
|
||||
slotProps={{
|
||||
box: {
|
||||
sx: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'end',
|
||||
position: 'relative',
|
||||
backgroundColor: 'background.default',
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
right: '2px',
|
||||
width: '2px',
|
||||
height: '2px',
|
||||
borderRadius: 100,
|
||||
backgroundColor: 'background.paper',
|
||||
...applyStyles(getNextIndexFromPage(page) > currentPageIndex, {
|
||||
backgroundColor: 'primary.main',
|
||||
}),
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</ReaderProgressBarSlot>
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
right: '2px',
|
||||
width: '2px',
|
||||
height: '2px',
|
||||
borderRadius: 100,
|
||||
backgroundColor: 'background.paper',
|
||||
...applyStyles(isTrailingPage, {
|
||||
backgroundColor: 'primary.main',
|
||||
}),
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</ReaderProgressBarSlot>
|
||||
),
|
||||
[],
|
||||
)}
|
||||
slotProps={{
|
||||
container: {
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
*/
|
||||
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { memo } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { ReaderProgressBar } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBar.tsx';
|
||||
import { userReaderStatePagesContext } from '@/modules/reader/contexts/state/ReaderStatePagesContext.tsx';
|
||||
import { ReaderService } from '@/modules/reader/services/ReaderService.ts';
|
||||
import { IReaderSettings, ProgressBarType, TReaderScrollbarContext } from '@/modules/reader/types/Reader.types.ts';
|
||||
import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
|
||||
import { getPage, getProgressBarPositionInfo } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
||||
import { getProgressBarPositionInfo } from '@/modules/reader/utils/ReaderProgressBar.utils.tsx';
|
||||
import { ReaderProgressBarDirectionWrapper } from '@/modules/reader/components/overlay/progress-bar/ReaderProgressBarDirectionWrapper.tsx';
|
||||
import { TReaderProgressBarContext } from '@/modules/reader/types/ReaderProgressBar.types.ts';
|
||||
import { NavbarContextType } from '@/modules/navigation-bar/NavigationBar.types.ts';
|
||||
@@ -42,9 +42,7 @@ const BaseStandardReaderProgressBar = ({
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const pagesState = userReaderStatePagesContext();
|
||||
const { currentPageIndex, pages, totalPages } = pagesState;
|
||||
|
||||
const currentPagesIndex = getPage(currentPageIndex, pages).pagesIndex;
|
||||
const { totalPages } = pagesState;
|
||||
|
||||
const { isBottom, isLeft, isRight, isVertical, isHorizontal } = getProgressBarPositionInfo(progressBarPosition);
|
||||
|
||||
@@ -59,30 +57,34 @@ const BaseStandardReaderProgressBar = ({
|
||||
<ReaderProgressBar
|
||||
{...pagesState}
|
||||
progressBarPosition={progressBarPosition}
|
||||
createProgressBarSlot={(page, pageLoadStates, pagesIndex) => {
|
||||
if (isHidden && isMinimized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
createProgressBarSlot={useCallback(
|
||||
(
|
||||
page,
|
||||
pagesIndex,
|
||||
primaryPageLoadState,
|
||||
secondaryPageLoadState,
|
||||
isCurrentPage,
|
||||
isLeadingPage,
|
||||
_,
|
||||
totalPages_,
|
||||
) => (
|
||||
<ReaderProgressBarSlotDesktop
|
||||
pageName={page.name}
|
||||
pageUrl={page.primary.url}
|
||||
primaryPageLoadState={pageLoadStates[page.primary.index].loaded}
|
||||
secondaryPageLoadState={
|
||||
page.secondary ? pageLoadStates[page.secondary.index].loaded : undefined
|
||||
}
|
||||
primaryPageLoadState={primaryPageLoadState}
|
||||
secondaryPageLoadState={secondaryPageLoadState}
|
||||
isHorizontal={isHorizontal}
|
||||
isVertical={isVertical}
|
||||
progressBarPosition={progressBarPosition}
|
||||
isCurrentPage={currentPagesIndex === pagesIndex}
|
||||
isCurrentPage={isCurrentPage}
|
||||
isFirstPage={pagesIndex === 0}
|
||||
isLastPage={pagesIndex === pages.length - 1}
|
||||
isLeadingPage={pagesIndex < currentPagesIndex}
|
||||
isLastPage={pagesIndex === totalPages_ - 1}
|
||||
isLeadingPage={isLeadingPage}
|
||||
isDragging={isDragging}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
),
|
||||
[isHorizontal, isVertical, isDragging, progressBarPosition],
|
||||
)}
|
||||
slotProps={{
|
||||
container: {
|
||||
sx: {
|
||||
|
||||
Reference in New Issue
Block a user