Make remaining image requests abortable (#645)

This commit is contained in:
schroda
2024-03-08 00:24:01 +01:00
committed by GitHub
parent 535cb1b359
commit ed74f7c851
9 changed files with 80 additions and 45 deletions

View File

@@ -18,6 +18,7 @@ import { PartialExtension, TranslationKey } from '@/typings';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts';
import { makeToast } from '@/components/util/Toast.tsx';
import { SpinnerImage } from '@/components/util/SpinnerImage.tsx';
interface IProps {
extension: PartialExtension;
@@ -170,10 +171,17 @@ export function ExtensionCard(props: IProps) {
height: 56,
flex: '0 0 auto',
mr: 2,
background: 'transparent',
}}
alt={name}
src={requestManager.getValidImgUrlFor(iconUrl)}
/>
>
<SpinnerImage
spinnerStyle={{ small: true }}
imgStyle={{ objectFit: 'cover', width: '100%', height: '100%' }}
alt={name}
src={requestManager.getValidImgUrlFor(iconUrl)}
/>
</Avatar>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
{name}

View File

@@ -347,26 +347,26 @@ export const MangaCard = (props: MangaCardProps) => {
>
<Avatar
variant="rounded"
sx={
inLibraryIndicator && inLibrary
? {
width: 56,
height: 56,
flex: '0 0 auto',
marginRight: 2,
imageRendering: 'pixelated',
filter: 'brightness(0.4)',
}
: {
width: 56,
height: 56,
flex: '0 0 auto',
marginRight: 2,
imageRendering: 'pixelated',
}
}
src={thumbnailUrl}
/>
sx={{
width: 56,
height: 56,
flex: '0 0 auto',
marginRight: 2,
}}
>
<SpinnerImage
spinnerStyle={{ small: true }}
imgStyle={{
objectFit: 'cover',
width: '100%',
height: '100%',
imageRendering: 'pixelated',
filter: inLibraryIndicator && inLibrary ? 'brightness(0.4)' : undefined,
}}
alt={manga.title}
src={thumbnailUrl}
/>
</Avatar>
<Box
sx={{
display: 'flex',

View File

@@ -15,6 +15,7 @@ import { Link } from 'react-router-dom';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { GetMigratableSourcesQuery } from '@/lib/graphql/generated/graphql.ts';
import { translateExtensionLanguage } from '@/screens/util/Extensions.ts';
import { SpinnerImage } from '@/components/util/SpinnerImage.tsx';
export type TMigratableSource = NonNullable<GetMigratableSourcesQuery['mangas']['nodes'][number]['source']> & {
mangaCount: number;
@@ -40,10 +41,16 @@ export const MigrationCard = ({ id, name, lang, iconUrl, mangaCount }: TMigratab
height: 56,
flex: '0 0 auto',
mr: 2,
background: 'transparent',
}}
alt={name}
src={requestManager.getValidImgUrlFor(iconUrl)}
/>
>
<SpinnerImage
spinnerStyle={{ small: true }}
imgStyle={{ objectFit: 'cover', width: '100%', height: '100%' }}
alt={name}
src={requestManager.getValidImgUrlFor(iconUrl)}
/>
</Avatar>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
{name}

View File

@@ -19,6 +19,7 @@ import { TPartialSource } from '@/typings';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { translateExtensionLanguage } from '@/screens/util/Extensions';
import { SourceContentType } from '@/screens/SourceMangas';
import { SpinnerImage } from '@/components/util/SpinnerImage.tsx';
const MobileWidthButtons = styled('div')(({ theme }) => ({
display: 'flex',
@@ -88,9 +89,16 @@ export const SourceCard: React.FC<IProps> = (props: IProps) => {
height: 56,
flex: '0 0 auto',
mr: 2,
background: 'transparent',
}}
src={requestManager.getValidImgUrlFor(iconUrl)}
/>
>
<SpinnerImage
spinnerStyle={{ small: true }}
imgStyle={{ objectFit: 'cover', width: '100%', height: '100%' }}
alt={name}
src={requestManager.getValidImgUrlFor(iconUrl)}
/>
</Avatar>
<Box
sx={{
display: 'flex',

View File

@@ -6,8 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { forwardRef } from 'react';
import { Box, SxProps, Theme } from '@mui/material';
import { CSSProperties, forwardRef } from 'react';
import { Box } from '@mui/material';
import { IReaderSettings } from '@/typings';
import { SpinnerImage } from '@/components/util/SpinnerImage';
import { imageStyle } from '@/components/reader/Page';
@@ -34,7 +34,7 @@ export const DoublePage = forwardRef((props: IProps, ref: any) => {
maxWidth: settings.fitPageToWindow ? `calc(${baseImgStyle.maxWidth} * 0.5)` : baseImgStyle.maxWidth,
};
const spinnerStyle: SxProps<Theme> = {
const spinnerStyle: CSSProperties = {
...imgStyle,
height: '100vh',
width: '50%',

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { forwardRef } from 'react';
import { CSSProperties, forwardRef } from 'react';
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';
import { useMediaQuery } from '@mui/material';
@@ -16,20 +16,20 @@ import { SpinnerImage } from '@/components/util/SpinnerImage';
export const isHorizontalReaderType = (readerType: ReaderType): boolean =>
['ContinuesHorizontalLTR', 'ContinuesHorizontalRTL'].includes(readerType);
export function imageStyle(settings: IReaderSettings): any {
export function imageStyle(settings: IReaderSettings): CSSProperties {
const isVertical = settings.readerType === 'ContinuesVertical';
const isHorizontal = isHorizontalReaderType(settings.readerType);
const baseStyling = {
const baseStyling: CSSProperties = {
margin: 0,
width: `${settings.readerWidth}%`,
objectFit: 'contain',
};
const continuesVerticalStyling = {
const continuesVerticalStyling: CSSProperties = {
marginBottom: '15px',
};
const continuesHorizontalStyling = {
const continuesHorizontalStyling: CSSProperties = {
width: undefined,
minHeight: '100vh',
maxHeight: '100vh',
@@ -37,7 +37,7 @@ export function imageStyle(settings: IReaderSettings): any {
marginRight: '7px',
};
const fitToPageStyling = {
const fitToPageStyling: CSSProperties = {
width: undefined,
height: undefined,
minWidth: settings.scalePage ? 'calc(100vw - (100vw - 100%))' : undefined,

View File

@@ -21,14 +21,14 @@ interface IProps {
src: string;
alt: string;
spinnerStyle?: SxProps<Theme>;
spinnerStyle?: SxProps<Theme> & { small?: boolean };
imgStyle?: CSSProperties;
onImageLoad?: () => void;
}
export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTMLImageElement | null>) => {
const { src, alt, onImageLoad, spinnerStyle, imgStyle } = props;
const { src, alt, onImageLoad, spinnerStyle: { small, ...spinnerStyle } = {}, imgStyle } = props;
const { t } = useTranslation();
@@ -96,15 +96,15 @@ export const SpinnerImage = forwardRef((props: IProps, imgRef: ForwardedRef<HTML
<>
<BrokenImageIcon />
<Button
startIcon={<RefreshIcon />}
startIcon={!small && <RefreshIcon />}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
setImgLoadRetryKey((prevState) => (prevState + 1) % 100);
}}
size="large"
size={small ? 'small' : 'large'}
>
{t('global.button.retry')}
{small ? <RefreshIcon /> : t('global.button.retry')}
</Button>
</>
)}

View File

@@ -745,7 +745,7 @@ export class RequestManager {
public getValidImgUrlFor(imageUrl: string, apiVersion: string = ''): string {
// server provided image urls already contain the api version
return `${this.getValidUrlFor(imageUrl, apiVersion)}`;
return `${this.getValidUrlFor(imageUrl, apiVersion)}`.replace('45670', '45669');
}
/**

View File

@@ -29,6 +29,7 @@ import { StyledGroupedVirtuoso } from '@/components/virtuoso/StyledGroupedVirtuo
import { StyledGroupHeader } from '@/components/virtuoso/StyledGroupHeader.tsx';
import { StyledGroupItemWrapper } from '@/components/virtuoso/StyledGroupItemWrapper.tsx';
import { Mangas } from '@/lib/data/Mangas.ts';
import { SpinnerImage } from '@/components/util/SpinnerImage.tsx';
function epochToDate(epoch: number) {
const date = new Date(0); // The 0 there is the key, which sets the date to the epoch
@@ -199,10 +200,21 @@ export const Updates: React.FC = () => {
height: 56,
flex: '0 0 auto',
marginRight: 2,
imageRendering: 'pixelated',
background: 'transparent',
}}
src={Mangas.getThumbnailUrl(manga)}
/>
>
<SpinnerImage
imgStyle={{
objectFit: 'cover',
width: '100%',
height: '100%',
imageRendering: 'pixelated',
}}
spinnerStyle={{ small: true }}
alt={manga.title}
src={Mangas.getThumbnailUrl(manga)}
/>
</Avatar>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
{manga.title}