diff --git a/android/app/build.gradle b/android/app/build.gradle index ed259183df3c..4dcc674c352d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -155,8 +155,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001019701 - versionName "1.1.97-1" + versionCode 1001019702 + versionName "1.1.97-2" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b60e2e18e8ad..f2f5c64fe627 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -30,7 +30,7 @@ CFBundleVersion - 1.1.97.1 + 1.1.97.2 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 8568f3445b54..ba7ee1904a98 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.1.97.1 + 1.1.97.2 diff --git a/package-lock.json b/package-lock.json index 9ceff082092c..e737d5a3e0a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.1.97-1", + "version": "1.1.97-2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.1.97-1", + "version": "1.1.97-2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 32e588c32a2a..a1e8a62c336b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.1.97-1", + "version": "1.1.97-2", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", 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 && ( -