fix: Fix display issues with incorrect thumbnails. Change ImageThumb to functional component. (#1148)

This commit is contained in:
ladeirarodolfo 2019-11-08 07:26:31 -03:00 committed by Erik Ziegler
parent 8481e94d4d
commit d70eae3eb0
2 changed files with 117 additions and 99 deletions

View File

@ -2,7 +2,7 @@
import './ImageThumbnail.styl'; import './ImageThumbnail.styl';
import { utils } from '@ohif/core'; import { utils } from '@ohif/core';
import React, { PureComponent } from 'react'; import React, { useState, useEffect, createRef } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ViewportErrorIndicator from '../../viewer/ViewportErrorIndicator'; import ViewportErrorIndicator from '../../viewer/ViewportErrorIndicator';
@ -13,97 +13,100 @@ import ViewportLoadingIndicator from '../../viewer/ViewportLoadingIndicator';
// - Set as external dependency? // - Set as external dependency?
// - Pass in the entire load and render function as a prop? // - Pass in the entire load and render function as a prop?
//import cornerstone from 'cornerstone-core'; //import cornerstone from 'cornerstone-core';
function ImageThumbnail(props) {
const {
width,
height,
imageSrc,
imageId,
stackPercentComplete,
error: propsError,
} = props;
export default class ImageThumbnail extends PureComponent { const [isLoading, setLoading] = useState(false);
static propTypes = { const [error, setError] = useState(false);
imageSrc: PropTypes.string, const [image, setImage] = useState({});
imageId: PropTypes.string, const canvasRef = createRef();
error: PropTypes.bool.isRequired,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
stackPercentComplete: PropTypes.number.isRequired,
};
static defaultProps = {
error: false,
stackPercentComplete: 0,
width: 217,
height: 123,
};
constructor(props) {
super(props);
this.cancelablePromises = [];
this.canvas = React.createRef();
this.state = {
loading: this.shouldRenderToCanvas(),
};
}
shouldRenderToCanvas() {
return this.props.imageId && !this.props.imageSrc;
}
fetchImage() {
const cancelablePromise = utils.makeCancelable(
cornerstone.loadAndCacheImage(this.props.imageId)
);
this.cancelablePromises.push(cancelablePromise);
return cancelablePromise;
}
componentDidMount() {
if (this.shouldRenderToCanvas()) {
this.fetchImage()
.then(image => {
cornerstone.renderToCanvas(this.canvas.current, image);
this.setState({
loading: false,
});
})
.catch(error => {
if (error.isCanceled) return;
this.setState({
loading: false,
error: true,
});
throw new Error(error);
});
}
}
componentWillUnmount() {
while (this.cancelablePromises.length > 0) {
this.cancelablePromises.pop().cancel();
}
}
render() {
let loadingOrError; let loadingOrError;
if (this.props.error) { let cancelablePromise;
if (propsError || error) {
loadingOrError = <ViewportErrorIndicator />; loadingOrError = <ViewportErrorIndicator />;
} else if (this.state.loading) { } else if (isLoading) {
loadingOrError = <ViewportLoadingIndicator />; loadingOrError = <ViewportLoadingIndicator />;
} }
const showStackLoadingProgressBar = const showStackLoadingProgressBar = stackPercentComplete !== undefined;
this.props.stackPercentComplete !== undefined;
const shouldRenderToCanvas = () => {
return imageId && !imageSrc;
};
const fetchImagePromise = () => {
if (!cancelablePromise) {
return;
}
setLoading(true);
cancelablePromise
.then(response => {
setImage(response);
})
.catch(error => {
if (error.isCanceled) return;
setLoading(false);
setError(true);
throw new Error(error);
});
};
const setImagePromise = () => {
if (shouldRenderToCanvas()) {
cancelablePromise = utils.makeCancelable(
cornerstone.loadAndCacheImage(imageId)
);
}
};
const purgeCancelablePromise = () => {
if (cancelablePromise) {
cancelablePromise.cancel();
}
};
useEffect(() => {
return () => {
purgeCancelablePromise();
};
}, []);
useEffect(() => {
if (image.imageId) {
cornerstone.renderToCanvas(canvasRef.current, image);
setLoading(false);
}
}, [image.imageId]);
useEffect(() => {
if (!image.imageId || image.imageId !== imageId) {
purgeCancelablePromise();
setImagePromise();
fetchImagePromise();
}
}, [imageId]);
return ( return (
<div className="ImageThumbnail"> <div className="ImageThumbnail">
<div className="image-thumbnail-canvas"> <div className="image-thumbnail-canvas">
{this.shouldRenderToCanvas() ? ( {shouldRenderToCanvas() ? (
<canvas <canvas ref={canvasRef} width={width} height={height} />
ref={this.canvas}
width={this.props.width}
height={this.props.height}
/>
) : ( ) : (
<img <img
className="static-image" className="static-image"
src={this.props.imageSrc} src={imageSrc}
//width={this.props.width} //width={this.props.width}
height={this.props.height} height={height}
alt={''} alt={''}
/> />
)} )}
@ -113,14 +116,29 @@ export default class ImageThumbnail extends PureComponent {
<div className="image-thumbnail-progress-bar"> <div className="image-thumbnail-progress-bar">
<div <div
className="image-thumbnail-progress-bar-inner" className="image-thumbnail-progress-bar-inner"
style={{ width: `${this.props.stackPercentComplete}%` }} style={{ width: `${stackPercentComplete}%` }}
/> />
</div> </div>
)} )}
{this.state.loading && ( {isLoading && <div className="image-thumbnail-loading-indicator"></div>}
<div className="image-thumbnail-loading-indicator"></div>
)}
</div> </div>
); );
}
} }
ImageThumbnail.propTypes = {
imageSrc: PropTypes.string,
imageId: PropTypes.string,
error: PropTypes.bool,
width: PropTypes.number,
height: PropTypes.number,
stackPercentComplete: PropTypes.number.isRequired,
};
ImageThumbnail.defaultProps = {
error: false,
stackPercentComplete: 0,
width: 217,
height: 123,
};
export default ImageThumbnail;

View File

@ -32,7 +32,7 @@ function StudyBrowser(props) {
return ( return (
<div <div
key={`container_${studyIndex}_${thumbIndex}`} key={thumb.displaySetInstanceUid}
className="thumbnail-container" className="thumbnail-container"
data-cy="thumbnail-list" data-cy="thumbnail-list"
> >