This commit is contained in:
Guilherme Gazzo 2017-08-11 15:18:09 -03:00
parent 0e1cb6e5ed
commit 138546e4c9
No known key found for this signature in database
GPG Key ID: 1F85C9AD922D0829
11 changed files with 293 additions and 141 deletions

View File

@ -71,7 +71,6 @@ export default class Message extends React.PureComponent {
let initials = usernameParts.length > 1 ? usernameParts[0][0] + usernameParts[usernameParts.length - 1][0] : username.replace(/[^A-Za-z0-9]/g, '').substr(0, 2); let initials = usernameParts.length > 1 ? usernameParts[0][0] + usernameParts[usernameParts.length - 1][0] : username.replace(/[^A-Za-z0-9]/g, '').substr(0, 2);
initials = initials.toUpperCase(); initials = initials.toUpperCase();
return ( return (
<View style={[styles.message, extraStyle]}> <View style={[styles.message, extraStyle]}>
<View style={[styles.avatarContainer, { backgroundColor: color }]}> <View style={[styles.avatarContainer, { backgroundColor: color }]}>

View File

@ -17,6 +17,7 @@ const styles = StyleSheet.create({
}, },
textBoxInput: { textBoxInput: {
height: 40, height: 40,
alignSelf: 'stretch',
backgroundColor: '#fff', backgroundColor: '#fff',
flexGrow: 1 flexGrow: 1
}, },
@ -44,14 +45,15 @@ export default class MessageBox extends React.PureComponent {
}; };
} }
submit = () => { submit(message) {
if (this.state.text.trim() === '') { // console.log(this.state);
const text = message;
this.setState({ text: '' });
if (text.trim() === '') {
return; return;
} }
this.props.onSubmit(text);
this.props.onSubmit(this.state.text); }
this.setState({ text: '' });
};
addFile = () => { addFile = () => {
const options = { const options = {
@ -106,13 +108,15 @@ export default class MessageBox extends React.PureComponent {
<View style={styles.textBox}> <View style={styles.textBox}>
<Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} /> <Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} />
<TextInput <TextInput
ref={component => this.component = component}
style={styles.textBoxInput} style={styles.textBoxInput}
value={this.state.text} value={this.state.text}
onChangeText={text => this.setState({ text })} onChangeText={text => this.setState({ text })}
returnKeyType='send' returnKeyType='send'
onSubmitEditing={this.submit} onSubmitEditing={event => this.submit(event.nativeEvent.text)}
blurOnSubmit={false} blurOnSubmit={false}
placeholder='New message' placeholder='New message'
underlineColorAndroid='transparent'
/> />
</View> </View>
); );

View File

@ -35,10 +35,10 @@ const subscriptionSchema = {
open: { type: 'bool', optional: true }, open: { type: 'bool', optional: true },
alert: { type: 'bool', optional: true }, alert: { type: 'bool', optional: true },
// roles: [ 'owner' ], // roles: [ 'owner' ],
unread: { type: 'int', optional: true } unread: { type: 'int', optional: true },
// userMentions: 0, // userMentions: 0,
// groupMentions: 0, // groupMentions: 0,
// _updatedAt: Fri Jul 28 2017 18:31:35 GMT-0300 (-03), _updatedAt: { type: 'date', optional: true }
} }
}; };
@ -80,11 +80,10 @@ const realm = new Realm({
export default realm; export default realm;
// Clear settings // Clear settings
realm.write(() => { // realm.write(() => {
// const allSettins = realm.objects('settings'); // // const allSettins = realm.objects('settings');
// realm.delete(allSettins); // // realm.delete(allSettins);
//
// realm.create('servers', { id: 'https://demo.rocket.chat', current: false }, true); // // realm.create('servers', { id: 'https://demo.rocket.chat', current: false }, true);
// realm.create('servers', { id: 'http://localhost:3000', current: false }, true); // // realm.create('servers', { id: 'http://localhost:3000', current: false }, true);
// realm.create('servers', { id: 'http://10.0.2.2:3000', current: false }, true); // });
});

View File

@ -1,9 +1,37 @@
import Meteor from 'react-native-meteor'; import Meteor from 'react-native-meteor';
import Random from 'react-native-meteor/lib/Random'; import Random from 'react-native-meteor/lib/Random';
import realm from './realm'; import realm from './realm';
import debounce from '../utils/debounce';
export { Accounts } from 'react-native-meteor'; export { Accounts } from 'react-native-meteor';
const call = (method, ...params) => new Promise((resolve, reject) => {
Meteor.call(method, ...params, (err, data) => {
if (err) {
reject(err);
}
resolve(data);
});
});
const write = (() => {
const cache = [];
const run = debounce(() => {
if (!cache.length) {
return;
}
realm.write(() => {
cache.forEach(([name, obj]) => {
realm.create(name, obj, true);
});
});
// cache = [];
}, 1000);
return (name, obj) => {
cache.push([name, obj]);
run();
};
})();
const RocketChat = { const RocketChat = {
createChannel({ name, users, type }) { createChannel({ name, users, type }) {
@ -45,6 +73,7 @@ const RocketChat = {
if (typeof item.value === 'string') { if (typeof item.value === 'string') {
setting.value = item.value; setting.value = item.value;
} }
// write('settings', setting);
realm.create('settings', setting, true); realm.create('settings', setting, true);
}); });
}); });
@ -61,17 +90,36 @@ const RocketChat = {
const message = ddbMessage.fields.args[0]; const message = ddbMessage.fields.args[0];
message.temp = false; message.temp = false;
message._server = { id: RocketChat.currentServer }; message._server = { id: RocketChat.currentServer };
// write('messages', message);
realm.create('messages', message, true); realm.create('messages', message, true);
}); });
} }
this.subCache = this.subCache || {};
this.roomCache = this.roomCache || {};
this.cache = {};
if (ddbMessage.collection === 'stream-notify-user') { if (ddbMessage.collection === 'stream-notify-user') {
console.log(ddbMessage);
realm.write(() => {
const data = ddbMessage.fields.args[1]; const data = ddbMessage.fields.args[1];
data._server = { id: RocketChat.currentServer }; let key;
realm.create('subscriptions', data, true); if (ddbMessage.fields.eventName && ddbMessage.fields.eventName.indexOf('rooms-changed') > -1) {
}); this.roomCache[data._id] = data;
key = data._id;
} else {
this.subCache[data.rid] = data;
key = data.rid;
delete this.subCache[key]._updatedAt;
}
this.cache[key] = this.cache[key] ||
setTimeout(() => {
this.subCache[key] = this.subCache[key] || realm.objects('subscriptions').filtered('rid = $0', key).slice(0, 1)[0];
if (this.roomCache[key]) {
this.subCache[key]._updatedAt = this.roomCache[key]._updatedAt;
}
write('subscriptions', this.subCache[key]);
delete this.subCache[key];
delete this.roomCache[key];
delete this.cache[key];
}, 550);
} }
}); });
}); });
@ -86,7 +134,7 @@ const RocketChat = {
if (err) { if (err) {
console.error(err); console.error(err);
} }
if (data.length) {
realm.write(() => { realm.write(() => {
data.forEach((subscription) => { data.forEach((subscription) => {
// const subscription = { // const subscription = {
@ -96,9 +144,11 @@ const RocketChat = {
// subscription.value = item.value; // subscription.value = item.value;
// } // }
subscription._server = { id: RocketChat.currentServer }; subscription._server = { id: RocketChat.currentServer };
write('subscriptions', subscription);
realm.create('subscriptions', subscription, true); realm.create('subscriptions', subscription, true);
}); });
}); });
}
return cb && cb(); return cb && cb();
}); });
@ -113,14 +163,16 @@ const RocketChat = {
} }
return; return;
} }
if (data.messages.length) {
realm.write(() => { realm.write(() => {
data.messages.forEach((message) => { data.messages.forEach((message) => {
message.temp = false; message.temp = false;
message._server = { id: RocketChat.currentServer }; message._server = { id: RocketChat.currentServer };
// write('messages', message);
realm.create('messages', message, true); realm.create('messages', message, true);
}); });
}); });
}
if (cb) { if (cb) {
if (data.messages.length < 20) { if (data.messages.length < 20) {
@ -139,6 +191,19 @@ const RocketChat = {
const user = Meteor.user(); const user = Meteor.user();
realm.write(() => { realm.write(() => {
// write('messages', {
// _id,
// rid,
// msg,
// ts: new Date(),
// _updatedAt: new Date(),
// temp: true,
// _server: { id: RocketChat.currentServer },
// u: {
// _id: user._id,
// username: user.username
// }
// });
realm.create('messages', { realm.create('messages', {
_id, _id,
rid, rid,
@ -185,7 +250,9 @@ const RocketChat = {
}); });
}); });
}, },
readMessages(rid) {
return call('readMessages', rid);
},
joinRoom(rid) { joinRoom(rid) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Meteor.call('joinRoom', rid, (error, result) => { Meteor.call('joinRoom', rid, (error, result) => {
@ -252,13 +319,14 @@ const RocketChat = {
}; };
export default RocketChat; export default RocketChat;
Meteor.Accounts.onLogin(() => { Meteor.Accounts.onLogin(() => {
Meteor.call('subscriptions/get', (err, data) => { Promise.all([call('subscriptions/get'), call('rooms/get')]).then(([subscriptions, rooms]) => {
if (err) { subscriptions = subscriptions.sort((s1, s2) => (s1.rid > s2.rid ? 1 : -1));
console.error(err); rooms = rooms.sort((s1, s2) => (s1._id > s2._id ? 1 : -1));
} const data = subscriptions.map((subscription, index) => {
subscription._updatedAt = rooms[index]._updatedAt;
return subscription;
});
realm.write(() => { realm.write(() => {
data.forEach((subscription) => { data.forEach((subscription) => {
// const subscription = { // const subscription = {
@ -268,9 +336,13 @@ Meteor.Accounts.onLogin(() => {
// subscription.value = item.value; // subscription.value = item.value;
// } // }
subscription._server = { id: RocketChat.currentServer }; subscription._server = { id: RocketChat.currentServer };
// write('subscriptions', subscription);
realm.create('subscriptions', subscription, true); realm.create('subscriptions', subscription, true);
}); });
}); });
}).then(() => {
Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/subscriptions-changed`, false); Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/subscriptions-changed`, false);
Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/rooms-changed`, false);
console.log('subscriptions done.');
}); });
}); });

View File

@ -61,6 +61,6 @@ export default new StackNavigator({
initialRouteName: 'Main', initialRouteName: 'Main',
cardStyle: { cardStyle: {
backgroundColor: '#fff' backgroundColor: '#fff'
}, }
mode: 'modal' // mode: 'modal'
}); });

14
app/utils/debounce.js Normal file
View File

@ -0,0 +1,14 @@
export default function debounce(func, wait, immediate) {
let timeout;
return function _debounce(...args) {
const context = this;
const later = function __debounce() {
timeout = null;
if (!immediate) { func.apply(context, args); }
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) { func.apply(context, args); }
};
}

21
app/utils/throttle.js Normal file
View File

@ -0,0 +1,21 @@
export default function throttle(fn, threshhold = 250, scope) {
let last,
deferTimer;
return function() {
const context = scope || this;
let now = +new Date(),
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(() => {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}

View File

@ -1,13 +1,14 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Text, View, FlatList, StyleSheet, Button } from 'react-native'; import { Text, View, StyleSheet, Button } from 'react-native';
import { ListView } from 'realm/react-native';
import realm from '../lib/realm'; import realm from '../lib/realm';
import RocketChat from '../lib/rocketchat'; import RocketChat from '../lib/rocketchat';
import debounce from '../utils/throttle';
import Message from '../components/Message'; import Message from '../components/Message';
import MessageBox from '../components/MessageBox'; import MessageBox from '../components/MessageBox';
import KeyboardView from '../components/KeyboardView'; // import KeyboardView from '../components/KeyboardView';
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1 flex: 1
@ -45,17 +46,18 @@ export default class RoomView extends React.Component {
title: navigation.state.params.name || realm.objectForPrimaryKey('subscriptions', navigation.state.params.sid).name title: navigation.state.params.name || realm.objectForPrimaryKey('subscriptions', navigation.state.params.sid).name
}); });
constructor(props) { constructor(props) {
super(props); super(props);
this.rid = props.navigation.state.params.rid || realm.objectForPrimaryKey('subscriptions', props.navigation.state.params.sid).rid; this.rid = props.navigation.state.params.rid || realm.objectForPrimaryKey('subscriptions', props.navigation.state.params.sid).rid;
// this.rid = 'GENERAL'; // this.rid = 'GENERAL';
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', RocketChat.currentServer, this.rid).sorted('ts', true);
this.state = { this.state = {
dataSource: [], dataSource: ds.cloneWithRows(this.data.slice(0, 10)),
loaded: true, loaded: true,
joined: typeof props.navigation.state.params.rid === 'undefined' joined: typeof props.navigation.state.params.rid === 'undefined'
}; };
// console.log(this.messages);
this.url = realm.objectForPrimaryKey('settings', 'Site_Url').value; this.url = realm.objectForPrimaryKey('settings', 'Site_Url').value;
} }
@ -68,16 +70,13 @@ export default class RoomView extends React.Component {
this.setState({ this.setState({
loaded: true loaded: true
}); });
});
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', RocketChat.currentServer, this.rid).sorted('ts', true);
this.setState({
dataSource: this.data
});
this.data.addListener(this.updateState); this.data.addListener(this.updateState);
});
this.updateState();
}
componentDidMount() {
return RocketChat.readMessages(this.rid);
} }
componentWillUnmount() { componentWillUnmount() {
this.data.removeListener(this.updateState); this.data.removeListener(this.updateState);
} }
@ -85,12 +84,12 @@ export default class RoomView extends React.Component {
onEndReached = () => { onEndReached = () => {
if (this.state.dataSource.length && this.state.loaded && this.state.loadingMore !== true && this.state.end !== true) { if (this.state.dataSource.length && this.state.loaded && this.state.loadingMore !== true && this.state.end !== true) {
this.setState({ this.setState({
...this.state, // ...this.state,
loadingMore: true loadingMore: true
}); });
RocketChat.loadMessagesForRoom(this.rid, this.state.dataSource[this.state.dataSource.length - 1].ts, ({ end }) => { RocketChat.loadMessagesForRoom(this.rid, this.state.dataSource[this.state.dataSource.length - 1].ts, ({ end }) => {
this.setState({ this.setState({
...this.state, // ...this.state,
loadingMore: false, loadingMore: false,
end end
}); });
@ -98,11 +97,15 @@ export default class RoomView extends React.Component {
} }
} }
updateState = (data) => { updateState = debounce(() => {
this.setState({ this.setState({
dataSource: data dataSource: ds.cloneWithRows(this.data)
}); });
}; // RocketChat.readMessages(this.rid);
// this.setState({
// messages: this.messages
// });
}, 100);
sendMessage = message => RocketChat.sendMessage(this.rid, message); sendMessage = message => RocketChat.sendMessage(this.rid, message);
@ -148,6 +151,7 @@ export default class RoomView extends React.Component {
} }
return ( return (
<MessageBox <MessageBox
ref={box => this.box = box}
onSubmit={this.sendMessage} onSubmit={this.sendMessage}
rid={this.rid} rid={this.rid}
/> />
@ -165,22 +169,24 @@ export default class RoomView extends React.Component {
} }
render() { render() {
// data={this.state.dataSource}
// extraData={this.state}
// renderItem={this.renderItem}
// keyExtractor={item => item._id}
//
return ( return (
<KeyboardView style={styles.container} keyboardVerticalOffset={64}> <View style={styles.container}>
{this.renderBanner()} {this.renderBanner()}
<FlatList <ListView
ref={ref => this.listView = ref}
style={styles.list} style={styles.list}
data={this.state.dataSource}
extraData={this.state}
renderItem={this.renderItem}
keyExtractor={item => item._id}
onEndReached={this.onEndReached}
onEndReachedThreshold={0.1} onEndReachedThreshold={0.1}
ListFooterComponent={this.renderHeader()} ListFooterComponent={this.renderHeader()}
onEndReached={this.onEndReached}
dataSource={this.state.dataSource}
renderRow={item => this.renderItem({ item })}
/> />
{this.renderFooter()} {this.renderFooter()}
</KeyboardView> </View>
); );
} }
} }

View File

@ -1,12 +1,14 @@
import ActionButton from 'react-native-action-button'; import ActionButton from 'react-native-action-button';
import { ListView } from 'realm/react-native';
import Icon from 'react-native-vector-icons/Ionicons'; import Icon from 'react-native-vector-icons/Ionicons';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Text, View, FlatList, StyleSheet, TouchableOpacity, Platform, TextInput } from 'react-native'; import { Button, Text, View, StyleSheet, TouchableOpacity, Platform, TextInput } from 'react-native';
import Meteor from 'react-native-meteor'; import Meteor from 'react-native-meteor';
import realm from '../lib/realm'; import realm from '../lib/realm';
import RocketChat from '../lib/rocketchat'; import RocketChat from '../lib/rocketchat';
import RoomItem from '../components/RoomItem'; import RoomItem from '../components/RoomItem';
import debounce from '../utils/debounce';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
@ -72,6 +74,28 @@ Meteor.Accounts.onLogin(() => {
console.log('onLogin'); console.log('onLogin');
}); });
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
class RoomsListItem extends React.PureComponent {
static propTypes = {
item: PropTypes.object.isRequired,
onPress: PropTypes.func.isRequired
}
_onPress = (...args) => {
this.props.onPress(...args);
};
render() {
const { item } = this.props;
return (
<TouchableOpacity key={item._id} onPress={() => this.props.onPress(item._id, item)}>
<RoomItem
id={item._id}
item={item}
/>
</TouchableOpacity>
);
}
}
export default class RoomsListView extends React.Component { export default class RoomsListView extends React.Component {
static propTypes = { static propTypes = {
navigation: PropTypes.object.isRequired navigation: PropTypes.object.isRequired
@ -95,9 +119,9 @@ export default class RoomsListView extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.data = realm.objects('subscriptions').filtered('_server.id = $0', RocketChat.currentServer).sorted('_updatedAt', true);
this.state = { this.state = {
dataSource: [], dataSource: ds.cloneWithRows(this.data.sorted('_updatedAt', true).slice(0, 10)),
searching: false, searching: false,
searchDataSource: [], searchDataSource: [],
searchText: '' searchText: ''
@ -168,40 +192,23 @@ export default class RoomsListView extends React.Component {
} }
} }
} }
setInitialData = () => { setInitialData = () => {
if (this.data) { if (this.data) {
this.data.removeListener(this.updateState); this.data.removeListener(this.updateState);
} }
this.data = realm.objects('subscriptions').filtered('_server.id = $0', RocketChat.currentServer).sorted('name');
this.data.addListener(this.updateState); this.data.addListener(this.updateState);
this.updateState();
}
getSubscriptions = () => this.data.sorted('_updatedAt', true)
updateState = debounce(() => {
this.setState({ this.setState({
dataSource: this.sort(this.data) dataSource: ds.cloneWithRows(this.data)
}); });
} }, 500);
sort = (data) => {
return data.slice().sort((a, b) => {
if (a.unread < b.unread) {
return 1;
}
if (a.unread > b.unread) {
return -1;
}
return 0;
});
}
updateState = (data) => {
this.setState({
dataSource: this.sort(data)
});
}
_onPressItem = (id, item = {}) => { _onPressItem = (id, item = {}) => {
const { navigate } = this.props.navigation; const { navigate } = this.props.navigation;
@ -222,8 +229,8 @@ export default class RoomsListView extends React.Component {
.then(subs => navigate('Room', { sid: subs[0]._id })) .then(subs => navigate('Room', { sid: subs[0]._id }))
.then(() => clearSearch()); .then(() => clearSearch());
} else { } else {
navigate('Room', { rid: item._id, name: item.name });
clearSearch(); clearSearch();
navigate('Room', { rid: item._id, name: item.name });
} }
return; return;
} }
@ -256,12 +263,7 @@ export default class RoomsListView extends React.Component {
} }
renderItem = ({ item }) => ( renderItem = ({ item }) => (
<TouchableOpacity onPress={() => this._onPressItem(item._id, item)}> <RoomsListItem item={item} onPress={() => this._onPressItem(item._id, item)} />
<RoomItem
id={item._id}
item={item}
/>
</TouchableOpacity>
); );
renderSeparator = () => ( renderSeparator = () => (
@ -282,25 +284,25 @@ export default class RoomsListView extends React.Component {
</View> </View>
); );
renderList = () => { // if (!this.state.searching && !this.state.dataSource.length) {
if (!this.state.searching && !this.state.dataSource.length) { // return (
return ( // <View style={styles.emptyView}>
<View style={styles.emptyView}> // <Text style={styles.emptyText}>No rooms</Text>
<Text style={styles.emptyText}>No rooms</Text> // </View>
</View> // );
); // }
} renderList = () => (
// data={this.state.searching ? this.state.searchDataSource : this.state.dataSource}
return ( // keyExtractor={item => item._id}
<FlatList // ItemSeparatorComponent={this.renderSeparator}
// renderItem={this.renderItem}
<ListView
dataSource={this.state.dataSource}
style={styles.list} style={styles.list}
data={this.state.searching ? this.state.searchDataSource : this.state.dataSource} renderRow={item => this.renderItem({ item })}
renderItem={this.renderItem}
keyExtractor={item => item._id}
ItemSeparatorComponent={this.renderSeparator}
/> />
); )
}
renderCreateButtons() { renderCreateButtons() {
return ( return (
<ActionButton buttonColor='rgba(231,76,60,1)'> <ActionButton buttonColor='rgba(231,76,60,1)'>

30
package-lock.json generated
View File

@ -3683,6 +3683,26 @@
"resolved": "https://registry.npmjs.org/react-native-action-button/-/react-native-action-button-2.7.2.tgz", "resolved": "https://registry.npmjs.org/react-native-action-button/-/react-native-action-button-2.7.2.tgz",
"integrity": "sha1-BvEYjo/h0Y0D/JBg1LYEybgbtso=" "integrity": "sha1-BvEYjo/h0Y0D/JBg1LYEybgbtso="
}, },
"react-native-auto-grow-textinput": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/react-native-auto-grow-textinput/-/react-native-auto-grow-textinput-1.2.0.tgz",
"integrity": "sha512-O+mT2GOrDRzJdg2GbdfuGlO/nn/J8c9pdBCPahLYA8yiAjayAG67XOujGrfuv/wNCF7W94NsYdyfaf2hlOIhYQ=="
},
"react-native-autogrow-input": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/react-native-autogrow-input/-/react-native-autogrow-input-0.2.1.tgz",
"integrity": "sha512-vWcfqGqzDw4XqRJr4HnHC+dcGAfJDYZiF2B0tBZjtjA6MNSv2TNz5knYZjvLggRgmEflj02r88scvfFputsRig=="
},
"react-native-autogrow-textinput": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/react-native-autogrow-textinput/-/react-native-autogrow-textinput-4.1.0.tgz",
"integrity": "sha1-p+WxfrPBarCOMbv7iNkkiO2H8nY="
},
"react-native-console-time-polyfill": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/react-native-console-time-polyfill/-/react-native-console-time-polyfill-0.0.6.tgz",
"integrity": "sha1-eCPYb+g0OcdEgNGxJKkrGnhXGIk="
},
"react-native-dismiss-keyboard": { "react-native-dismiss-keyboard": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz", "resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz",
@ -3718,6 +3738,11 @@
"resolved": "https://registry.npmjs.org/react-native-form-generator/-/react-native-form-generator-0.9.9.tgz", "resolved": "https://registry.npmjs.org/react-native-form-generator/-/react-native-form-generator-0.9.9.tgz",
"integrity": "sha1-aKribR6Nw+MAc8zXuymPvf3OG8o=" "integrity": "sha1-aKribR6Nw+MAc8zXuymPvf3OG8o="
}, },
"react-native-image-picker": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.3.tgz",
"integrity": "sha1-CtLu3klQGnBG2ARqc4E2llOcPc0="
},
"react-native-img-cache": { "react-native-img-cache": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/react-native-img-cache/-/react-native-img-cache-1.4.0.tgz", "resolved": "https://registry.npmjs.org/react-native-img-cache/-/react-native-img-cache-1.4.0.tgz",
@ -3735,6 +3760,11 @@
"resolved": "https://registry.npmjs.org/react-native-meteor/-/react-native-meteor-1.1.0.tgz", "resolved": "https://registry.npmjs.org/react-native-meteor/-/react-native-meteor-1.1.0.tgz",
"integrity": "sha1-Vake/i1GbTqMzrW1QZeZru3NZ1Y=" "integrity": "sha1-Vake/i1GbTqMzrW1QZeZru3NZ1Y="
}, },
"react-native-optimized-flatlist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/react-native-optimized-flatlist/-/react-native-optimized-flatlist-1.0.1.tgz",
"integrity": "sha1-2+6C8gi0i+8jxssm8dXzrFjmdbI="
},
"react-native-svg": { "react-native-svg": {
"version": "5.4.1", "version": "5.4.1",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-5.4.1.tgz", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-5.4.1.tgz",

View File

@ -16,12 +16,17 @@
"react-emojione": "^3.1.10", "react-emojione": "^3.1.10",
"react-native": "0.46.1", "react-native": "0.46.1",
"react-native-action-button": "^2.7.2", "react-native-action-button": "^2.7.2",
"react-native-auto-grow-textinput": "^1.2.0",
"react-native-autogrow-input": "^0.2.1",
"react-native-autogrow-textinput": "^4.1.0",
"react-native-console-time-polyfill": "0.0.6",
"react-native-easy-markdown": "git+https://github.com/lappalj4/react-native-easy-markdown.git", "react-native-easy-markdown": "git+https://github.com/lappalj4/react-native-easy-markdown.git",
"react-native-fetch-blob": "^0.10.8", "react-native-fetch-blob": "^0.10.8",
"react-native-form-generator": "^0.9.9", "react-native-form-generator": "^0.9.9",
"react-native-image-picker": "^0.26.3", "react-native-image-picker": "^0.26.3",
"react-native-img-cache": "^1.4.0", "react-native-img-cache": "^1.4.0",
"react-native-meteor": "^1.1.0", "react-native-meteor": "^1.1.0",
"react-native-optimized-flatlist": "^1.0.1",
"react-native-svg": "^5.4.1", "react-native-svg": "^5.4.1",
"react-native-svg-image": "^1.1.4", "react-native-svg-image": "^1.1.4",
"react-native-vector-icons": "^4.3.0", "react-native-vector-icons": "^4.3.0",