diff --git a/src/CONST.js b/src/CONST.js index f006b8f2f49f..9c09ce446770 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -28,6 +28,7 @@ const CONST = { ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, ANIMATION_IN_TIMING: 100, + ARROW_HIDE_DELAY: 3000, API_ATTACHMENT_VALIDATIONS: { // Same as the PHP layer allows diff --git a/src/components/AttachmentCarousel/index.js b/src/components/AttachmentCarousel/index.js index c1c8fd85145f..11f48b12d9ae 100644 --- a/src/components/AttachmentCarousel/index.js +++ b/src/components/AttachmentCarousel/index.js @@ -19,6 +19,7 @@ import tryResolveUrlFromApiRoot from '../../libs/tryResolveUrlFromApiRoot'; import Tooltip from '../Tooltip'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import compose from '../../libs/compose'; +import withWindowDimensions from '../withWindowDimensions'; const propTypes = { /** source is used to determine the starting index in the array of attachments */ @@ -52,6 +53,8 @@ class AttachmentCarousel extends React.Component { }; this.cycleThroughAttachments = this.cycleThroughAttachments.bind(this); + this.autoHideArrow = this.autoHideArrow.bind(this); + this.cancelAutoHideArrow = this.cancelAutoHideArrow.bind(this); this.getItemLayout = this.getItemLayout.bind(this); this.renderItem = this.renderItem.bind(this); this.renderCell = this.renderCell.bind(this); @@ -70,6 +73,7 @@ class AttachmentCarousel extends React.Component { componentDidMount() { this.makeStateWithReports(); + this.autoHideArrow(); } componentDidUpdate(prevProps) { @@ -111,6 +115,27 @@ class AttachmentCarousel extends React.Component { }); } + /** + * On a touch screen device, automatically hide the arrows + * if there is no interaction for 3 seconds. + */ + autoHideArrow() { + if (!this.canUseTouchScreen) { + return; + } + this.cancelAutoHideArrow(); + this.autoHideArrowTimeout = setTimeout(() => { + this.toggleArrowsVisibility(false); + }, CONST.ARROW_HIDE_DELAY); + } + + /** + * Cancels the automatic hiding of the arrows. + */ + cancelAutoHideArrow() { + clearTimeout(this.autoHideArrowTimeout); + } + /** * Toggles the visibility of the arrows * @param {Boolean} shouldShowArrow @@ -120,11 +145,16 @@ class AttachmentCarousel extends React.Component { if (this.state.isZoomed) { return; } - if (_.isBoolean(shouldShowArrow)) { - this.setState({shouldShowArrow}); - return; - } - this.setState(current => ({shouldShowArrow: !current.shouldShowArrow})); + this.setState((current) => { + const newShouldShowArrow = _.isBoolean(shouldShowArrow) ? shouldShowArrow : !current.shouldShowArrow; + return {shouldShowArrow: newShouldShowArrow}; + }, () => { + if (this.state.shouldShowArrow) { + this.autoHideArrow(); + } else { + this.cancelAutoHideArrow(); + } + }); } /** @@ -257,35 +287,55 @@ class AttachmentCarousel extends React.Component { this.setState({containerWidth: nativeEvent.layout.width + 1})} - onMouseEnter={() => this.toggleArrowsVisibility(true)} - onMouseLeave={() => this.toggleArrowsVisibility(false)} + onMouseEnter={() => !this.canUseTouchScreen && this.toggleArrowsVisibility(true)} + onMouseLeave={() => !this.canUseTouchScreen && this.toggleArrowsVisibility(false)} > {this.state.shouldShowArrow && ( <> {!isBackDisabled && ( - +