diff --git a/src/components/ImageView/index.js b/src/components/ImageView/index.js index 2f2e4f15e3f3..2017962b5e83 100644 --- a/src/components/ImageView/index.js +++ b/src/components/ImageView/index.js @@ -7,6 +7,7 @@ import styles from '../../styles/styles'; import * as StyleUtils from '../../styles/StyleUtils'; import canUseTouchScreen from '../../libs/canUseTouchscreen'; import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions'; +import FullscreenLoadingIndicator from '../FullscreenLoadingIndicator'; const propTypes = { /** URL to full-sized image */ @@ -23,7 +24,10 @@ class ImageView extends PureComponent { this.onContainerPressIn = this.onContainerPressIn.bind(this); this.onContainerPress = this.onContainerPress.bind(this); this.onContainerPressOut = this.onContainerPressOut.bind(this); + this.imageLoadingStart = this.imageLoadingStart.bind(this); + this.imageLoadingEnd = this.imageLoadingEnd.bind(this); this.state = { + isLoading: false, containerHeight: 0, containerWidth: 0, isZoomed: false, @@ -227,6 +231,14 @@ class ImageView extends PureComponent { this.setState(prevState => ({isDragging: prevState.isMouseDown})); } + imageLoadingStart() { + this.setState({isLoading: true}); + } + + imageLoadingEnd() { + this.setState({isLoading: false}); + } + render() { if (this.canUseTouchScreen) { return ( @@ -240,7 +252,14 @@ class ImageView extends PureComponent { styles.h100, ]} resizeMode="contain" + onLoadStart={this.imageLoadingStart} + onLoadEnd={this.imageLoadingEnd} /> + {this.state.isLoading && ( + + )} ); } @@ -274,8 +293,16 @@ class ImageView extends PureComponent { styles.w100, ]} resizeMode="contain" + onLoadStart={this.imageLoadingStart} + onLoadEnd={this.imageLoadingEnd} /> + + {this.state.isLoading && ( + + )} ); } diff --git a/src/components/ImageView/index.native.js b/src/components/ImageView/index.native.js index 58e5ac905f9d..360210ac50f9 100644 --- a/src/components/ImageView/index.native.js +++ b/src/components/ImageView/index.native.js @@ -1,6 +1,8 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; -import {View, InteractionManager, PanResponder} from 'react-native'; +import { + View, InteractionManager, PanResponder, +} from 'react-native'; import Image from 'react-native-fast-image'; import ImageZoom from 'react-native-image-pan-zoom'; import ImageSize from 'react-native-image-size'; @@ -9,6 +11,7 @@ import styles from '../../styles/styles'; import * as StyleUtils from '../../styles/StyleUtils'; import variables from '../../styles/variables'; import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions'; +import FullscreenLoadingIndicator from '../FullscreenLoadingIndicator'; /** * On the native layer, we use a image library to handle zoom functionality @@ -25,6 +28,7 @@ class ImageView extends PureComponent { super(props); this.state = { + isLoading: false, thumbnailWidth: 100, thumbnailHeight: 100, imageWidth: undefined, @@ -43,6 +47,9 @@ class ImageView extends PureComponent { this.panResponder = PanResponder.create({ onStartShouldSetPanResponder: this.updatePanResponderTouches.bind(this), }); + + this.imageLoadingStart = this.imageLoadingStart.bind(this); + this.imageLoadingEnd = this.imageLoadingEnd.bind(this); } componentDidMount() { @@ -100,6 +107,14 @@ class ImageView extends PureComponent { return false; } + imageLoadingStart() { + this.setState({isLoading: true}); + } + + imageLoadingEnd() { + this.setState({isLoading: false}); + } + render() { // Default windowHeight accounts for the modal header height const windowHeight = this.props.windowHeight - variables.contentHeaderHeight; @@ -120,7 +135,10 @@ class ImageView extends PureComponent { + ); @@ -177,7 +195,9 @@ class ImageView extends PureComponent { this.props.style, ]} source={{uri: this.props.url}} - resizeMode={Image.resizeMode.contain} + resizeMode="contain" + onLoadStart={this.imageLoadingStart} + onLoadEnd={this.imageLoadingEnd} /> {/** Create an invisible view on top of the image so we can capture and set the amount of touches before @@ -194,6 +214,11 @@ class ImageView extends PureComponent { ]} /> + {this.state.isLoading && ( + + )} ); } diff --git a/src/components/ImageWithSizeCalculation.js b/src/components/ImageWithSizeCalculation.js index 698da27c610e..3b6eee240d11 100644 --- a/src/components/ImageWithSizeCalculation.js +++ b/src/components/ImageWithSizeCalculation.js @@ -1,9 +1,10 @@ import React, {PureComponent} from 'react'; -import {Image} from 'react-native'; +import {View, Image} from 'react-native'; import PropTypes from 'prop-types'; import Log from '../libs/Log'; import styles from '../styles/styles'; import makeCancellablePromise from '../libs/MakeCancellablePromise'; +import FullscreenLoadingIndicator from './FullscreenLoadingIndicator'; const propTypes = { /** Url for image to display */ @@ -29,6 +30,17 @@ const defaultProps = { * it can be appropriately resized. */ class ImageWithSizeCalculation extends PureComponent { + constructor(props) { + super(props); + + this.state = { + isLoading: false, + }; + + this.imageLoadingStart = this.imageLoadingStart.bind(this); + this.imageLoadingEnd = this.imageLoadingEnd.bind(this); + } + componentDidMount() { this.calculateImageSize(); } @@ -83,17 +95,39 @@ class ImageWithSizeCalculation extends PureComponent { }); } + imageLoadingStart() { + this.setState({isLoading: true}); + } + + imageLoadingEnd() { + this.setState({isLoading: false}); + } + render() { return ( - + > + + {this.state.isLoading && ( + + )} + ); } } diff --git a/src/styles/styles.js b/src/styles/styles.js index 9eab8076ae71..6ba66e585eae 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -317,6 +317,10 @@ const styles = { backgroundColor: 'transparent', }, + opacity1: { + opacity: 1, + }, + textDanger: { color: colors.red, },