Image upload improvements (#368)

<!-- INSTRUCTION: Keep the line below to notify all core developers about this new PR -->
@RocketChat/ReactNative

<!-- INSTRUCTION: Inform the issue number that this PR closes, or remove the line below -->
- [x] Crop image
- [x] Type image description (like web)
- [x] Show upload progress
- [x] "Try again" in case of error
- [x] Cancel upload while in progress
- [x] [Android] Zoom on photos

<!-- INSTRUCTION: Tell us more about your PR with screen shots if you can -->
![image](https://user-images.githubusercontent.com/804994/42526934-a12da304-844d-11e8-8668-f3d69369726a.png)
![image](https://user-images.githubusercontent.com/804994/42527829-297945fe-8450-11e8-9f0e-9e668dd33043.png)
This commit is contained in:
Diego Mello 2018-07-17 16:10:27 -03:00 committed by Guilherme Gazzo
parent 1faf9bf542
commit 2e245e4d7c
25 changed files with 1090 additions and 465 deletions

View File

@ -103,6 +103,7 @@ android {
abiFilters "armeabi-v7a", "x86"
}
missingDimensionStrategy "RNN.reactNativeVersion", "reactNative55"
vectorDrawables.useSupportLibrary = true
}
compileOptions {
@ -178,17 +179,17 @@ repositories {
}
dependencies {
implementation project(':react-native-image-crop-picker')
implementation project(':react-native-i18n')
implementation project(':react-native-fabric')
implementation project(':react-native-audio')
implementation project(":reactnativekeyboardinput")
implementation project(':react-native-video')
implementation project(':react-native-svg')
implementation project(':react-native-image-picker')
implementation project(':react-native-vector-icons')
implementation project(':react-native-fetch-blob')
implementation project(':rn-fetch-blob')
implementation project(':react-native-zeroconf')
implementation project(':react-native-toast')
implementation project(':@remobile/react-native-toast')
implementation project(':react-native-fast-image')
implementation project(':realm')
implementation project(':react-native-navigation')

View File

@ -4,6 +4,7 @@ import android.content.Context;
import android.os.Bundle;
import com.AlexanderZaytsev.RNI18n.RNI18nPackage;
import com.reactnative.ivpusic.imagepicker.PickerPackage;
import com.RNFetchBlob.RNFetchBlobPackage;
import com.balthazargronon.RCTZeroconf.ZeroconfReactPackage;
import com.brentvatne.react.ReactVideoPackage;
@ -12,7 +13,6 @@ import com.dylanvann.fastimage.FastImageViewPackage;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.horcrux.svg.SvgPackage;
import com.imagepicker.ImagePickerPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.reactnativenavigation.NavigationApplication;
import com.remobile.toast.RCTToastPackage;
@ -57,8 +57,8 @@ public class MainApplication extends NavigationApplication implements INotificat
public List<ReactPackage> createAdditionalReactPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new PickerPackage(),
new SvgPackage(),
new ImagePickerPackage(),
new VectorIconsPackage(),
new RNFetchBlobPackage(),
new ZeroconfReactPackage(),

View File

@ -25,6 +25,7 @@ allprojects {
maven {
url 'https://maven.google.com'
}
maven { url "https://jitpack.io" }
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"

View File

@ -1,4 +1,10 @@
rootProject.name = 'RocketChatRN'
include ':@remobile/react-native-toast'
project(':@remobile/react-native-toast').projectDir = new File(rootProject.projectDir, '../node_modules/@remobile/react-native-toast/android')
include ':rn-fetch-blob'
project(':rn-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/rn-fetch-blob/android')
include ':react-native-image-crop-picker'
project(':react-native-image-crop-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-crop-picker/android')
include ':react-native-i18n'
project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android')
include ':react-native-fast-image'
@ -13,18 +19,12 @@ include ':react-native-video'
project(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')
include ':react-native-svg'
project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
include ':react-native-image-picker'
project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-fetch-blob'
project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android')
include ':react-native-zeroconf'
project(':react-native-zeroconf').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-zeroconf/android')
include ':realm'
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
include ':react-native-toast'
project(':react-native-toast').projectDir = new File(settingsDir, '../node_modules/@remobile/react-native-toast/android')
include ':react-native-navigation'
project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/android/app/')
include ':reactnativenotifications'

View File

@ -16,8 +16,7 @@ const colors = {
const styles = StyleSheet.create({
container: {
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 2
paddingVertical: 10
},
text: {
textAlign: 'center',
@ -40,6 +39,9 @@ const styles = StyleSheet.create({
},
disabled: {
opacity: 0.5
},
border: {
borderRadius: 2
}
});
@ -48,7 +50,9 @@ export default class Button extends React.PureComponent {
title: PropTypes.string,
type: PropTypes.string,
onPress: PropTypes.func,
disabled: PropTypes.bool
disabled: PropTypes.bool,
margin: PropTypes.any,
backgroundColor: PropTypes.string
}
static defaultProps = {
@ -60,21 +64,22 @@ export default class Button extends React.PureComponent {
render() {
const {
title, type, onPress, disabled, ...otherProps
title, type, onPress, disabled, margin, backgroundColor, ...otherProps
} = this.props;
return (
<Touch
onPress={onPress}
accessibilityTraits='button'
style={Platform.OS === 'ios' && styles.margin}
style={Platform.OS === 'ios' && [(margin || styles.margin), styles.border]}
disabled={disabled}
{...otherProps}
>
<View
style={[
styles.container,
styles[`background_${ type }`],
Platform.OS === 'android' && styles.margin,
styles.border,
backgroundColor ? { backgroundColor } : styles[`background_${ type }`],
Platform.OS === 'android' && (margin || styles.margin),
disabled && styles.disabled
]}
>

View File

@ -0,0 +1,59 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ActionSheet from 'react-native-actionsheet';
import I18n from '../../i18n';
export default class FilesActions extends Component {
static propTypes = {
hideActions: PropTypes.func.isRequired,
takePhoto: PropTypes.func.isRequired,
chooseFromLibrary: PropTypes.func.isRequired
}
constructor(props) {
super(props);
// Cancel
this.options = [I18n.t('Cancel')];
this.CANCEL_INDEX = 0;
// Photo
this.options.push(I18n.t('Take_a_photo'));
this.PHOTO_INDEX = 1;
// Library
this.options.push(I18n.t('Choose_from_library'));
this.LIBRARY_INDEX = 2;
setTimeout(() => {
this.ActionSheet.show();
});
}
handleActionPress = (actionIndex) => {
const { takePhoto, chooseFromLibrary } = this.props;
switch (actionIndex) {
case this.PHOTO_INDEX:
takePhoto();
break;
case this.LIBRARY_INDEX:
chooseFromLibrary();
break;
default:
break;
}
this.props.hideActions();
}
render() {
return (
<ActionSheet
ref={o => this.ActionSheet = o}
options={this.options}
cancelButtonIndex={this.CANCEL_INDEX}
onPress={this.handleActionPress}
/>
);
}
}

View File

@ -0,0 +1,133 @@
import React, { Component } from 'react';
import { View, Text, StyleSheet, Image, ScrollView, Platform } from 'react-native';
import PropTypes from 'prop-types';
import Modal from 'react-native-modal';
import { responsive } from 'react-native-responsive-ui';
import equal from 'deep-equal';
import TextInput from '../TextInput';
import Button from '../Button';
import I18n from '../../i18n';
const cancelButtonColor = '#f7f8fa';
const styles = StyleSheet.create({
titleContainer: {
flexDirection: 'row',
paddingHorizontal: 16,
paddingTop: 16
},
title: {
fontWeight: 'bold'
},
container: {
height: Platform.OS === 'ios' ? 404 : 430,
backgroundColor: '#ffffff',
flexDirection: 'column'
},
scrollView: {
flex: 1,
padding: 16
},
image: {
height: 150,
flex: 1,
marginBottom: 16,
resizeMode: 'contain'
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 16,
backgroundColor: '#f7f8fa'
},
buttonMargin: {
margin: 0
}
});
@responsive
export default class UploadModal extends Component {
static propTypes = {
isVisible: PropTypes.bool,
file: PropTypes.object,
close: PropTypes.func,
submit: PropTypes.func,
window: PropTypes.object
}
state = {
name: '',
description: '',
file: {}
};
static getDerivedStateFromProps(props, state) {
if (!equal(props.file, state.file) && props.file && props.file.path) {
return {
file: props.file,
name: props.file.filename || 'Filename',
description: ''
};
}
return null;
}
_submit = () => {
const { file, submit } = this.props;
const { name, description } = this.state;
submit({ ...file, name, description });
}
render() {
const { window: { width }, isVisible, close } = this.props;
const { name, description, file } = this.state;
return (
<Modal
isVisible={isVisible}
style={{ alignItems: 'center' }} // TODO: need this?
onBackdropPress={() => this.props.close()}
onBackButtonPress={() => this.props.close()}
animationIn='fadeIn'
animationOut='fadeOut'
useNativeDriver
hideModalContentWhileAnimating
>
<View style={[styles.container, { width: width - 32 }]}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Upload file?</Text>
</View>
<ScrollView style={styles.scrollView}>
<Image source={{ isStatic: true, uri: file.path }} style={styles.image} />
<TextInput
placeholder='File name'
value={name}
onChangeText={value => this.setState({ name: value })}
/>
<TextInput
placeholder='File description'
value={description}
onChangeText={value => this.setState({ description: value })}
/>
</ScrollView>
<View style={styles.buttonContainer}>
<Button
title={I18n.t('Cancel')}
type='secondary'
backgroundColor={cancelButtonColor}
margin={styles.buttonMargin}
onPress={close}
/>
<Button
title={I18n.t('Send')}
type='primary'
margin={styles.buttonMargin}
onPress={this._submit}
/>
</View>
</View>
</Modal>
);
}
}

View File

@ -2,10 +2,10 @@ import React from 'react';
import PropTypes from 'prop-types';
import { View, TextInput, FlatList, Text, TouchableOpacity, Alert } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import ImagePicker from 'react-native-image-picker';
import { connect } from 'react-redux';
import { emojify } from 'react-emojione';
import { KeyboardAccessoryView } from 'react-native-keyboard-input';
import ImagePicker from 'react-native-image-crop-picker';
import { userTyping } from '../../actions/room';
import RocketChat from '../../lib/rocketchat';
@ -17,6 +17,8 @@ import Avatar from '../Avatar';
import CustomEmoji from '../EmojiPicker/CustomEmoji';
import { emojis } from '../../emojis';
import Recording from './Recording';
import FilesActions from './FilesActions';
import UploadModal from './UploadModal';
import './EmojiKeyboard';
import log from '../../utils/log';
import I18n from '../../i18n';
@ -28,6 +30,14 @@ const onlyUnique = function onlyUnique(value, index, self) {
return self.indexOf(({ _id }) => value._id === _id) === index;
};
const imagePickerConfig = {
cropping: true,
compressImageQuality: 0.8,
cropperAvoidEmptySpaceAroundImage: false,
cropperChooseText: I18n.t('Choose'),
cropperCancelText: I18n.t('Cancel')
};
@connect(state => ({
room: state.room,
message: state.messages.message,
@ -58,7 +68,11 @@ export default class MessageBox extends React.PureComponent {
text: '',
mentions: [],
showEmojiKeyboard: false,
recording: false
showFilesAction: false,
recording: false,
file: {
isVisible: false
}
};
this.users = [];
this.rooms = [];
@ -160,43 +174,60 @@ export default class MessageBox extends React.PureComponent {
key='fileIcon'
accessibilityLabel={I18n.t('Message actions')}
accessibilityTraits='button'
onPress={() => this.addFile()}
onPress={this.toggleFilesActions}
testID='messagebox-actions'
/>);
return icons;
}
addFile = () => {
const options = {
maxHeight: 1960,
maxWidth: 1960,
quality: 0.8
};
ImagePicker.showImagePicker(options, async(response) => {
if (response.didCancel) {
console.warn('User cancelled image picker');
} else if (response.error) {
log('ImagePicker Error', response.error);
} else {
const fileInfo = {
name: response.fileName,
size: response.fileSize,
type: response.type || 'image/jpeg',
// description: '',
store: 'Uploads'
};
try {
await RocketChat.sendFileMessage(this.props.rid, fileInfo, response.data);
} catch (e) {
log('addFile', e);
}
}
});
toggleFilesActions = () => {
this.setState(prevState => ({ showFilesAction: !prevState.showFilesAction }));
}
sendImageMessage = async(file) => {
this.setState({ file: { isVisible: false } });
const fileInfo = {
name: file.name,
description: file.description,
size: file.size,
type: file.mime,
store: 'Uploads',
path: file.path
};
try {
await RocketChat.sendFileMessage(this.props.rid, fileInfo);
} catch (e) {
log('sendImageMessage', e);
}
}
takePhoto = async() => {
try {
const image = await ImagePicker.openCamera(imagePickerConfig);
this.showUploadModal(image);
} catch (e) {
log('takePhoto', e);
}
}
chooseFromLibrary = async() => {
try {
const image = await ImagePicker.openPicker(imagePickerConfig);
this.showUploadModal(image);
} catch (e) {
log('chooseFromLibrary', e);
}
}
showUploadModal = (file) => {
this.setState({ file: { ...file, isVisible: true } });
}
editCancel() {
this.props.editCancel();
this.setState({ text: '' });
}
async openEmoji() {
await this.setState({
showEmojiKeyboard: true
@ -489,6 +520,20 @@ export default class MessageBox extends React.PureComponent {
);
};
renderFilesActions = () => {
if (!this.state.showFilesAction) {
return null;
}
return (
<FilesActions
key='files-actions'
hideActions={this.toggleFilesActions}
takePhoto={this.takePhoto}
chooseFromLibrary={this.chooseFromLibrary}
/>
);
}
renderContent() {
if (this.state.recording) {
return (<Recording onFinish={this.finishAudioMessage} />);
@ -525,18 +570,28 @@ export default class MessageBox extends React.PureComponent {
render() {
return (
<KeyboardAccessoryView
key='input'
renderContent={() => this.renderContent()}
kbInputRef={this.component}
kbComponent={this.state.showEmojiKeyboard ? 'EmojiKeyboard' : null}
onKeyboardResigned={() => this.onKeyboardResigned()}
onItemSelected={this._onEmojiSelected}
trackInteractive
// revealKeyboardInteractive
requiresSameParentToManageScrollView
addBottomView
/>
[
<KeyboardAccessoryView
key='input'
renderContent={() => this.renderContent()}
kbInputRef={this.component}
kbComponent={this.state.showEmojiKeyboard ? 'EmojiKeyboard' : null}
onKeyboardResigned={() => this.onKeyboardResigned()}
onItemSelected={this._onEmojiSelected}
trackInteractive
// revealKeyboardInteractive
requiresSameParentToManageScrollView
addBottomView
/>,
this.renderFilesActions(),
<UploadModal
key='upload-modal'
isVisible={(this.state.file && this.state.file.isVisible)}
file={this.state.file}
close={() => this.setState({ file: {} })}
submit={this.sendImageMessage}
/>
]
);
}
}

View File

@ -66,6 +66,7 @@ export default class extends React.PureComponent {
<PhotoModal
key='modal'
title={this.props.file.title}
description={this.props.file.description}
image={img}
isVisible={this.state.modalVisible}
onClose={() => this.setState({ modalVisible: false })}

View File

@ -1,15 +1,13 @@
import React from 'react';
import { ScrollView, View, Text, TouchableWithoutFeedback } from 'react-native';
import { View, Text, TouchableWithoutFeedback, ActivityIndicator, StyleSheet } from 'react-native';
import FastImage from 'react-native-fast-image';
import PropTypes from 'prop-types';
import Modal from 'react-native-modal';
import ImageViewer from 'react-native-image-zoom-viewer';
import { responsive } from 'react-native-responsive-ui';
const styles = {
const styles = StyleSheet.create({
imageWrapper: {
alignItems: 'stretch',
flex: 1
},
image: {
flex: 1
},
titleContainer: {
@ -22,42 +20,67 @@ const styles = {
textAlign: 'center',
fontSize: 16,
fontWeight: '600'
},
description: {
color: '#ffffff',
textAlign: 'center',
fontSize: 14,
fontWeight: '500'
},
indicatorContainer: {
alignItems: 'center',
justifyContent: 'center'
}
};
});
const margin = 40;
@responsive
export default class PhotoModal extends React.PureComponent {
static propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string,
image: PropTypes.string.isRequired,
isVisible: PropTypes.bool,
onClose: PropTypes.func.isRequired
onClose: PropTypes.func.isRequired,
window: PropTypes.object
}
render() {
const {
image, isVisible, onClose, title
image, isVisible, onClose, title, description, window: { width, height }
} = this.props;
return (
<Modal
isVisible={isVisible}
style={{ alignItems: 'center' }}
onBackdropPress={onClose}
onBackButtonPress={onClose}
animationIn='fadeIn'
animationOut='fadeOut'
>
<TouchableWithoutFeedback onPress={onClose}>
<View style={styles.titleContainer}>
<Text style={styles.title}>{title}</Text>
<View style={{ width: width - margin, height: height - margin }}>
<TouchableWithoutFeedback onPress={onClose}>
<View style={styles.titleContainer}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.description}>{description}</Text>
</View>
</TouchableWithoutFeedback>
<View style={styles.imageWrapper}>
<ImageViewer
imageUrls={[{ url: encodeURI(image) }]}
onClick={onClose}
backgroundColor='transparent'
enableSwipeDown
onSwipeDown={onClose}
renderIndicator={() => {}}
renderImage={props => <FastImage {...props} />}
loadingRender={() => (
<View style={[styles.indicatorContainer, { width, height }]}>
<ActivityIndicator />
</View>
)}
/>
</View>
</TouchableWithoutFeedback>
<View style={styles.imageWrapper}>
<ScrollView contentContainerStyle={styles.imageWrapper} maximumZoomScale={5}>
<TouchableWithoutFeedback onPress={onClose}>
<FastImage
style={styles.image}
source={{ uri: encodeURI(image) }}
mutable
resizeMode='contain'
/>
</TouchableWithoutFeedback>
</ScrollView>
</View>
</Modal>
);

View File

@ -111,6 +111,8 @@ export default {
Chats: 'Chats',
Close: 'Close',
Close_emoji_selector: 'Close emoji selector',
Choose: 'Choose',
Choose_from_library: 'Choose from library',
Code: 'Code',
Colaborative: 'Colaborative',
Connect: 'Connect',
@ -136,6 +138,7 @@ export default {
Email: 'Email',
Enable_notifications: 'Enable notifications',
Everyone_can_access_this_channel: 'Everyone can access this channel',
Error_uploading: 'Error uploading',
Files: 'Files',
Finish_recording: 'Finish recording',
For_your_security_you_must_enter_your_current_password_to_continue: 'For your security, you must enter your current password to continue',
@ -246,6 +249,7 @@ export default {
Search: 'Search',
Select_Avatar: 'Select Avatar',
Select_Users: 'Select Users',
Send: 'Send',
Send_audio_message: 'Send audio message',
Send_message: 'Send message',
Servers: 'Servers',
@ -266,6 +270,7 @@ export default {
Starred: 'Starred',
Start_of_conversation: 'Start of conversation',
Submit: 'Submit',
Take_a_photo: 'Take a photo',
tap_to_change_status: 'tap to change status',
Tap_to_view_servers_list: 'Tap to view servers list',
Terms_of_Service: ' Terms of Service ',
@ -276,6 +281,7 @@ export default {
Toggle_Drawer: 'Toggle_Drawer',
topic: 'topic',
Topic: 'Topic',
Try_again: 'Try again',
Type_the_channel_name_here: 'Type the channel name here',
unarchive: 'unarchive',
UNARCHIVE: 'UNARCHIVE',
@ -285,6 +291,7 @@ export default {
Unpin: 'Unpin',
unread_messages: 'unread messages',
Unstar: 'Unstar',
Uploading: 'Uploading',
User_added_by: 'User {{userAdded}} added by {{userBy}}',
User_has_been_key: 'User has been {{key}}!',
User_is_no_longer_role_by_: '{{user}} is no longer {{role}} by {{userBy}}',

View File

@ -14,7 +14,7 @@ if (__DEV__) {
/* eslint-disable global-require */
const reduxImmutableStateInvariant = require('redux-immutable-state-invariant').default();
sagaMiddleware = createSagaMiddleware({
// sagaMonitor: Reactotron.createSagaMonitor()
sagaMonitor: Reactotron.createSagaMonitor()
});
enhancers = compose(

View File

@ -0,0 +1,89 @@
import RNFetchBlob from 'rn-fetch-blob';
import reduxStore from '../createStore';
import database from '../realm';
const promises = {};
function _ufsCreate(fileInfo) {
return this.ddp.call('ufsCreate', fileInfo);
}
function _ufsComplete(fileId, store, token) {
return this.ddp.call('ufsComplete', fileId, store, token);
}
function _sendFileMessage(rid, data, msg = {}) {
return this.ddp.call('sendFileMessage', rid, null, data, msg);
}
export function isUploadActive(path) {
return !!promises[path];
}
export async function cancelUpload(path) {
if (promises[path]) {
await promises[path].cancel();
}
}
export async function sendFileMessage(rid, fileInfo) {
try {
const data = await RNFetchBlob.wrap(fileInfo.path);
if (!fileInfo.size) {
const fileStat = await RNFetchBlob.fs.stat(fileInfo.path);
fileInfo.size = fileStat.size;
fileInfo.name = fileStat.filename;
}
const { FileUpload_MaxFileSize } = reduxStore.getState().settings;
// -1 maxFileSize means there is no limit
if (FileUpload_MaxFileSize > -1 && fileInfo.size > FileUpload_MaxFileSize) {
return Promise.reject({ error: 'error-file-too-large' }); // eslint-disable-line
}
fileInfo.rid = rid;
database.write(() => {
database.create('uploads', fileInfo, true);
});
const result = await _ufsCreate.call(this, fileInfo);
promises[fileInfo.path] = RNFetchBlob.fetch('POST', result.url, {
'Content-Type': 'octet-stream'
}, data);
// Workaround for https://github.com/joltup/rn-fetch-blob/issues/96
setTimeout(() => {
promises[fileInfo.path].uploadProgress((loaded, total) => {
database.write(() => {
fileInfo.progress = Math.floor((loaded / total) * 100);
database.create('uploads', fileInfo, true);
});
});
});
await promises[fileInfo.path];
const completeResult = await _ufsComplete.call(this, result.fileId, fileInfo.store, result.token);
await _sendFileMessage.call(this, completeResult.rid, {
_id: completeResult._id,
type: completeResult.type,
size: completeResult.size,
name: completeResult.name,
description: completeResult.description,
url: completeResult.path
});
database.write(() => {
const upload = database.objects('uploads').filtered('path = $0', fileInfo.path);
database.delete(upload);
});
} catch (e) {
database.write(() => {
fileInfo.error = true;
database.create('uploads', fileInfo, true);
});
}
}

View File

@ -260,6 +260,22 @@ const rolesSchema = {
}
};
const uploadsSchema = {
name: 'uploads',
primaryKey: 'path',
properties: {
path: 'string',
rid: 'string',
name: { type: 'string', optional: true },
description: { type: 'string', optional: true },
size: { type: 'int', optional: true },
type: { type: 'string', optional: true },
store: { type: 'string', optional: true },
progress: { type: 'int', default: 1 },
error: { type: 'bool', default: false }
}
};
const schema = [
settingsSchema,
subscriptionSchema,
@ -279,7 +295,8 @@ const schema = [
messagesReactionsSchema,
messagesReactionsUsernamesSchema,
rolesSchema,
userMutedInRoomSchema
userMutedInRoomSchema,
uploadsSchema
];
// class DebouncedDb {

View File

@ -1,7 +1,7 @@
import { AsyncStorage, Platform } from 'react-native';
import { hashPassword } from 'react-native-meteor/lib/utils';
import foreach from 'lodash/forEach';
import RNFetchBlob from 'react-native-fetch-blob';
import RNFetchBlob from 'rn-fetch-blob';
import reduxStore from './createStore';
import defaultSettings from '../constants/settings';
@ -39,6 +39,7 @@ import loadMessagesForRoom from './methods/loadMessagesForRoom';
import loadMissedMessages from './methods/loadMissedMessages';
import sendMessage, { getMessage, _sendMessageCall } from './methods/sendMessage';
import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFileMessage';
import { getDeviceToken } from '../push';
@ -615,88 +616,9 @@ const RocketChat = {
joinRoom(rid) {
return call('joinRoom', rid);
},
/*
"name":"yXfExLErmNR5eNPx7.png"
"size":961
"type":"image/png"
"rid":"GENERAL"
"description":""
"store":"fileSystem"
*/
_ufsCreate(fileInfo) {
// return call('ufsCreate', fileInfo);
return call('ufsCreate', fileInfo);
},
// ["ZTE8CKHJt7LATv7Me","fileSystem","e8E96b2819"
_ufsComplete(fileId, store, token) {
return call('ufsComplete', fileId, store, token);
},
/*
- "GENERAL"
- {
"type":"image/png",
"size":961,
"name":"yXfExLErmNR5eNPx7.png",
"description":"",
"url":"/ufs/fileSystem/ZTE8CKHJt7LATv7Me/yXfExLErmNR5eNPx7.png"
}
*/
_sendFileMessage(rid, data, msg = {}) {
return call('sendFileMessage', rid, null, data, msg);
},
async sendFileMessage(rid, fileInfo, data) {
let placeholder;
try {
if (!data) {
data = await RNFetchBlob.wrap(fileInfo.path);
const fileStat = await RNFetchBlob.fs.stat(fileInfo.path);
fileInfo.size = fileStat.size;
fileInfo.name = fileStat.filename;
}
const { FileUpload_MaxFileSize } = reduxStore.getState().settings;
// -1 maxFileSize means there is no limit
if (FileUpload_MaxFileSize > -1 && fileInfo.size > FileUpload_MaxFileSize) {
return Promise.reject({ error: 'error-file-too-large' }); // eslint-disable-line
}
placeholder = RocketChat.getMessage(rid, 'Sending a file');
const result = await RocketChat._ufsCreate({ ...fileInfo, rid });
await RNFetchBlob.fetch('POST', result.url, {
'Content-Type': 'application/octet-stream'
}, data);
const completeRresult = await RocketChat._ufsComplete(result.fileId, fileInfo.store, result.token);
return await RocketChat._sendFileMessage(completeRresult.rid, {
_id: completeRresult._id,
type: completeRresult.type,
size: completeRresult.size,
name: completeRresult.name,
url: completeRresult.path
});
} catch (e) {
return e;
} finally {
// TODO: fix that
try {
if (placeholder) {
database.write(() => {
const msg = database.objects('messages').filtered('_id = $0', placeholder._id);
database.delete(msg);
});
}
} catch (e) {
console.error(e);
}
}
},
sendFileMessage,
cancelUpload,
isUploadActive,
getSettings,
getPermissions,
getCustomEmoji,

View File

@ -254,7 +254,7 @@ export default class RoomItem extends React.Component {
<Markdown
msg={this.lastMessage}
style={{
view: {
root: {
flex: 1
}
}}

View File

@ -5,7 +5,7 @@ import { connect } from 'react-redux';
import Dialog from 'react-native-dialog';
import SHA256 from 'js-sha256';
import Icon from 'react-native-vector-icons/MaterialIcons';
import ImagePicker from 'react-native-image-picker';
import ImagePicker from 'react-native-image-crop-picker';
import RNPickerSelect from 'react-native-picker-select';
import LoggedView from '../View';
@ -243,19 +243,21 @@ export default class ProfileView extends LoggedView {
}
}
pickImage = () => {
pickImage = async() => {
const options = {
title: I18n.t('Select_Avatar')
cropping: true,
compressImageQuality: 0.8,
cropperAvoidEmptySpaceAroundImage: false,
cropperChooseText: I18n.t('Choose'),
cropperCancelText: I18n.t('Cancel'),
includeBase64: true
};
ImagePicker.showImagePicker(options, async(response) => {
if (response.didCancel) {
console.warn('User cancelled image picker');
} else if (response.error) {
log('ImagePicker Error', response.error);
} else {
this.setAvatar({ url: response.uri, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' });
}
});
try {
const response = await ImagePicker.openPicker(options);
this.setAvatar({ url: response.path, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' });
} catch (error) {
console.warn(error);
}
}
renderAvatarButton = ({

View File

@ -0,0 +1,158 @@
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { responsive } from 'react-native-responsive-ui';
import database from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import I18n from '../../i18n';
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
width: '100%',
maxHeight: 246
},
item: {
backgroundColor: '#F1F2F4',
height: 54,
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: '#CACED1',
justifyContent: 'center',
paddingHorizontal: 20
},
row: {
flexDirection: 'row',
alignItems: 'center'
},
descriptionContainer: {
flexDirection: 'column',
flex: 1,
marginLeft: 10
},
descriptionText: {
fontSize: 16,
lineHeight: 20,
color: '#54585E'
},
progress: {
position: 'absolute',
bottom: 0,
backgroundColor: '#1D74F5',
height: 3
},
tryAgainButtonText: {
color: '#1D74F5',
fontSize: 16,
fontWeight: '500',
lineHeight: 20
}
});
@responsive
export default class UploadProgress extends Component {
static propTypes = {
window: PropTypes.object,
rid: PropTypes.string
}
constructor(props) {
super(props);
this.state = {
uploads: []
};
this.uploads = database.objects('uploads').filtered('rid = $0', this.props.rid);
this.uploads.addListener(this.updateUploads);
}
componentDidMount() {
this.uploads.forEach((u) => {
if (!RocketChat.isUploadActive(u.path)) {
database.write(() => {
const [upload] = database.objects('uploads').filtered('path = $0', u.path);
if (upload) {
upload.error = true;
}
});
}
});
}
componentWillUnmount() {
this.uploads.removeAllListeners();
}
deleteUpload = (item) => {
database.write(() => database.delete(item));
}
cancelUpload = async(item) => {
try {
await RocketChat.cancelUpload(item.path);
} catch (e) {
log('UploadProgess.cancelUpload', e);
}
}
tryAgain = async(item) => {
try {
database.write(() => {
item.error = false;
});
await RocketChat.sendFileMessage(this.props.rid, JSON.parse(JSON.stringify(item)));
} catch (e) {
log('UploadProgess.tryAgain', e);
}
}
updateUploads = () => {
this.setState({ uploads: this.uploads });
}
renderItemContent = (item) => {
if (!item.error) {
return (
[
<View key='row' style={styles.row}>
<Icon name='image' size={20} color='#9EA2A8' />
<Text style={[styles.descriptionContainer, styles.descriptionText]} ellipsizeMode='tail' numberOfLines={1}>
{I18n.t('Uploading')} {item.name}
</Text>
<Icon name='close' size={20} color='#9EA2A8' onPress={() => this.cancelUpload(item)} />
</View>,
<View key='progress' style={[styles.progress, { width: (this.props.window.width * item.progress) / 100 }]} />
]
);
}
return (
<View style={styles.row}>
<Icon name='warning' size={20} color='#FF5050' />
<View style={styles.descriptionContainer}>
<Text style={styles.descriptionText}>{I18n.t('Error_uploading')} {item.name}</Text>
<TouchableOpacity onPress={() => this.tryAgain(item)}>
<Text style={styles.tryAgainButtonText}>{I18n.t('Try_again')}</Text>
</TouchableOpacity>
</View>
<Icon name='close' size={20} color='#9EA2A8' onPress={() => this.deleteUpload(item)} />
</View>
);
}
renderItem = (item, index) => (
<View key={item.path} style={[styles.item, index !== 0 ? { marginTop: 10 } : {}]}>
{this.renderItemContent(item)}
</View>
);
render() {
const { uploads } = this.state;
return (
<ScrollView style={styles.container}>
{uploads.map((item, i) => this.renderItem(item, i))}
</ScrollView>
);
}
}

View File

@ -15,6 +15,7 @@ import MessageActions from '../../containers/MessageActions';
import MessageErrorActions from '../../containers/MessageErrorActions';
import MessageBox from '../../containers/MessageBox';
import ReactionPicker from './ReactionPicker';
import UploadProgress from './UploadProgress';
import styles from './styles';
import log from '../../utils/log';
import I18n from '../../i18n';
@ -289,6 +290,7 @@ export default class RoomView extends LoggedView {
null}
{this.props.showErrorActions ? <MessageErrorActions /> : null}
<ReactionPicker onEmojiSelected={this.onReactionPress} />
<UploadProgress rid={this.rid} />
</View>
);
}

View File

@ -14,6 +14,7 @@
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
00E356F31AD99517003FC87E /* RocketChatRNTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RocketChatRNTests.m */; };
09CB5909C1E64707832358CE /* libRNI18n-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */; };
0AC2050A2CA1485DAC130425 /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 72FB6BA830CE4EEBAC92BF54 /* Feather.ttf */; };
0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B37C79D9BD0742CE936B6982 /* libc++.tbd */; };
0DC38A29B0E54AF4AF96CB95 /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2EADB1731B5E47D093292B59 /* MaterialCommunityIcons.ttf */; };
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
@ -56,6 +57,11 @@
7A3562E620E1569000A4CF66 /* libReactNativeNavigation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A3562E520E1567900A4CF66 /* libReactNativeNavigation.a */; };
7A430E4F20238C46008F55BC /* libRCTCustomInputController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A430E1E20238C02008F55BC /* libRCTCustomInputController.a */; };
7A8DEB5A20ED0BEC00C5DCE4 /* libRNNotifications.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A8DEB5220ED0BDE00C5DCE4 /* libRNNotifications.a */; };
7A6EDBDC20ED6DCF0086E097 /* ImageCropPickerSDK in Resources */ = {isa = PBXBuildFile; fileRef = 7A6EDBDB20ED6DCF0086E097 /* ImageCropPickerSDK */; };
7A6EDBDE20ED6E010086E097 /* RSKImageCropper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */; };
7A6EDBDF20ED6E010086E097 /* RSKImageCropper.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
7A6EDBE220ED6E0E0086E097 /* QBImagePicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */; };
7A6EDBE320ED6E0E0086E097 /* QBImagePicker.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
7AFB806E205AE65700D004E7 /* libRCTToast.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AFB804C205AE63100D004E7 /* libRCTToast.a */; };
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
8A159EDB97C44E52AF62D69C /* libRNSVG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA50CE47374C4C35BE6D9D58 /* libRNSVG.a */; };
@ -70,9 +76,9 @@
B8E79AF41F3CD167005B464F /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB61A68108700A75B9A /* Info.plist */; };
BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2E2837F110483CA29EE0D4 /* libFastImage.a */; };
BED2B77AA660460E8BC9F8E0 /* libRNFetchBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6533FB90166345D29F1B91C0 /* libRNFetchBlob.a */; };
C758F0BD5C3244E2BA073E61 /* libRNImagePicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B696712EE2345A59F007A88 /* libRNImagePicker.a */; };
CBD0E0A35B174C4DBFED3B31 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E528DE3A405E43B4A37ABA68 /* Zocial.ttf */; };
D6408D9E4A864FF6BA986857 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */; };
E27A0F0529F74A6E80BBAA8C /* libimageCropPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */; };
EF736EF520A64AE8820E684A /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF26CC845883492D8AC8869B /* libRealmReact.a */; };
F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 921481B47B50490CA761932E /* libRNI18n.a */; };
/* End PBXBuildFile section */
@ -295,13 +301,6 @@
remoteGlobalIDString = F60690131CA2766F0003FB26;
remoteInfo = RealmReact;
};
60B837831F3F6F4C00677E56 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 014A3B5C1C6CF33500B6D375;
remoteInfo = RNImagePicker;
};
78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
@ -337,6 +336,13 @@
remoteGlobalIDString = 39DF4FE71E00394E00F5B4B2;
remoteInfo = RCTCustomInputController;
};
7A6EDBD920ED6CBB0086E097 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3400A8081CEB54A6008A0BC7;
remoteInfo = imageCropPicker;
};
7A770EC120BECDC7001AD51A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 1845C223DA364898A8400573 /* FastImage.xcodeproj */;
@ -372,6 +378,13 @@
remoteGlobalIDString = 641E28441F0EEC8500443AF6;
remoteInfo = "RCTVideo-tvOS";
};
7A8C915220F39A8000C8F5EE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = A15C300E1CD25C330074CB35;
remoteInfo = RNFetchBlob;
};
7A8DEB5120ED0BDE00C5DCE4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */;
@ -470,13 +483,6 @@
remoteGlobalIDString = D834CED81CC64F2400FA5668;
remoteInfo = KeyboardTrackingView;
};
B8E79A8D1F3CCC6D005B464F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = A15C300E1CD25C330074CB35;
remoteInfo = RNFetchBlob;
};
B8E79A901F3CCC6D005B464F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 22A8B76C8EBA443BB97CE82D /* RNVectorIcons.xcodeproj */;
@ -500,6 +506,21 @@
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
7A6EDBE020ED6E020086E097 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
7A6EDBDF20ED6E010086E097 /* RSKImageCropper.framework in Embed Frameworks */,
7A6EDBE320ED6E0E0086E097 /* QBImagePicker.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
@ -511,6 +532,7 @@
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* RocketChatRNTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RocketChatRNTests.m; sourceTree = "<group>"; };
06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFetchBlob.xcodeproj; path = "../node_modules/rn-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = "<group>"; };
1142E3442BA94B19BCF52814 /* libRNAudio.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNAudio.a; sourceTree = "<group>"; };
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
@ -523,6 +545,7 @@
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RocketChatRN/main.m; sourceTree = "<group>"; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
1845C223DA364898A8400573 /* FastImage.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = FastImage.xcodeproj; path = "../node_modules/react-native-fast-image/ios/FastImage.xcodeproj"; sourceTree = "<group>"; };
1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libimageCropPicker.a; sourceTree = "<group>"; };
1B0746E708284151B8AD1198 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = file; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; };
1D3BB00B9ABF44EA9BD71318 /* libSafariViewManager.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSafariViewManager.a; sourceTree = "<group>"; };
20CE3E407E0D4D9E8C9885F2 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTVideo.a; sourceTree = "<group>"; };
@ -535,13 +558,12 @@
3B696712EE2345A59F007A88 /* libRNImagePicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNImagePicker.a; sourceTree = "<group>"; };
4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SafariViewManager.xcodeproj; path = "../node_modules/react-native-safari-view/SafariViewManager.xcodeproj"; sourceTree = "<group>"; };
41FE03CD3B554249859F01BA /* RNZeroconf.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNZeroconf.xcodeproj; path = "../node_modules/react-native-zeroconf/ios/RNZeroconf.xcodeproj"; sourceTree = "<group>"; };
4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNImagePicker.xcodeproj; path = "../node_modules/react-native-image-picker/ios/RNImagePicker.xcodeproj"; sourceTree = "<group>"; };
4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFetchBlob.xcodeproj; path = "../node_modules/react-native-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = "<group>"; };
5A0EEFAF8AB14F5B9E796CDD /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; };
5A8684E7C27E426C9206E980 /* RealmReact.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RealmReact.xcodeproj; path = "../node_modules/realm/react-native/ios/RealmReact.xcodeproj"; sourceTree = "<group>"; };
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; };
6533FB90166345D29F1B91C0 /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = "<group>"; };
72FB6BA830CE4EEBAC92BF54 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; };
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
7A2D1FE620726EF600D0AA04 /* SMXCrashlytics.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SMXCrashlytics.xcodeproj; path = "../node_modules/react-native-fabric/ios/SMXCrashlytics.xcodeproj"; sourceTree = "<group>"; };
7A309C9B20724870000C6B13 /* Fabric.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = Fabric.sh; path = RocketChatRN/Fabric.sh; sourceTree = "<group>"; };
@ -551,7 +573,11 @@
7A3562E020E1567900A4CF66 /* ReactNativeNavigation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeNavigation.xcodeproj; path = "../node_modules/react-native-navigation/ios/ReactNativeNavigation.xcodeproj"; sourceTree = "<group>"; };
7A430E1620238C01008F55BC /* RCTCustomInputController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTCustomInputController.xcodeproj; path = "../node_modules/react-native-keyboard-input/lib/ios/RCTCustomInputController.xcodeproj"; sourceTree = "<group>"; };
7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNNotifications.xcodeproj; path = "../node_modules/react-native-notifications/RNNotifications/RNNotifications.xcodeproj"; sourceTree = "<group>"; };
7A6EDBDB20ED6DCF0086E097 /* ImageCropPickerSDK */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ImageCropPickerSDK; path = "../node_modules/react-native-image-crop-picker/ios/ImageCropPickerSDK"; sourceTree = "<group>"; };
7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = RSKImageCropper.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = QBImagePicker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7AFB8035205AE63000D004E7 /* RCTToast.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTToast.xcodeproj; path = "../node_modules/@remobile/react-native-toast/ios/RCTToast.xcodeproj"; sourceTree = "<group>"; };
8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = imageCropPicker.xcodeproj; path = "../node_modules/react-native-image-crop-picker/ios/imageCropPicker.xcodeproj"; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; };
921481B47B50490CA761932E /* libRNI18n.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNI18n.a; sourceTree = "<group>"; };
@ -610,17 +636,19 @@
EF736EF520A64AE8820E684A /* libRealmReact.a in Frameworks */,
0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */,
24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */,
7A6EDBE220ED6E0E0086E097 /* QBImagePicker.framework in Frameworks */,
33647F7997A2493E9E1343B3 /* libRNZeroconf.a in Frameworks */,
BED2B77AA660460E8BC9F8E0 /* libRNFetchBlob.a in Frameworks */,
77C35F50C01C43668188886C /* libRNVectorIcons.a in Frameworks */,
8A159EDB97C44E52AF62D69C /* libRNSVG.a in Frameworks */,
C758F0BD5C3244E2BA073E61 /* libRNImagePicker.a in Frameworks */,
7A6EDBDE20ED6E010086E097 /* RSKImageCropper.framework in Frameworks */,
8ECBD927DDAC4987B98E102E /* libRCTVideo.a in Frameworks */,
7A32C247206D791D001C80E9 /* Crashlytics.framework in Frameworks */,
2C800DF680F8451599E80AF1 /* libSafariViewManager.a in Frameworks */,
74815BBCB91147C08C8F7B3D /* libRNAudio.a in Frameworks */,
BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */,
F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */,
E27A0F0529F74A6E80BBAA8C /* libimageCropPicker.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -793,14 +821,6 @@
name = Products;
sourceTree = "<group>";
};
60B8375C1F3F6F4B00677E56 /* Products */ = {
isa = PBXGroup;
children = (
60B837841F3F6F4C00677E56 /* libRNImagePicker.a */,
);
name = Products;
sourceTree = "<group>";
};
78C398B11ACF4ADC00677621 /* Products */ = {
isa = PBXGroup;
children = (
@ -835,6 +855,14 @@
name = Products;
sourceTree = "<group>";
};
7A6EDBD620ED6CBB0086E097 /* Products */ = {
isa = PBXGroup;
children = (
7A6EDBDA20ED6CBB0086E097 /* libimageCropPicker.a */,
);
name = Products;
sourceTree = "<group>";
};
7A770EBC20BECDC7001AD51A /* Products */ = {
isa = PBXGroup;
children = (
@ -861,6 +889,14 @@
name = Products;
sourceTree = "<group>";
};
7A8C912120F39A8000C8F5EE /* Products */ = {
isa = PBXGroup;
children = (
7A8C915320F39A8000C8F5EE /* libRNFetchBlob.a */,
);
name = Products;
sourceTree = "<group>";
};
7A8DEB1C20ED0BDE00C5DCE4 /* Products */ = {
isa = PBXGroup;
children = (
@ -900,15 +936,15 @@
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
5A8684E7C27E426C9206E980 /* RealmReact.xcodeproj */,
41FE03CD3B554249859F01BA /* RNZeroconf.xcodeproj */,
4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */,
22A8B76C8EBA443BB97CE82D /* RNVectorIcons.xcodeproj */,
C23AEF1D9EBE4A38A1A6B97B /* RNSVG.xcodeproj */,
4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */,
AD0379F2BCE84C968538CDAF /* RCTVideo.xcodeproj */,
4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */,
C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */,
1845C223DA364898A8400573 /* FastImage.xcodeproj */,
22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */,
8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */,
0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@ -925,6 +961,9 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
7A6EDBE120ED6E0E0086E097 /* QBImagePicker.framework */,
7A6EDBDD20ED6E010086E097 /* RSKImageCropper.framework */,
7A6EDBDB20ED6DCF0086E097 /* ImageCropPickerSDK */,
7A32C245206D791D001C80E9 /* Crashlytics.framework */,
7A32C20F206D791D001C80E9 /* Fabric.framework */,
13B07FAE1A68108700A75B9A /* RocketChatRN */,
@ -972,6 +1011,7 @@
F88C6541BD764BEEABB87272 /* Octicons.ttf */,
8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */,
E528DE3A405E43B4A37ABA68 /* Zocial.ttf */,
72FB6BA830CE4EEBAC92BF54 /* Feather.ttf */,
);
name = Resources;
sourceTree = "<group>";
@ -1017,18 +1057,11 @@
FD2E2837F110483CA29EE0D4 /* libFastImage.a */,
921481B47B50490CA761932E /* libRNI18n.a */,
C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */,
1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */,
);
name = "Recovered References";
sourceTree = "<group>";
};
B8E79A881F3CCC6C005B464F /* Products */ = {
isa = PBXGroup;
children = (
B8E79A8E1F3CCC6D005B464F /* libRNFetchBlob.a */,
);
name = Products;
sourceTree = "<group>";
};
B8E79A8A1F3CCC6C005B464F /* Products */ = {
isa = PBXGroup;
children = (
@ -1084,6 +1117,7 @@
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
7A6EDBE020ED6E020086E097 /* Embed Frameworks */,
);
buildRules = (
);
@ -1182,6 +1216,10 @@
ProductGroup = 7A770EBE20BECDC7001AD51A /* Products */;
ProjectRef = 1845C223DA364898A8400573 /* FastImage.xcodeproj */;
},
{
ProductGroup = 7A6EDBD620ED6CBB0086E097 /* Products */;
ProjectRef = 8031BD2B0F824A0D8510616B /* imageCropPicker.xcodeproj */;
},
{
ProductGroup = B8971BAD202A091D0000D245 /* Products */;
ProjectRef = B8971BAC202A091D0000D245 /* KeyboardTrackingView.xcodeproj */;
@ -1259,17 +1297,13 @@
ProjectRef = C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */;
},
{
ProductGroup = B8E79A881F3CCC6C005B464F /* Products */;
ProjectRef = 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */;
ProductGroup = 7A8C912120F39A8000C8F5EE /* Products */;
ProjectRef = 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */;
},
{
ProductGroup = 7A770EBC20BECDC7001AD51A /* Products */;
ProjectRef = 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */;
},
{
ProductGroup = 60B8375C1F3F6F4B00677E56 /* Products */;
ProjectRef = 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */;
},
{
ProductGroup = 7A8DEB1C20ED0BDE00C5DCE4 /* Products */;
ProjectRef = 7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */;
@ -1509,13 +1543,6 @@
remoteRef = 607D61151F325B7E00F639C4 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
60B837841F3F6F4C00677E56 /* libRNImagePicker.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNImagePicker.a;
remoteRef = 60B837831F3F6F4C00677E56 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -1551,6 +1578,13 @@
remoteRef = 7A430E1D20238C02008F55BC /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7A6EDBDA20ED6CBB0086E097 /* libimageCropPicker.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libimageCropPicker.a;
remoteRef = 7A6EDBD920ED6CBB0086E097 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7A770EC220BECDC7001AD51A /* libFastImage.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -1586,6 +1620,13 @@
remoteRef = 7A7F5C9A1FCC982500024129 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7A8C915320F39A8000C8F5EE /* libRNFetchBlob.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNFetchBlob.a;
remoteRef = 7A8C915220F39A8000C8F5EE /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
7A8DEB5220ED0BDE00C5DCE4 /* libRNNotifications.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -1684,13 +1725,6 @@
remoteRef = B8971BB0202A091D0000D245 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B8E79A8E1F3CCC6D005B464F /* libRNFetchBlob.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNFetchBlob.a;
remoteRef = B8E79A8D1F3CCC6D005B464F /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
B8E79A911F3CCC6D005B464F /* libRNVectorIcons.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -1736,12 +1770,14 @@
70A8D9B456894EFFAF027CAB /* FontAwesome.ttf in Resources */,
435AB658888F41D69A230652 /* Foundation.ttf in Resources */,
4529B474417149059A180775 /* Ionicons.ttf in Resources */,
7A6EDBDC20ED6DCF0086E097 /* ImageCropPickerSDK in Resources */,
0DC38A29B0E54AF4AF96CB95 /* MaterialCommunityIcons.ttf in Resources */,
334A709FA3B448BC9A8563F6 /* MaterialIcons.ttf in Resources */,
2684481F67844BE398381564 /* Octicons.ttf in Resources */,
D6408D9E4A864FF6BA986857 /* SimpleLineIcons.ttf in Resources */,
CBD0E0A35B174C4DBFED3B31 /* Zocial.ttf in Resources */,
B8E79AF41F3CD167005B464F /* Info.plist in Resources */,
0AC2050A2CA1485DAC130425 /* Feather.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1871,10 +1907,8 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-image-picker/ios",
"$(SRCROOT)/../node_modules/react-native-navigation/ios/**",
"$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios",
"$(SRCROOT)/../node_modules/react-native-video/ios",
@ -1883,6 +1917,8 @@
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
"$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
);
INFOPLIST_FILE = RocketChatRNTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@ -1899,6 +1935,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@ -1919,10 +1956,8 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-image-picker/ios",
"$(SRCROOT)/../node_modules/react-native-navigation/ios/**",
"$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios",
"$(SRCROOT)/../node_modules/react-native-video/ios",
@ -1931,6 +1966,8 @@
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
"$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
);
INFOPLIST_FILE = RocketChatRNTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@ -1947,6 +1984,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@ -1976,10 +2014,8 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-image-picker/ios",
"$(SRCROOT)/../node_modules/react-native-navigation/ios/**",
"$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios",
"$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/**",
@ -1990,6 +2026,8 @@
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
"$(SRCROOT)/../node_modules/react-native-notifications/RNNotifications",
"$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
);
INFOPLIST_FILE = RocketChatRN/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@ -2024,10 +2062,8 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-image-picker/ios",
"$(SRCROOT)/../node_modules/react-native-navigation/ios/**",
"$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios",
"$(SRCROOT)/../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj/**",
@ -2038,6 +2074,8 @@
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
"$(SRCROOT)/../node_modules/react-native-notifications/RNNotifications",
"$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
);
INFOPLIST_FILE = RocketChatRN/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@ -2071,10 +2109,8 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-image-picker/ios",
"$(SRCROOT)/../node_modules/react-native-navigation/ios/**",
"$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios",
"$(SRCROOT)/../node_modules/react-native-video/ios",
@ -2083,6 +2119,8 @@
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
"$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
);
INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@ -2098,6 +2136,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@ -2128,10 +2167,8 @@
"$(inherited)",
"$(SRCROOT)/../node_modules/realm/src/**",
"$(SRCROOT)/../node_modules/react-native-zeroconf/ios/RNZeroconf",
"$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)/../node_modules/react-native-svg/ios/**",
"$(SRCROOT)/../node_modules/react-native-image-picker/ios",
"$(SRCROOT)/../node_modules/react-native-navigation/ios/**",
"$(SRCROOT)/../node_modules/react-native-autogrow-textinput/ios",
"$(SRCROOT)/../node_modules/react-native-video/ios",
@ -2140,6 +2177,8 @@
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
"$(SRCROOT)/../node_modules/react-native-image-crop-picker/ios/**",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
);
INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@ -2155,6 +2194,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@ -2194,6 +2234,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -2229,6 +2270,7 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -83,6 +83,7 @@
<string>SimpleLineIcons.ttf</string>
<string>Zocial.ttf</string>
<string>icomoon.ttf</string>
<string>Feather.ttf</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>

515
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@
"android": "react-native run-android",
"storybook": "storybook start -p 7007",
"snyk-protect": "snyk protect",
"prepare": "npm run snyk-protect; exit 0",
"fabric-ios": "./scripts/fabric-ios.sh",
"fabric-android": "./scripts/fabric-android.sh",
"postinstall": "cp ./temp/react.gradle ./node_modules/react-native"
@ -33,7 +32,7 @@
"babel-preset-expo": "^4.0.0",
"deep-equal": "^1.0.1",
"ejson": "^2.1.2",
"js-base64": "^2.4.5",
"js-base64": "^2.4.6",
"js-sha256": "^0.9.0",
"lodash": "^4.17.10",
"markdown-it-flowdock": "^0.3.7",
@ -48,19 +47,19 @@
"react-native-dialog": "^5.0.0",
"react-native-fabric": "^0.5.1",
"react-native-fast-image": "^4.0.14",
"react-native-fetch-blob": "^0.10.8",
"react-native-i18n": "^2.0.12",
"react-native-image-picker": "^0.26.10",
"react-native-i18n": "^2.0.14",
"react-native-image-crop-picker": "git+https://github.com/RocketChat/react-native-image-crop-picker.git",
"react-native-image-zoom-viewer": "^2.2.13",
"react-native-keyboard-aware-scroll-view": "^0.6.0",
"react-native-keyboard-input": "^5.2.3",
"react-native-keyboard-tracking-view": "^5.4.4",
"react-native-markdown-renderer": "git+https://github.com/RocketChat/react-native-markdown-renderer.git",
"react-native-meteor": "^1.3.0",
"react-native-modal": "^6.1.0",
"react-native-markdown-renderer": "^3.2.8",
"react-native-meteor": "^1.4.0",
"react-native-modal": "^6.4.0",
"react-native-navigation": "^1.1.474",
"react-native-notifications": "^1.1.19",
"react-native-optimized-flatlist": "^1.0.4",
"react-native-picker-select": "^3.1.3",
"react-native-picker-select": "^4.0.0",
"react-native-responsive-ui": "^1.1.1",
"react-native-safari-view": "^2.1.0",
"react-native-scrollable-tab-view": "^0.8.0",
@ -78,6 +77,7 @@
"redux-immutable-state-invariant": "^2.1.0",
"redux-saga": "^0.16.0",
"regenerator-runtime": "^0.12.0",
"rn-fetch-blob": "^0.10.11",
"snyk": "^1.88.1",
"strip-ansi": "^4.0.0"
},
@ -103,9 +103,9 @@
"react-dom": "^16.4.1",
"react-native-bundle-visualizer": "^1.3.0",
"react-test-renderer": "^16.4.1",
"reactotron-react-native": "^2.0.0-beta.10",
"reactotron-redux": "^1.13.0",
"reactotron-redux-saga": "^1.13.0"
"reactotron-react-native": "^2.0.0",
"reactotron-redux": "^2.0.0",
"reactotron-redux-saga": "^2.0.0"
},
"jest": {
"testPathIgnorePatterns": [