From c696b6ccb4eb6282693c82717e31e5c691cd32d5 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 7 Jun 2021 15:35:24 +0300 Subject: [PATCH 1/6] chore: update attachment packages --- package-lock.json | 12 ++++++------ package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 58df082b00cf..e524af3f00d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33773,9 +33773,9 @@ "integrity": "sha512-isK9z1ibzG0Z8HPRhCk0krmvtLknONCpEHLGSpBtf+oQ02PllAXljGMFN/XJCnq3G3MdmP1CffZh3vm4e/A50w==" }, "react-native-document-picker": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-4.0.0.tgz", - "integrity": "sha512-tjIOBBcyjv4j5E1MDL2OvEKNpXxQybLNkjjfpTyDUzek7grZ5eOvSlp6i/Y3EfuIGLByeaw++9R1SZtOij6R7w==" + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-5.0.4.tgz", + "integrity": "sha512-PN3NYZFgz6McbcfH5Cu3yf3nE4UBAiJYdL26F5cjypOoCFhdfLz0NM13V/tVOLGhWZXNUmI3g4dhPQBthq+pJg==" }, "react-native-geolocation-service": { "version": "5.2.0", @@ -33824,9 +33824,9 @@ "integrity": "sha512-BF66XeP6dzuANsPmmFsJshM2Jyh/Mo1t8FsGc1L9Q9/sVP8MJULDabB1hms+eAoqgtyhMr5BuXV3E1hJ5U5H6Q==" }, "react-native-image-picker": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-2.3.4.tgz", - "integrity": "sha512-4UHu+zOyDT570r5mIbjH6h1iMrKIq/qfsKiAVUEZwncVegh0usJiEYNyJw4CEVwNeehmye/ia5sLDsa+kzIE4g==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-4.0.3.tgz", + "integrity": "sha512-S4a1jE4fAPDzmah/7OVTEAXGz1/wlGyClU+spygmek5rVLERR5BgwnkX3tLP/UvMQbfdPZNUbnH0hEe7su2AZg==" }, "react-native-iphone-x-helper": { "version": "1.3.1", diff --git a/package.json b/package.json index 98e909d7463e..40b5a3753967 100644 --- a/package.json +++ b/package.json @@ -73,11 +73,11 @@ "react-native": "0.64.1", "react-native-bootsplash": "^3.2.0", "react-native-config": "^1.4.0", - "react-native-document-picker": "^4.0.0", + "react-native-document-picker": "^5.0.4", "react-native-geolocation-service": "^5.2.0", "react-native-gesture-handler": "1.9.0", "react-native-image-pan-zoom": "^2.1.12", - "react-native-image-picker": "^2.3.3", + "react-native-image-picker": "^4.0.3", "react-native-keyboard-spacer": "^0.4.1", "react-native-modal": "^11.10.0", "react-native-onyx": "git+https://github.com/Expensify/react-native-onyx.git#52c254fbc4b96224d2ac087e57ef6efc4210ccc1", From 8c99df427234438c20dabd3ce1a0bc46a308635e Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 7 Jun 2021 16:09:56 +0300 Subject: [PATCH 2/6] refactor: migrate image-picker usages to v4 --- .../AttachmentPicker/index.native.js | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/components/AttachmentPicker/index.native.js b/src/components/AttachmentPicker/index.native.js index c51efab7dee9..dc3c1aad7db3 100644 --- a/src/components/AttachmentPicker/index.native.js +++ b/src/components/AttachmentPicker/index.native.js @@ -3,7 +3,7 @@ */ import React, {Component} from 'react'; import {Alert, Linking, View} from 'react-native'; -import RNImagePicker from 'react-native-image-picker'; +import {launchCamera, launchImageLibrary} from 'react-native-image-picker'; import RNDocumentPicker from 'react-native-document-picker'; import basePropTypes from './AttachmentPickerPropTypes'; import styles from '../../styles/styles'; @@ -25,9 +25,9 @@ const propTypes = { * for ImagePicker configuration options */ const imagePickerOptions = { - storageOptions: { - skipBackup: true, - }, + includeBase64: false, + saveToPhotos: false, + selectionLimit: 1, }; /** @@ -70,12 +70,12 @@ class AttachmentPicker extends Component { { icon: Camera, text: this.props.translate('attachmentPicker.takePhoto'), - pickAttachment: () => this.showImagePicker(RNImagePicker.launchCamera), + pickAttachment: () => this.showImagePicker(launchCamera), }, { icon: Gallery, text: this.props.translate('attachmentPicker.chooseFromGallery'), - pickAttachment: () => this.showImagePicker(RNImagePicker.launchImageLibrary), + pickAttachment: () => this.showImagePicker(launchImageLibrary), }, { icon: Paperclip, @@ -95,7 +95,7 @@ class AttachmentPicker extends Component { * @param {ImagePickerResponse|DocumentPickerResponse} attachment */ pickAttachment(attachment) { - if (attachment && !attachment.didCancel && !attachment.error) { + if (attachment) { if (attachment.width === -1 || attachment.height === -1) { this.showImageCorruptionAlert(); return; @@ -135,20 +135,25 @@ class AttachmentPicker extends Component { showImagePicker(imagePickerFunc) { return new Promise((resolve, reject) => { imagePickerFunc(imagePickerOptions, (response) => { - if (response.error) { - switch (response.error) { - case 'Camera permissions not granted': - case 'Permissions weren\'t granted': + if (response.didCancel) { + // When the user cancelled resolve with no attachment + return resolve(); + } + if (response.errorCode) { + switch (response.errorCode) { + case 'permission': this.showPermissionsAlert(); break; default: - this.showGeneralAlert(response.error); + this.showGeneralAlert(); break; } - reject(new Error(`Error during attachment selection: ${response.error}`)); + + return reject(new Error(`Error during attachment selection: ${response.errorMessage}`)); } - resolve(response); + // Resolve with the first (and only) selected file + return resolve(response.assets[0]); }); }); } From 2fe0b2bd2c4c9409a750a8b887ef3877f4f7eaae Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Mon, 7 Jun 2021 17:16:57 +0300 Subject: [PATCH 3/6] remove android:requestLegacyExternalStorage - no longer needed --- android/app/src/main/AndroidManifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8b7e639b1993..4a29d40e2e9f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,7 +14,6 @@ android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" - android:requestLegacyExternalStorage="true" android:theme="@style/AppTheme"> Date: Tue, 8 Jun 2021 11:40:35 +0300 Subject: [PATCH 4/6] add: launchCamera.js and launchCamera.android.js When an user installs E.cash on Android they've automatically granted camera permission since it's included in the manifest, but if they ever revoke the Permission we need to check and request it again as the image-picker library does not handle this --- .../AttachmentPicker/index.native.js | 3 +- .../AttachmentPicker/launchCamera.android.js | 32 +++++++++++++++++++ .../AttachmentPicker/launchCamera.js | 3 ++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/components/AttachmentPicker/launchCamera.android.js create mode 100644 src/components/AttachmentPicker/launchCamera.js diff --git a/src/components/AttachmentPicker/index.native.js b/src/components/AttachmentPicker/index.native.js index dc3c1aad7db3..a4b432719559 100644 --- a/src/components/AttachmentPicker/index.native.js +++ b/src/components/AttachmentPicker/index.native.js @@ -3,7 +3,7 @@ */ import React, {Component} from 'react'; import {Alert, Linking, View} from 'react-native'; -import {launchCamera, launchImageLibrary} from 'react-native-image-picker'; +import {launchImageLibrary} from 'react-native-image-picker'; import RNDocumentPicker from 'react-native-document-picker'; import basePropTypes from './AttachmentPickerPropTypes'; import styles from '../../styles/styles'; @@ -13,6 +13,7 @@ import {Camera, Gallery, Paperclip} from '../Icon/Expensicons'; import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions'; import withLocalize, {withLocalizePropTypes} from '../withLocalize'; import compose from '../../libs/compose'; +import launchCamera from './launchCamera'; const propTypes = { ...basePropTypes, diff --git a/src/components/AttachmentPicker/launchCamera.android.js b/src/components/AttachmentPicker/launchCamera.android.js new file mode 100644 index 000000000000..b431c55e756d --- /dev/null +++ b/src/components/AttachmentPicker/launchCamera.android.js @@ -0,0 +1,32 @@ +import {PermissionsAndroid} from 'react-native'; +import {launchCamera} from 'react-native-image-picker'; + +/** + * Launching the camera for Android involves checking for permissions + * And only then starting the camera + * If the user deny permission the callback will be called with an error response + * in the same format as the error returned by react-native-image-picker + * @param {CameraOptions} options + * @param {function} callback - callback called with the result + */ +export default function launchCameraAndroid(options, callback) { + // Checks current camera permissions and prompts the user in case they aren't granted + PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA) + .then((permission) => { + if (permission !== PermissionsAndroid.RESULTS.GRANTED) { + const error = new Error('User did not grant permissions'); + error.errorCode = 'permission'; + throw error; + } + + launchCamera(options, callback); + }) + .catch((error) => { + /* Intercept the permission error as well as any other errors and call the callback + * follow the same pattern expected for image picker results */ + callback({ + errorMessage: error.message, + errorCode: error.errorCode || 'others', + }); + }); +} diff --git a/src/components/AttachmentPicker/launchCamera.js b/src/components/AttachmentPicker/launchCamera.js new file mode 100644 index 000000000000..dc1f921086de --- /dev/null +++ b/src/components/AttachmentPicker/launchCamera.js @@ -0,0 +1,3 @@ +import {launchCamera} from 'react-native-image-picker'; + +export default launchCamera; From 8ca20b2e2e8fa1a3bcd8e09e36fd5961ba19a347 Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Thu, 10 Jun 2021 21:21:33 +0300 Subject: [PATCH 5/6] chore: update ios pods for image-picker and document-picker --- ios/Podfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 80f75b7712b9..f345442d4e6c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -351,11 +351,11 @@ PODS: - react-native-config/App (= 1.4.1) - react-native-config/App (1.4.1): - React-Core - - react-native-document-picker (4.0.0): + - react-native-document-picker (5.0.4): - React-Core - react-native-geolocation-service (5.2.0): - React - - react-native-image-picker (2.3.4): + - react-native-image-picker (4.0.3): - React-Core - react-native-netinfo (5.9.10): - React-Core @@ -773,9 +773,9 @@ SPEC CHECKSUMS: React-jsiexecutor: 124e8f99992490d0d13e0649d950d3e1aae06fe9 React-jsinspector: 500a59626037be5b3b3d89c5151bc3baa9abf1a9 react-native-config: d8b45133fd13d4f23bd2064b72f6e2c08b2763ed - react-native-document-picker: b3e78a8f7fef98b5cb069f20fc35797d55e68e28 + react-native-document-picker: 3690b7d064a1153d4d572ab6a045fdd130cbf14c react-native-geolocation-service: 7c9436da6dfdecd9526c62eac62ea2bc3f0cc8ea - react-native-image-picker: 32d1ad2c0024ca36161ae0d5c2117e2d6c441f11 + react-native-image-picker: 4089335b89b625d4e34d53fb249c48a7a791b3ea react-native-netinfo: 52cf0ee8342548a485e28f4b09e56b477567244d react-native-pdf: 4b5a9e4465a6a3b399e91dc4838eb44ddf716d1f react-native-plaid-link-sdk: 1a6593e2d3d790e8113c29178d883eb883f8c032 From 2a91ee3756bf28bf3d53411340efe2a613be6fff Mon Sep 17 00:00:00 2001 From: Peter Velkov Date: Thu, 10 Jun 2021 21:47:08 +0300 Subject: [PATCH 6/6] fix: document picker does not open on iOS It seems the timeout fix is still needed for this to work on iOS --- src/components/AttachmentPicker/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AttachmentPicker/index.native.js b/src/components/AttachmentPicker/index.native.js index a4b432719559..60712b1863d9 100644 --- a/src/components/AttachmentPicker/index.native.js +++ b/src/components/AttachmentPicker/index.native.js @@ -233,7 +233,7 @@ class AttachmentPicker extends Component { .then(this.pickAttachment) .catch(console.error) .finally(() => delete this.onModalHide), - 10, + 25, ); this.close();