From b4a062e574c9776140ecdd50dbc80693d94041e1 Mon Sep 17 00:00:00 2001 From: pranavpandey1998official <44601530+pranavpandey1998official@users.noreply.github.com> Date: Thu, 18 Jul 2019 22:55:18 +0530 Subject: [PATCH] [NEW] File upload (#882) --- android/app/build.gradle | 1 + .../rocket/reactnative/MainApplication.java | 2 + android/settings.gradle | 2 + app/constants/settings.js | 6 + app/containers/MessageBox/UploadModal.js | 138 +- app/containers/MessageBox/index.js | 30 +- app/i18n/locales/en.js | 1 + app/i18n/locales/pt-BR.js | 1 + ios/Podfile | 1 + ios/Podfile.lock | 8 +- .../RNDocumentPicker.h | 1 + .../RNDocumentPicker.h | 1 + .../react-native-document-picker.podspec.json | 22 + ios/Pods/Manifest.lock | 8 +- ios/Pods/Pods.xcodeproj/project.pbxproj | 10252 ++++++++-------- ...ods-RocketChatRN-acknowledgements.markdown | 25 + .../Pods-RocketChatRN-acknowledgements.plist | 31 + .../Pods-RocketChatRN.debug.xcconfig | 6 +- .../Pods-RocketChatRN.release.xcconfig | 6 +- .../react-native-document-picker-dummy.m | 5 + .../react-native-document-picker-prefix.pch | 12 + .../react-native-document-picker.xcconfig | 9 + ios/RocketChatRN.xcodeproj/project.pbxproj | 3 + package.json | 1 + yarn.lock | 5 + 25 files changed, 5505 insertions(+), 5072 deletions(-) create mode 120000 ios/Pods/Headers/Private/react-native-document-picker/RNDocumentPicker.h create mode 120000 ios/Pods/Headers/Public/react-native-document-picker/RNDocumentPicker.h create mode 100644 ios/Pods/Local Podspecs/react-native-document-picker.podspec.json create mode 100644 ios/Pods/Target Support Files/react-native-document-picker/react-native-document-picker-dummy.m create mode 100644 ios/Pods/Target Support Files/react-native-document-picker/react-native-document-picker-prefix.pch create mode 100644 ios/Pods/Target Support Files/react-native-document-picker/react-native-document-picker.xcconfig diff --git a/android/app/build.gradle b/android/app/build.gradle index 1067fb0f..9d2271ef 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -174,6 +174,7 @@ android { dependencies { addUnimodulesDependencies() implementation "org.webkit:android-jsc:r241213" + implementation project(':react-native-document-picker') implementation project(':react-native-firebase') implementation project(':react-native-webview') implementation project(':react-native-orientation-locker') diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java index d87d301f..a2b1eed8 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java @@ -3,6 +3,7 @@ package chat.rocket.reactnative; import android.app.Application; import com.facebook.react.ReactApplication; +import io.github.elyx0.reactnativedocumentpicker.DocumentPickerPackage; import io.invertase.firebase.RNFirebasePackage; import io.invertase.firebase.fabric.crashlytics.RNFirebaseCrashlyticsPackage; import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; @@ -60,6 +61,7 @@ public class MainApplication extends Application implements ReactApplication, IN protected List getPackages() { return Arrays.asList( new MainReactPackage(), + new DocumentPickerPackage(), new RNFirebasePackage(), new RNFirebaseCrashlyticsPackage(), new RNFirebaseAnalyticsPackage(), diff --git a/android/settings.gradle b/android/settings.gradle index cdbc352b..e5b09caf 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -2,6 +2,8 @@ apply from: '../node_modules/react-native-unimodules/gradle.groovy' includeUnimodulesProjects() rootProject.name = 'RocketChatRN' +include ':react-native-document-picker' +project(':react-native-document-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-document-picker/android') include ':react-native-firebase' project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android') include ':react-native-webview' diff --git a/app/constants/settings.js b/app/constants/settings.js index 4e4d9939..17eb1560 100644 --- a/app/constants/settings.js +++ b/app/constants/settings.js @@ -73,5 +73,11 @@ export default { }, AutoTranslate_Enabled: { type: 'valueAsBoolean' + }, + FileUpload_MediaTypeWhiteList: { + type: 'valueAsString' + }, + FileUpload_MaxFileSize: { + type: 'valueAsNumber' } }; diff --git a/app/containers/MessageBox/UploadModal.js b/app/containers/MessageBox/UploadModal.js index d1d3f87f..4a5baa3c 100644 --- a/app/containers/MessageBox/UploadModal.js +++ b/app/containers/MessageBox/UploadModal.js @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import { View, Text, StyleSheet, Image, ScrollView, TouchableHighlight } from 'react-native'; +import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import Modal from 'react-native-modal'; import { responsive } from 'react-native-responsive-ui'; @@ -12,7 +13,9 @@ import Button from '../Button'; import I18n from '../../i18n'; import sharedStyles from '../../views/Styles'; import { isIOS } from '../../utils/deviceInfo'; -import { COLOR_PRIMARY, COLOR_BACKGROUND_CONTAINER, COLOR_WHITE } from '../../constants/colors'; +import { + COLOR_PRIMARY, COLOR_BACKGROUND_CONTAINER, COLOR_WHITE, COLOR_DANGER +} from '../../constants/colors'; import { CustomIcon } from '../../lib/Icons'; const cancelButtonColor = COLOR_BACKGROUND_CONTAINER; @@ -71,6 +74,23 @@ const styles = StyleSheet.create({ flex: 1, textAlign: 'center' }, + errorIcon: { + color: COLOR_DANGER + }, + fileMime: { + ...sharedStyles.textColorTitle, + ...sharedStyles.textBold, + textAlign: 'center', + fontSize: 20, + marginBottom: 20 + }, + errorContainer: { + margin: 20, + flex: 1, + textAlign: 'center', + justifyContent: 'center', + alignItems: 'center' + }, video: { flex: 1, borderRadius: 4, @@ -84,13 +104,19 @@ const styles = StyleSheet.create({ }); @responsive +@connect(state => ({ + FileUpload_MediaTypeWhiteList: state.settings.FileUpload_MediaTypeWhiteList, + FileUpload_MaxFileSize: state.settings.FileUpload_MaxFileSize +})) export default class UploadModal extends Component { static propTypes = { isVisible: PropTypes.bool, file: PropTypes.object, close: PropTypes.func, submit: PropTypes.func, - window: PropTypes.object + window: PropTypes.object, + FileUpload_MediaTypeWhiteList: PropTypes.string, + FileUpload_MaxFileSize: PropTypes.number } state = { @@ -132,12 +158,78 @@ export default class UploadModal extends Component { return false; } + canUploadFile = () => { + const { FileUpload_MediaTypeWhiteList, FileUpload_MaxFileSize, file } = this.props; + if (!(file && file.path)) { + return true; + } + if (file.size > FileUpload_MaxFileSize) { + return false; + } + if (!FileUpload_MediaTypeWhiteList) { + return false; + } + const allowedMime = FileUpload_MediaTypeWhiteList.split(','); + if (allowedMime.includes(file.mime)) { + return true; + } + const wildCardGlob = '/*'; + const wildCards = allowedMime.filter(item => item.indexOf(wildCardGlob) > 0); + if (wildCards.includes(file.mime.replace(/(\/.*)$/, wildCardGlob))) { + return true; + } + return false; + } + submit = () => { const { file, submit } = this.props; const { name, description } = this.state; submit({ ...file, name, description }); } + renderError = () => { + const { file, FileUpload_MaxFileSize, close } = this.props; + const { window: { width } } = this.props; + const errorMessage = (FileUpload_MaxFileSize < file.size) + ? 'error-file-too-large' + : 'error-invalid-file-type'; + return ( + + + {I18n.t(errorMessage)} + + + + + { file.mime } + + { + (isIOS) + ? ( +