-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathThumbnailImage.js
111 lines (96 loc) · 4.06 KB
/
ThumbnailImage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import lodashClamp from 'lodash/clamp';
import React, {PureComponent} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import ImageWithSizeCalculation from './ImageWithSizeCalculation';
import styles from '../styles/styles';
import * as StyleUtils from '../styles/StyleUtils';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
const propTypes = {
/** Source URL for the preview image */
previewSourceURL: PropTypes.string.isRequired,
/** Any additional styles to apply */
// eslint-disable-next-line react/forbid-prop-types
style: PropTypes.any,
/** Whether the image requires an authToken */
isAuthTokenRequired: PropTypes.bool.isRequired,
/** Width of the thumbnail image */
imageWidth: PropTypes.number,
/** Height of the thumbnail image */
imageHeight: PropTypes.number,
...windowDimensionsPropTypes,
};
const defaultProps = {
style: {},
imageWidth: 200,
imageHeight: 200,
};
class ThumbnailImage extends PureComponent {
constructor(props) {
super(props);
this.updateImageSize = this.updateImageSize.bind(this);
const {thumbnailWidth, thumbnailHeight} = this.calculateThumbnailImageSize(props.imageWidth, props.imageHeight);
this.state = {
thumbnailWidth,
thumbnailHeight,
};
}
/**
* Compute the thumbnails width and height given original image dimensions.
*
* @param {Number} width - Width of the original image.
* @param {Number} height - Height of the original image.
* @returns {Object} - Object containing thumbnails width and height.
*/
calculateThumbnailImageSize(width, height) {
if (!width || !height) {
return {};
}
// Width of the thumbnail works better as a constant than it does
// a percentage of the screen width since it is relative to each screen
// Note: Clamp minimum width 40px to support touch device
let thumbnailScreenWidth = lodashClamp(width, 40, 250);
const imageHeight = height / (width / thumbnailScreenWidth);
let thumbnailScreenHeight = lodashClamp(imageHeight, 40, this.props.windowHeight * 0.40);
const aspectRatio = height / width;
// If thumbnail height is greater than its width, then the image is portrait otherwise landscape.
// For portrait images, we need to adjust the width of the image to keep the aspect ratio and vice-versa.
if (thumbnailScreenHeight > thumbnailScreenWidth) {
thumbnailScreenWidth = Math.round(thumbnailScreenHeight * (1 / aspectRatio));
} else {
thumbnailScreenHeight = Math.round(thumbnailScreenWidth * aspectRatio);
}
return {thumbnailWidth: thumbnailScreenWidth, thumbnailHeight: Math.max(40, thumbnailScreenHeight)};
}
/**
* Update the state with the computed thumbnail sizes.
*
* @param {{ width: number, height: number }} Params - width and height of the original image.
*/
updateImageSize({width, height}) {
const {thumbnailWidth, thumbnailHeight} = this.calculateThumbnailImageSize(width, height);
this.setState({thumbnailWidth, thumbnailHeight});
}
render() {
return (
<View style={[this.props.style, styles.overflowHidden]}>
<View
style={[
StyleUtils.getWidthAndHeightStyle(this.state.thumbnailWidth, this.state.thumbnailHeight),
styles.alignItemsCenter,
styles.justifyContentCenter,
]}
>
<ImageWithSizeCalculation
url={this.props.previewSourceURL}
onMeasure={this.updateImageSize}
isAuthTokenRequired={this.props.isAuthTokenRequired}
/>
</View>
</View>
);
}
}
ThumbnailImage.propTypes = propTypes;
ThumbnailImage.defaultProps = defaultProps;
export default withWindowDimensions(ThumbnailImage);