diff --git a/src/CONST.js b/src/CONST.js index 0a4f6cfe0475..32847df3ab37 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -808,6 +808,14 @@ const CONST = { // When generating a random value to fit in 7 digits (for the `middle` or `right` parts above), this is the maximum value to multiply by Math.random(). MAX_INT_FOR_RANDOM_7_DIGIT_VALUE: 10000000, IOS_KEYBOARD_SPACE_OFFSET: -30, + + PDF_PASSWORD_FORM: { + // Constants for password-related error responses received from react-pdf. + REACT_PDF_PASSWORD_RESPONSES: { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2, + }, + }, }; export default CONST; diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index ca0393926b9e..e5235244b719 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -1,6 +1,6 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; -import {View} from 'react-native'; +import {View, Animated} from 'react-native'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import lodashExtend from 'lodash/extend'; @@ -9,6 +9,7 @@ import CONST from '../CONST'; import Modal from './Modal'; import AttachmentView from './AttachmentView'; import styles from '../styles/styles'; +import * as StyleUtils from '../styles/StyleUtils'; import themeColors from '../styles/themes/default'; import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL'; import compose from '../libs/compose'; @@ -78,11 +79,14 @@ class AttachmentModal extends PureComponent { file: null, sourceURL: props.sourceURL, modalType: CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE, + isConfirmButtonDisabled: false, + confirmButtonFadeAnimation: new Animated.Value(1), }; this.submitAndClose = this.submitAndClose.bind(this); this.closeConfirmModal = this.closeConfirmModal.bind(this); this.validateAndDisplayFileToUpload = this.validateAndDisplayFileToUpload.bind(this); + this.updateConfirmButtonVisibility = this.updateConfirmButtonVisibility.bind(this); } /** @@ -123,8 +127,9 @@ class AttachmentModal extends PureComponent { * Execute the onConfirm callback and close the modal. */ submitAndClose() { - // If the modal has already been closed, don't allow another submission - if (!this.state.isModalOpen) { + // If the modal has already been closed or the confirm button is disabled + // do not submit. + if (!this.state.isModalOpen || this.state.isConfirmButtonDisabled) { return; } @@ -205,14 +210,38 @@ class AttachmentModal extends PureComponent { } } + /** + * In order to gracefully hide/show the confirm button when the keyboard + * opens/closes, apply an animation to fade the confirm button out/in. And since + * we're only updating the opacity of the confirm button, we must also conditionally + * disable it. + * + * @param {Boolean} shouldFadeOut If true, fade out confirm button. Otherwise fade in. + */ + updateConfirmButtonVisibility(shouldFadeOut) { + this.setState({isConfirmButtonDisabled: shouldFadeOut}); + const toValue = shouldFadeOut ? 0 : 1; + + Animated.timing(this.state.confirmButtonFadeAnimation, { + toValue, + duration: 100, + useNativeDriver: true, + }).start(); + } + render() { const sourceURL = this.props.isAuthTokenRequired ? addEncryptedAuthTokenToURL(this.state.sourceURL) : this.state.sourceURL; + // When the confirm button is visible we don't need bottom padding on the attachment view. + const attachmentViewPaddingStyles = this.props.onConfirm + ? [styles.pl5, styles.pr5, styles.pt5] + : styles.p5; + const attachmentViewStyles = this.props.isSmallScreenWidth || this.props.isMediumScreenWidth ? [styles.imageModalImageCenterContainer] - : [styles.imageModalImageCenterContainer, styles.p5]; + : [styles.imageModalImageCenterContainer, attachmentViewPaddingStyles]; const {fileName, fileExtension} = this.splitExtensionFromFileName(this.props.originalFileName || lodashGet(this.state, 'file.name', '')); @@ -246,20 +275,27 @@ class AttachmentModal extends PureComponent { /> {this.state.sourceURL && ( - + )} {/* If we have an onConfirm method show a confirmation button */} {this.props.onConfirm && ( -