* Enable study prefetcher and expose configs * Fix progress for all images * Enable study loading listener * Add new default for displaying progress bar for series * Use events instead of redux to improve performance * Add documentation, resolve issues with different datasets * CR Updates * CR Updates * CR Updates & Resolve issue when activating both stack and study prefetch * Add upward and update display set logic * Add new behavior to prefetching orders * Rollback display set check and activate cache check * Remove prefetch check * Check if displayset has images * Debounce check cache events * Remove usued debounce flags * Ignore prefetching same image * Use new image instead of image rendered * Continue prefetch after cache check * Update prefetch logic after checking cache * Remove log * Update displayset count default to 3 * Update netlify config Co-authored-by: Alireza <ar.sedghi@gmail.com>
159 lines
3.8 KiB
JavaScript
159 lines
3.8 KiB
JavaScript
/* global cornerstone */
|
|
import './ImageThumbnail.styl';
|
|
|
|
import { utils } from '@ohif/core';
|
|
import React, { useState, useEffect, createRef, useCallback } from 'react';
|
|
import classNames from 'classnames';
|
|
|
|
import PropTypes from 'prop-types';
|
|
import ViewportErrorIndicator from '../../viewer/ViewportErrorIndicator';
|
|
import ViewportLoadingIndicator from '../../viewer/ViewportLoadingIndicator';
|
|
|
|
// TODO: How should we have this component depend on Cornerstone?
|
|
// - Passed in as a prop?
|
|
// - Set as external dependency?
|
|
// - Pass in the entire load and render function as a prop?
|
|
//import cornerstone from 'cornerstone-core';
|
|
function ImageThumbnail(props) {
|
|
const {
|
|
active,
|
|
width,
|
|
height,
|
|
imageSrc,
|
|
imageId,
|
|
stackPercentComplete,
|
|
error: propsError,
|
|
showProgressBar,
|
|
} = props;
|
|
|
|
const [isLoading, setLoading] = useState(false);
|
|
const [error, setError] = useState(false);
|
|
const [image, setImage] = useState({});
|
|
const canvasRef = createRef();
|
|
|
|
let loadingOrError;
|
|
let cancelablePromise;
|
|
|
|
if (propsError || error) {
|
|
loadingOrError = <ViewportErrorIndicator />;
|
|
} else if (isLoading) {
|
|
loadingOrError = <ViewportLoadingIndicator />;
|
|
}
|
|
|
|
const showStackLoadingProgressBar =
|
|
showProgressBar && 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 = useCallback(() => {
|
|
if (cancelablePromise) {
|
|
cancelablePromise.cancel();
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
purgeCancelablePromise();
|
|
};
|
|
}, [purgeCancelablePromise]);
|
|
|
|
useEffect(() => {
|
|
if (image.imageId) {
|
|
cornerstone.renderToCanvas(canvasRef.current, image);
|
|
setLoading(false);
|
|
}
|
|
}, [canvasRef, image, image.imageId]);
|
|
|
|
useEffect(() => {
|
|
if (!image.imageId || image.imageId !== imageId) {
|
|
purgeCancelablePromise();
|
|
setImagePromise();
|
|
fetchImagePromise();
|
|
}
|
|
}, [
|
|
fetchImagePromise,
|
|
image.imageId,
|
|
imageId,
|
|
purgeCancelablePromise,
|
|
setImagePromise,
|
|
]);
|
|
|
|
return (
|
|
<div className={classNames('ImageThumbnail', { active: active })}>
|
|
<div className="image-thumbnail-canvas">
|
|
{shouldRenderToCanvas() ? (
|
|
<canvas ref={canvasRef} width={width} height={height} />
|
|
) : (
|
|
<img
|
|
className="static-image"
|
|
src={imageSrc}
|
|
//width={this.props.width}
|
|
height={height}
|
|
alt={''}
|
|
/>
|
|
)}
|
|
</div>
|
|
{loadingOrError}
|
|
{showStackLoadingProgressBar && (
|
|
<div className="image-thumbnail-progress-bar">
|
|
<div
|
|
className="image-thumbnail-progress-bar-inner"
|
|
style={{ width: `${stackPercentComplete}%` }}
|
|
/>
|
|
</div>
|
|
)}
|
|
{isLoading && <div className="image-thumbnail-loading-indicator"></div>}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
ImageThumbnail.propTypes = {
|
|
active: PropTypes.bool,
|
|
imageSrc: PropTypes.string,
|
|
imageId: PropTypes.string,
|
|
error: PropTypes.bool,
|
|
width: PropTypes.number,
|
|
height: PropTypes.number,
|
|
stackPercentComplete: PropTypes.number.isRequired,
|
|
showProgressBar: PropTypes.bool,
|
|
};
|
|
|
|
ImageThumbnail.defaultProps = {
|
|
active: false,
|
|
error: false,
|
|
stackPercentComplete: 0,
|
|
width: 217,
|
|
height: 123,
|
|
showProgressBar: true,
|
|
};
|
|
|
|
export default ImageThumbnail;
|