Show image loading placeholder only when visible
The MUI spinner impacts the cpu usage. While only a few of them don't matter, rendering multiple of them can impact the cpu usage. This can be a problem in the reader in case a chapter with a lot of chapters is rendered and a continuous reading mode is being used. In such a case the cpu usage stays increased until all pages have been loaded
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { useState, useEffect, forwardRef, ForwardedRef } from 'react';
|
||||
import { useState, useEffect, forwardRef, ForwardedRef, useCallback, useRef } from 'react';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import Box from '@mui/material/Box';
|
||||
import Stack from '@mui/material/Stack';
|
||||
@@ -19,6 +19,7 @@ import { SxProps, Theme } from '@mui/material/styles';
|
||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||
import { Priority } from '@/lib/Queue.ts';
|
||||
import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
|
||||
import { useIntersectionObserver } from '@/modules/core/hooks/useIntersectionObserver.tsx';
|
||||
|
||||
interface IProps {
|
||||
shouldLoad?: boolean;
|
||||
@@ -42,7 +43,8 @@ interface IProps {
|
||||
retryKeyPrefix?: string;
|
||||
}
|
||||
|
||||
export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTMLImageElement | null>) => {
|
||||
export const SpinnerImage = forwardRef(
|
||||
(props: IProps, imgRef: ForwardedRef<HTMLImageElement | HTMLDivElement | null>) => {
|
||||
const {
|
||||
shouldLoad = true,
|
||||
shouldDecode,
|
||||
@@ -61,12 +63,15 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTML
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const loadingIndicatorRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const showMissingImageIcon = !src.length;
|
||||
|
||||
const [imageSourceUrl, setImageSourceUrl] = useState('');
|
||||
const [imgLoadRetryKey, setImgLoadRetryKey] = useState(0);
|
||||
const [isLoading, setIsLoading] = useState<boolean | undefined>(undefined);
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
const updateImageState = (loading: boolean, error: boolean = false, aborted: boolean = false) => {
|
||||
setIsLoading(loading);
|
||||
@@ -81,6 +86,11 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTML
|
||||
}
|
||||
};
|
||||
|
||||
useIntersectionObserver(
|
||||
loadingIndicatorRef,
|
||||
useCallback((entries) => setIsVisible(entries[0].isIntersecting), []),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (showMissingImageIcon || !shouldLoad) {
|
||||
return () => {};
|
||||
@@ -172,6 +182,7 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTML
|
||||
|
||||
{(isLoading || (src && !imageSourceUrl) || hasError) && (
|
||||
<Stack
|
||||
ref={loadingIndicatorRef}
|
||||
sx={{
|
||||
height: '100%',
|
||||
justifyContent: 'center',
|
||||
@@ -186,7 +197,9 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTML
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{(isLoading || (src && !imageSourceUrl && !hasError)) && <CircularProgress thickness={5} />}
|
||||
{isVisible && (isLoading || (src && !imageSourceUrl && !hasError)) && (
|
||||
<CircularProgress thickness={5} />
|
||||
)}
|
||||
{hasError && isLoading === false && (
|
||||
<>
|
||||
<BrokenImageIcon />
|
||||
@@ -208,4 +221,5 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTML
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user