Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ android {
}

dependencies {
implementation project(':react-native-document-picker')
Comment thread
pranavpandey1998official marked this conversation as resolved.
Outdated
addUnimodulesDependencies()
implementation "org.webkit:android-jsc:r241213"
implementation project(':react-native-firebase')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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;
Expand Down Expand Up @@ -60,6 +61,7 @@ public boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new DocumentPickerPackage(),
new RNFirebasePackage(),
new RNFirebaseCrashlyticsPackage(),
new RNFirebaseAnalyticsPackage(),
Expand Down
2 changes: 2 additions & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
apply from: '../node_modules/react-native-unimodules/gradle.groovy'
include ':react-native-document-picker'
Comment thread
pranavpandey1998official marked this conversation as resolved.
Outdated
project(':react-native-document-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-document-picker/android')
includeUnimodulesProjects()

rootProject.name = 'RocketChatRN'
Expand Down
6 changes: 6 additions & 0 deletions app/constants/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,11 @@ export default {
},
AutoTranslate_Enabled: {
type: 'valueAsBoolean'
},
FileUpload_MediaTypeWhiteList: {
type: 'valueAsString'
},
FileUpload_MaxFileSize: {
type: 'valueAsNumber'
}
};
158 changes: 135 additions & 23 deletions app/containers/MessageBox/UploadModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -12,7 +13,10 @@ 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, COLOR_TEXT
} from '../../constants/colors';
import { CustomIcon } from '../../lib/Icons';

const cancelButtonColor = COLOR_BACKGROUND_CONTAINER;

Expand Down Expand Up @@ -63,18 +67,48 @@ const styles = StyleSheet.create({
androidButtonText: {
fontSize: 18,
textAlign: 'center'
},
fileIcon: {
color: COLOR_PRIMARY,
margin: 20,
flex: 1,
textAlign: 'center'
},
errorIcon: {
color: COLOR_DANGER
},
fileMime: {
color: COLOR_TEXT,
Comment thread
pranavpandey1998official marked this conversation as resolved.
Outdated
...sharedStyles.textColorTitle,
...sharedStyles.textBold,
textAlign: 'center',
fontSize: 20,
marginBottom: 20
},
errorContainer: {
margin: 20,
flex: 1,
textAlign: 'center',
justifyContent: 'center',
alignItems: 'center'
}

});

@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 = {
Expand Down Expand Up @@ -116,12 +150,86 @@ 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 });
}

renderPreview() {
const { file } = this.props;
if (file.mime && file.mime.match(/image/)) {
return (<Image source={{ isStatic: true, uri: file.path }} style={styles.image} />);
}
return (<CustomIcon name='file-generic' size={72} style={styles.fileIcon} />);
}

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 (
<View style={[styles.container, { width: width - 32 }]}>
<View style={styles.titleContainer}>
<Text style={styles.title}>{I18n.t(errorMessage)}</Text>
</View>
<View style={styles.errorContainer}>
<CustomIcon name='circle-cross' size={120} style={styles.errorIcon} />
</View>
<Text style={styles.fileMime}>{ file.mime }</Text>
<View style={styles.buttonContainer}>
{
(isIOS)
? (
<Button
title={I18n.t('Cancel')}
type='secondary'
backgroundColor={cancelButtonColor}
style={styles.button}
onPress={close}
/>
)
: (
<TouchableHighlight
onPress={close}
style={[styles.androidButton, { backgroundColor: cancelButtonColor }]}
underlayColor={cancelButtonColor}
activeOpacity={0.5}
>
<Text style={[styles.androidButtonText, { ...sharedStyles.textBold, color: COLOR_PRIMARY }]}>{I18n.t('Cancel')}</Text>
</TouchableHighlight>
)
}
</View>
</View>
);
}

renderButtons = () => {
const { close } = this.props;
if (isIOS) {
Expand Down Expand Up @@ -168,7 +276,8 @@ export default class UploadModal extends Component {

render() {
const { window: { width }, isVisible, close } = this.props;
const { name, description, file } = this.state;
const { name, description } = this.state;
const showError = !this.canUploadFile();
return (
<Modal
isVisible={isVisible}
Expand All @@ -181,26 +290,29 @@ export default class UploadModal extends Component {
hideModalContentWhileAnimating
avoidKeyboard
>
<View style={[styles.container, { width: width - 32 }]}>
<View style={styles.titleContainer}>
<Text style={styles.title}>{I18n.t('Upload_file_question_mark')}</Text>
</View>

<ScrollView style={styles.scrollView}>
<Image source={{ isStatic: true, uri: file.path }} style={styles.image} />
<TextInput
placeholder={I18n.t('File_name')}
value={name}
onChangeText={value => this.setState({ name: value })}
/>
<TextInput
placeholder={I18n.t('File_description')}
value={description}
onChangeText={value => this.setState({ description: value })}
/>
</ScrollView>
{this.renderButtons()}
</View>
{(showError) ? this.renderError()
: (
<View style={[styles.container, { width: width - 32 }]}>
<View style={styles.titleContainer}>
<Text style={styles.title}>{I18n.t('Upload_file_question_mark')}</Text>
</View>

<ScrollView style={styles.scrollView}>
{this.renderPreview()}
<TextInput
placeholder={I18n.t('File_name')}
value={name}
onChangeText={value => this.setState({ name: value })}
/>
<TextInput
placeholder={I18n.t('File_description')}
value={description}
onChangeText={value => this.setState({ description: value })}
/>
</ScrollView>
{this.renderButtons()}
</View>
)}
</Modal>
);
}
Expand Down
34 changes: 30 additions & 4 deletions app/containers/MessageBox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { emojify } from 'react-emojione';
import { KeyboardAccessoryView } from 'react-native-keyboard-input';
import ImagePicker from 'react-native-image-crop-picker';
import equal from 'deep-equal';
import DocumentPicker from 'react-native-document-picker';
import ActionSheet from 'react-native-action-sheet';

import { userTyping as userTypingAction } from '../../actions/room';
Expand Down Expand Up @@ -62,6 +63,10 @@ const FILE_PHOTO_INDEX = 1;
fileOptions.push(I18n.t('Choose_from_library'));
const FILE_LIBRARY_INDEX = 2;

// File
fileOptions.push(I18n.t('Choose_file'));
const FILE_INDEX = 3;

class MessageBox extends Component {
static propTypes = {
rid: PropTypes.string.isRequired,
Expand Down Expand Up @@ -462,9 +467,8 @@ class MessageBox extends Component {
this.setShowSend(false);
}

sendImageMessage = async(file) => {
sendMediaMessage = async(file) => {
const { rid, tmid } = this.props;

this.setState({ file: { isVisible: false } });
const fileInfo = {
name: file.name,
Expand All @@ -477,7 +481,7 @@ class MessageBox extends Component {
try {
await RocketChat.sendFileMessage(rid, fileInfo, tmid);
} catch (e) {
log('err_send_image', e);
log('err_send_media_message', e);
}
}

Expand All @@ -499,6 +503,25 @@ class MessageBox extends Component {
}
}

chooseFile = async() => {
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles]
});
this.showUploadModal({
filename: res.name,
size: res.size,
mime: res.type,
path: res.uri
});
} catch (error) {
if (!DocumentPicker.isCancel(error)) {
log('chooseFile', error);
}
}
}


showUploadModal = (file) => {
this.setState({ file: { ...file, isVisible: true } });
}
Expand All @@ -520,6 +543,9 @@ class MessageBox extends Component {
case FILE_LIBRARY_INDEX:
this.chooseFromLibrary();
break;
case FILE_INDEX:
this.chooseFile();
break;
default:
break;
}
Expand Down Expand Up @@ -895,7 +921,7 @@ class MessageBox extends Component {
isVisible={(file && file.isVisible)}
file={file}
close={() => this.setState({ file: {} })}
submit={this.sendImageMessage}
submit={this.sendMediaMessage}
/>
</React.Fragment>
);
Expand Down
1 change: 1 addition & 0 deletions app/i18n/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export default {
Close_emoji_selector: 'Close emoji selector',
Choose: 'Choose',
Choose_from_library: 'Choose from library',
Choose_file: 'Choose file',
Comment thread
pranavpandey1998official marked this conversation as resolved.
Code: 'Code',
Collaborative: 'Collaborative',
Confirm: 'Confirm',
Expand Down
2 changes: 2 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ target 'RocketChatRN' do

use_unimodules!

pod 'react-native-document-picker', :path => '../node_modules/react-native-document-picker'
Comment thread
pranavpandey1998official marked this conversation as resolved.
Outdated

end

post_install do |installer|
Expand Down
Loading