1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2025-01-25 11:13:39 +02:00

Convert series images to TypeScript

This commit is contained in:
Mark McDowall 2024-09-02 16:05:19 -07:00 committed by Mark McDowall
parent e1e10e195c
commit ee99c3895d
7 changed files with 177 additions and 257 deletions

View File

@ -19,8 +19,10 @@ export type SeriesStatus = 'continuing' | 'ended' | 'upcoming' | 'deleted';
export type MonitorNewItems = 'all' | 'none';
export type CoverType = 'poster' | 'banner' | 'fanart' | 'season';
export interface Image {
coverType: string;
coverType: CoverType;
url: string;
remoteUrl: string;
}

View File

@ -1,29 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import SeriesImage from './SeriesImage';
const bannerPlaceholder = 'data:image/png;base64,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';
function SeriesBanner(props) {
return (
<SeriesImage
{...props}
coverType="banner"
placeholder={bannerPlaceholder}
/>
);
}
SeriesBanner.propTypes = {
...SeriesImage.propTypes,
coverType: PropTypes.string,
placeholder: PropTypes.string,
overflow: PropTypes.bool,
size: PropTypes.number.isRequired
};
SeriesBanner.defaultProps = {
size: 70
};
export default SeriesBanner;

View File

@ -0,0 +1,23 @@
import React from 'react';
import SeriesImage, { SeriesImageProps } from './SeriesImage';
const bannerPlaceholder =
'data:image/png;base64,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';
interface SeriesBannerProps
extends Omit<SeriesImageProps, 'coverType' | 'placeholder'> {
size?: 35 | 70;
}
function SeriesBanner({ size = 70, ...otherProps }: SeriesBannerProps) {
return (
<SeriesImage
{...otherProps}
size={size}
coverType="banner"
placeholder={bannerPlaceholder}
/>
);
}
export default SeriesBanner;

View File

@ -1,198 +0,0 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import LazyLoad from 'react-lazyload';
function findImage(images, coverType) {
return images.find((image) => image.coverType === coverType);
}
function getUrl(image, coverType, size) {
const imageUrl = image?.url;
if (imageUrl) {
return imageUrl.replace(`${coverType}.jpg`, `${coverType}-${size}.jpg`);
}
}
class SeriesImage extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
const pixelRatio = Math.max(Math.round(window.devicePixelRatio), 1);
const {
images,
coverType,
size
} = props;
const image = findImage(images, coverType);
this.state = {
pixelRatio,
image,
url: getUrl(image, coverType, pixelRatio * size),
isLoaded: false,
hasError: false
};
}
componentDidMount() {
if (!this.state.url && this.props.onError) {
this.props.onError();
}
}
componentDidUpdate() {
const {
images,
coverType,
placeholder,
size,
onError
} = this.props;
const {
image,
pixelRatio
} = this.state;
const nextImage = findImage(images, coverType);
if (nextImage && (!image || nextImage.url !== image.url)) {
this.setState({
image: nextImage,
url: getUrl(nextImage, coverType, pixelRatio * size),
hasError: false
// Don't reset isLoaded, as we want to immediately try to
// show the new image, whether an image was shown previously
// or the placeholder was shown.
});
} else if (!nextImage && image) {
this.setState({
image: nextImage,
url: placeholder,
hasError: false
});
if (onError) {
onError();
}
}
}
//
// Listeners
onError = () => {
this.setState({
hasError: true
});
if (this.props.onError) {
this.props.onError();
}
};
onLoad = () => {
this.setState({
isLoaded: true,
hasError: false
});
if (this.props.onLoad) {
this.props.onLoad();
}
};
//
// Render
render() {
const {
className,
style,
placeholder,
size,
lazy,
overflow
} = this.props;
const {
url,
hasError,
isLoaded
} = this.state;
if (hasError || !url) {
return (
<img
className={className}
style={style}
src={placeholder}
/>
);
}
if (lazy) {
return (
<LazyLoad
height={size}
offset={100}
overflow={overflow}
placeholder={
<img
className={className}
style={style}
src={placeholder}
/>
}
>
<img
className={className}
style={style}
src={url}
onError={this.onError}
onLoad={this.onLoad}
rel="noreferrer"
/>
</LazyLoad>
);
}
return (
<img
className={className}
style={style}
src={isLoaded ? url : placeholder}
onError={this.onError}
onLoad={this.onLoad}
/>
);
}
}
SeriesImage.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
coverType: PropTypes.string.isRequired,
placeholder: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
lazy: PropTypes.bool.isRequired,
overflow: PropTypes.bool.isRequired,
onError: PropTypes.func,
onLoad: PropTypes.func
};
SeriesImage.defaultProps = {
size: 250,
lazy: true,
overflow: false
};
export default SeriesImage;

View File

@ -0,0 +1,128 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import LazyLoad from 'react-lazyload';
import { CoverType, Image } from './Series';
function findImage(images: Image[], coverType: CoverType) {
return images.find((image) => image.coverType === coverType);
}
function getUrl(image: Image, coverType: CoverType, size: number) {
const imageUrl = image?.url;
return imageUrl
? imageUrl.replace(`${coverType}.jpg`, `${coverType}-${size}.jpg`)
: null;
}
export interface SeriesImageProps {
className?: string;
style?: object;
images: Image[];
coverType: CoverType;
placeholder: string;
size?: number;
lazy?: boolean;
overflow?: boolean;
onError?: () => void;
onLoad?: () => void;
}
const pixelRatio = Math.max(Math.round(window.devicePixelRatio), 1);
function SeriesImage({
className,
style,
images,
coverType,
placeholder,
size = 250,
lazy = true,
overflow = false,
onError,
onLoad,
}: SeriesImageProps) {
const [url, setUrl] = useState<string | null>(null);
const [hasError, setHasError] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
const image = useRef<Image | null>(null);
const handleLoad = useCallback(() => {
setHasError(false);
setIsLoaded(true);
onLoad?.();
}, [setHasError, setIsLoaded, onLoad]);
const handleError = useCallback(() => {
setHasError(true);
setIsLoaded(false);
onError?.();
}, [setHasError, setIsLoaded, onError]);
useEffect(() => {
const nextImage = findImage(images, coverType);
if (nextImage && (!image.current || nextImage.url !== image.current.url)) {
// Don't reset isLoaded, as we want to immediately try to
// show the new image, whether an image was shown previously
// or the placeholder was shown.
image.current = nextImage;
setUrl(getUrl(nextImage, coverType, pixelRatio * size));
setHasError(false);
} else if (!nextImage) {
if (image.current) {
image.current = null;
setUrl(placeholder);
setHasError(false);
onError?.();
}
}
}, [images, coverType, placeholder, size, onError]);
useEffect(() => {
if (!image.current) {
onError?.();
}
// This should only run once when the component mounts,
// so we don't need to include the other dependencies.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (hasError || !url) {
return <img className={className} style={style} src={placeholder} />;
}
if (lazy) {
return (
<LazyLoad
height={size}
offset={100}
overflow={overflow}
placeholder={
<img className={className} style={style} src={placeholder} />
}
>
<img
className={className}
style={style}
src={url}
rel="noreferrer"
onError={handleError}
onLoad={handleLoad}
/>
</LazyLoad>
);
}
return (
<img
className={className}
style={style}
src={isLoaded ? url : placeholder}
onError={handleError}
onLoad={handleLoad}
/>
);
}
export default SeriesImage;

View File

@ -1,29 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import SeriesImage from './SeriesImage';
const posterPlaceholder = 'data:image/png;base64,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';
function SeriesPoster(props) {
return (
<SeriesImage
{...props}
coverType="poster"
placeholder={posterPlaceholder}
/>
);
}
SeriesPoster.propTypes = {
...SeriesImage.propTypes,
coverType: PropTypes.string,
placeholder: PropTypes.string,
overflow: PropTypes.bool,
size: PropTypes.number.isRequired
};
SeriesPoster.defaultProps = {
size: 250
};
export default SeriesPoster;

View File

@ -0,0 +1,23 @@
import React from 'react';
import SeriesImage, { SeriesImageProps } from './SeriesImage';
const posterPlaceholder =
'data:image/png;base64,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';
interface SeriesPosterProps
extends Omit<SeriesImageProps, 'coverType' | 'placeholder'> {
size?: 250 | 500;
}
function SeriesPoster({ size = 250, ...otherProps }: SeriesPosterProps) {
return (
<SeriesImage
{...otherProps}
size={size}
coverType="poster"
placeholder={posterPlaceholder}
/>
);
}
export default SeriesPoster;