Update gradle and targetSdkVersion (#328)

* Changed the way we read RocketChat settings since setting.type won't be returned from server anymore

* Permissions

* Unnecessary action sheet render

* Update gradle

* Switched testServer to use blob

* RoomsListHeader search fixed

* Runs loadMessagesForRoom only if room has at least 20 rows

* - Logout if user's token expired
- Removed update avatar logic
- Profile dialog border on android

* - Animations disabled
- CircleCI set

* Tests updated

* "eventType argument is required" fix
This commit is contained in:
Diego Mello 2018-06-20 10:40:33 -03:00 committed by Guilherme Gazzo
parent 9e4ca34a80
commit 8af34a705a
20 changed files with 309 additions and 382 deletions

View File

@ -119,6 +119,7 @@ jobs:
cd android cd android
echo -e "" > ./gradle.properties echo -e "" > ./gradle.properties
echo -e "android.enableAapt2=false" >> ./gradle.properties
if [[ $KEYSTORE ]]; then if [[ $KEYSTORE ]]; then
echo $KEYSTORE_BASE64 | base64 --decode > ./app/$KEYSTORE echo $KEYSTORE_BASE64 | base64 --decode > ./app/$KEYSTORE

View File

@ -585,7 +585,7 @@ exports[`render unread +999 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/name?random=0", "uri": "/avatar/name",
} }
} }
style={ style={
@ -835,7 +835,7 @@ exports[`render unread 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/name?random=0", "uri": "/avatar/name",
} }
} }
style={ style={
@ -1085,7 +1085,7 @@ exports[`renders correctly 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/name?random=0", "uri": "/avatar/name",
} }
} }
style={ style={

View File

@ -62,7 +62,7 @@ exports[`Storyshots Avatar avatar 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/test?random=0", "uri": "/avatar/test",
} }
} }
style={ style={
@ -136,7 +136,7 @@ exports[`Storyshots Avatar avatar 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/aa?random=0", "uri": "/avatar/aa",
} }
} }
style={ style={
@ -210,7 +210,7 @@ exports[`Storyshots Avatar avatar 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/bb?random=0", "uri": "/avatar/bb",
} }
} }
style={ style={
@ -284,7 +284,7 @@ exports[`Storyshots Avatar avatar 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/test?random=0", "uri": "/avatar/test",
} }
} }
style={ style={
@ -393,7 +393,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/rocket.cat?random=0", "uri": "/avatar/rocket.cat",
} }
} }
style={ style={
@ -615,7 +615,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/rocket.cat?random=0", "uri": "/avatar/rocket.cat",
} }
} }
style={ style={
@ -841,7 +841,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/rocket.cat?random=0", "uri": "/avatar/rocket.cat",
} }
} }
style={ style={
@ -1086,7 +1086,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries?random=0", "uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries",
} }
} }
style={ style={
@ -1335,7 +1335,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries?random=0", "uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries",
} }
} }
style={ style={
@ -1580,7 +1580,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries?random=0", "uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries",
} }
} }
style={ style={
@ -1825,7 +1825,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries?random=0", "uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries",
} }
} }
style={ style={
@ -2070,7 +2070,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries?random=0", "uri": "/avatar/Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries",
} }
} }
style={ style={
@ -2315,7 +2315,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/W?random=0", "uri": "/avatar/W",
} }
} }
style={ style={
@ -2537,7 +2537,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/WW?random=0", "uri": "/avatar/WW",
} }
} }
style={ style={
@ -2759,7 +2759,7 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
source={ source={
Object { Object {
"priority": "high", "priority": "high",
"uri": "/avatar/?random=0", "uri": "/avatar/",
} }
} }
style={ style={

View File

@ -91,12 +91,12 @@ def enableProguardInReleaseBuilds = false
android { android {
compileSdkVersion 27 compileSdkVersion 27
buildToolsVersion "27.0.1" buildToolsVersion "27.0.3"
defaultConfig { defaultConfig {
applicationId "chat.rocket.reactnative" applicationId "chat.rocket.reactnative"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 23 targetSdkVersion 27
versionCode VERSIONCODE as Integer versionCode VERSIONCODE as Integer
versionName "1" versionName "1"
ndk { ndk {

View File

@ -3,9 +3,11 @@
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.2.3' // classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.android.tools.build:gradle:3.1.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
@ -16,6 +18,7 @@ allprojects {
repositories { repositories {
mavenLocal() mavenLocal()
jcenter() jcenter()
google()
maven { maven {
url 'https://maven.google.com' url 'https://maven.google.com'
} }

View File

@ -16,5 +16,6 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
android.enableAapt2=false
android.useDeprecatedNdk=true android.useDeprecatedNdk=true
VERSIONCODE=999999999 VERSIONCODE=999999999

View File

@ -2,4 +2,5 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip # distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

View File

@ -4,7 +4,6 @@ import { connect } from 'react-redux';
import { StyleSheet, Text, View, ViewPropTypes } from 'react-native'; import { StyleSheet, Text, View, ViewPropTypes } from 'react-native';
import FastImage from 'react-native-fast-image'; import FastImage from 'react-native-fast-image';
import avatarInitialsAndColor from '../utils/avatarInitialsAndColor'; import avatarInitialsAndColor from '../utils/avatarInitialsAndColor';
import database from '../lib/realm';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
iconContainer: { iconContainer: {
@ -42,37 +41,38 @@ export default class Avatar extends React.PureComponent {
borderRadius: 2, borderRadius: 2,
forceInitials: false forceInitials: false
}; };
state = { showInitials: true, user: {} }; state = { showInitials: true };
componentDidMount() { // componentDidMount() {
const { text, type } = this.props; // const { text, type } = this.props;
if (type === 'd') { // if (type === 'd') {
this.users = this.userQuery(text); // this.users = this.userQuery(text);
this.users.addListener(this.update); // this.users.addListener(this.update);
this.update(); // this.update();
} // }
} // }
componentWillReceiveProps(nextProps) { // componentWillReceiveProps(nextProps) {
if (nextProps.text !== this.props.text && nextProps.type === 'd') { // if (nextProps.text !== this.props.text && nextProps.type === 'd') {
if (this.users) { // if (this.users) {
this.users.removeAllListeners(); // this.users.removeAllListeners();
} // }
this.users = this.userQuery(nextProps.text); // this.users = this.userQuery(nextProps.text);
this.users.addListener(this.update); // this.users.addListener(this.update);
this.update(); // this.update();
} // }
} // }
componentWillUnmount() { // componentWillUnmount() {
if (this.users) { // if (this.users) {
this.users.removeAllListeners(); // this.users.removeAllListeners();
} // }
} // }
get avatarVersion() { // get avatarVersion() {
return (this.state.user && this.state.user.avatarVersion) || 0; // // return (this.state.user && this.state.user.avatarVersion) || 0;
} // return 0;
// }
/** FIXME: Workaround /** FIXME: Workaround
* While we don't have containers/components structure, this is breaking tests. * While we don't have containers/components structure, this is breaking tests.
@ -80,21 +80,21 @@ export default class Avatar extends React.PureComponent {
* and we would have a avatar container in charge of making queries. * and we would have a avatar container in charge of making queries.
* Also, it would make possible to write unit tests like these. * Also, it would make possible to write unit tests like these.
*/ */
userQuery = (username) => { // userQuery = (username) => {
if (database && database.databases && database.databases.activeDB) { // if (database && database.databases && database.databases.activeDB) {
return database.objects('users').filtered('username = $0', username); // return database.objects('users').filtered('username = $0', username);
} // }
return { // return {
addListener: () => {}, // addListener: () => {},
removeAllListeners: () => {} // removeAllListeners: () => {}
}; // };
} // }
update = () => { // update = () => {
if (this.users.length) { // if (this.users.length) {
this.setState({ user: this.users[0] }); // this.setState({ user: this.users[0] });
} // }
} // }
render() { render() {
const { const {
@ -123,7 +123,7 @@ export default class Avatar extends React.PureComponent {
let image; let image;
if (type === 'd' && !forceInitials) { if (type === 'd' && !forceInitials) {
const uri = avatar || `${ baseUrl }/avatar/${ text }?random=${ this.avatarVersion }`; const uri = avatar || `${ baseUrl }/avatar/${ text }`;
image = uri ? ( image = uri ? (
<FastImage <FastImage
style={[styles.avatar, avatarStyle]} style={[styles.avatar, avatarStyle]}

View File

@ -58,7 +58,7 @@ export default class Routes extends React.Component {
} }
componentWillUnmount() { componentWillUnmount() {
Linking.removeAllListeners(); Linking.removeEventListener('url', this.handleOpenURL);
} }
handleOpenURL({ url }) { handleOpenURL({ url }) {

View File

@ -206,11 +206,13 @@ export default class Socket extends EventEmitter {
}, 5000); }, 5000);
this.connection = new WebSocket(`${ this.url }/websocket`, null); this.connection = new WebSocket(`${ this.url }/websocket`, null);
this.connection.onopen = () => { this.connection.onopen = async() => {
this.emit('open'); this.emit('open');
resolve(); resolve();
this.ddp.emit('open'); this.ddp.emit('open');
return this._login && this.login(this._login); if (this._login) {
return this.login(this._login).catch(e => console.warn(e));
}
}; };
this.connection.onclose = debounce((e) => { this.connection.onclose = debounce((e) => {
this.emit('disconnected', e); this.emit('disconnected', e);
@ -260,6 +262,9 @@ export default class Socket extends EventEmitter {
msg: 'method', method, params msg: 'method', method, params
}).then(data => data.result || data.subs).catch((err) => { }).then(data => data.result || data.subs).catch((err) => {
log('DDP call Error', err); log('DDP call Error', err);
if (err && /you've been logged out by the server/i.test(err.reason)) {
return this.emit('forbidden');
}
return Promise.reject(err); return Promise.reject(err);
}); });
} }

View File

@ -1,4 +1,4 @@
import { AsyncStorage, Platform, InteractionManager } from 'react-native'; import { AsyncStorage, Platform } from 'react-native';
import { hashPassword } from 'react-native-meteor/lib/utils'; import { hashPassword } from 'react-native-meteor/lib/utils';
import foreach from 'lodash/forEach'; import foreach from 'lodash/forEach';
import RNFetchBlob from 'react-native-fetch-blob'; import RNFetchBlob from 'react-native-fetch-blob';
@ -10,7 +10,7 @@ import database from './realm';
import log from '../utils/log'; import log from '../utils/log';
// import * as actions from '../actions'; // import * as actions from '../actions';
import { setUser, setLoginServices, removeLoginServices, loginRequest, loginSuccess, loginFailure } from '../actions/login'; import { setUser, setLoginServices, removeLoginServices, loginRequest, loginSuccess, loginFailure, logout } from '../actions/login';
import { disconnect, connectSuccess, connectFailure } from '../actions/connect'; import { disconnect, connectSuccess, connectFailure } from '../actions/connect';
import { setActiveUser } from '../actions/activeUsers'; import { setActiveUser } from '../actions/activeUsers';
import { starredMessagesReceived, starredMessageUnstarred } from '../actions/starredMessages'; import { starredMessagesReceived, starredMessageUnstarred } from '../actions/starredMessages';
@ -80,11 +80,26 @@ const RocketChat = {
}, },
async testServer(url) { async testServer(url) {
if (/^(https?:\/\/)?(((\w|[0-9-_])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) { if (/^(https?:\/\/)?(((\w|[0-9-_])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) {
const response = await fetch(url, { method: 'HEAD' }); try {
if (response.status === 200 && response.headers.get('x-instance-id') != null && response.headers.get('x-instance-id').length) { let response = await RNFetchBlob.fetch('HEAD', url);
return url; response = response.respInfo;
if (response.status === 200 && response.headers['x-instance-id'] != null && response.headers['x-instance-id'].length) {
return url;
}
} catch (e) {
log('testServer', e);
} }
} }
// if (/^(https?:\/\/)?(((\w|[0-9-_])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) {
// try {
// const response = await fetch(url, { method: 'HEAD' });
// if (response.status === 200 && response.headers.get('x-instance-id') != null && response.headers.get('x-instance-id').length) {
// return url;
// }
// } catch (error) {
// console.log(error)
// }
// }
throw new Error({ error: 'invalid server' }); throw new Error({ error: 'invalid server' });
}, },
_setUser(ddpMessage) { _setUser(ddpMessage) {
@ -151,6 +166,8 @@ const RocketChat = {
this.ddp.on('loginError', protectedFunction(err => reduxStore.dispatch(loginFailure(err)))); this.ddp.on('loginError', protectedFunction(err => reduxStore.dispatch(loginFailure(err))));
this.ddp.on('forbidden', protectedFunction(() => reduxStore.dispatch(logout())));
this.ddp.on('users', protectedFunction(ddpMessage => RocketChat._setUser(ddpMessage))); this.ddp.on('users', protectedFunction(ddpMessage => RocketChat._setUser(ddpMessage)));
this.ddp.on('background', () => this.getRooms().catch(e => log('background getRooms', e))); this.ddp.on('background', () => this.getRooms().catch(e => log('background getRooms', e)));
@ -163,7 +180,7 @@ const RocketChat = {
})); }));
this.ddp.once('logged', protectedFunction(({ id }) => { this.ddp.once('logged', protectedFunction(({ id }) => {
this.subscribeRooms(id); this.subscribeRooms(id);
this.ddp.subscribe('stream-notify-logged', 'updateAvatar', false); // this.ddp.subscribe('stream-notify-logged', 'updateAvatar', false);
})); }));
this.ddp.on('disconnected', protectedFunction(() => { this.ddp.on('disconnected', protectedFunction(() => {
@ -185,20 +202,22 @@ const RocketChat = {
return reduxStore.dispatch(someoneTyping({ _rid, username: ddpMessage.fields.args[0], typing: ddpMessage.fields.args[1] })); return reduxStore.dispatch(someoneTyping({ _rid, username: ddpMessage.fields.args[0], typing: ddpMessage.fields.args[1] }));
})); }));
this.ddp.on('stream-notify-logged', (ddpMessage) => { // this.ddp.on('stream-notify-logged', (ddpMessage) => {
// this entire logic needs a better solution // // this entire logic needs a better solution
// we're using it only because our image cache lib doesn't support clear cache // // we're using it only because our image cache lib doesn't support clear cache
if (ddpMessage.fields && ddpMessage.fields.eventName === 'updateAvatar') { // if (ddpMessage.fields && ddpMessage.fields.eventName === 'updateAvatar') {
const { args } = ddpMessage.fields; // const { args } = ddpMessage.fields;
InteractionManager.runAfterInteractions(() => // InteractionManager.runAfterInteractions(() =>
args.forEach((arg) => { // args.forEach((arg) => {
const user = database.objects('users').filtered('username = $0', arg.username); // const user = database.objects('users').filtered('username = $0', arg.username);
if (user.length > 0) { // if (user.length > 0) {
user[0].avatarVersion += 1; // database.write(() => {
} // user[0].avatarVersion += 1;
})); // });
} // }
}); // }));
// }
// });
// this.ddp.on('stream-notify-user', protectedFunction((ddpMessage) => { // this.ddp.on('stream-notify-user', protectedFunction((ddpMessage) => {
// console.warn('rc.stream-notify-user') // console.warn('rc.stream-notify-user')

View File

@ -424,6 +424,7 @@ export default class ProfileView extends LoggedView {
onChangeText={value => this.setState({ typedPassword: value })} onChangeText={value => this.setState({ typedPassword: value })}
secureTextEntry secureTextEntry
testID='profile-view-typed-password' testID='profile-view-typed-password'
style={styles.dialogInput}
/> />
<Dialog.Button label={I18n.t('Cancel')} onPress={this.closePasswordAlert} /> <Dialog.Button label={I18n.t('Cancel')} onPress={this.closePasswordAlert} />
<Dialog.Button label={I18n.t('Save')} onPress={this.submit} /> <Dialog.Button label={I18n.t('Save')} onPress={this.submit} />

View File

@ -1,4 +1,4 @@
import { StyleSheet } from 'react-native'; import { StyleSheet, Platform } from 'react-native';
export default StyleSheet.create({ export default StyleSheet.create({
avatarContainer: { avatarContainer: {
@ -20,5 +20,14 @@ export default StyleSheet.create({
marginRight: 15, marginRight: 15,
marginBottom: 15, marginBottom: 15,
borderRadius: 2 borderRadius: 2
} },
dialogInput: Platform.select({
ios: {},
android: {
borderRadius: 4,
borderColor: 'rgba(0,0,0,.15)',
borderWidth: 2,
paddingHorizontal: 10
}
})
}); });

View File

@ -1,7 +1,7 @@
import { ListView as OldList } from 'realm/react-native'; import { ListView as OldList } from 'realm/react-native';
import React from 'react'; import React from 'react';
import cloneReferencedElement from 'react-clone-referenced-element'; import cloneReferencedElement from 'react-clone-referenced-element';
import { ScrollView, ListView as OldList2, LayoutAnimation } from 'react-native'; import { ScrollView, ListView as OldList2 } from 'react-native';
import moment from 'moment'; import moment from 'moment';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -57,7 +57,7 @@ export class List extends React.Component {
updateState = throttle(() => { updateState = throttle(() => {
// this.setState({ // this.setState({
this.dataSource = this.dataSource.cloneWithRows(this.data); this.dataSource = this.dataSource.cloneWithRows(this.data);
LayoutAnimation.easeInEaseOut(); // LayoutAnimation.easeInEaseOut();
this.forceUpdate(); this.forceUpdate();
// }); // });
}, 1000); }, 1000);
@ -71,7 +71,7 @@ export class List extends React.Component {
onEndReachedThreshold={100} onEndReachedThreshold={100}
renderFooter={this.props.renderFooter} renderFooter={this.props.renderFooter}
renderHeader={() => <Typing />} renderHeader={() => <Typing />}
onEndReached={() => this.props.onEndReached(this.data[this.data.length - 1])} onEndReached={() => this.props.onEndReached(this.data[this.data.length - 1], this.data.length)}
dataSource={this.dataSource} dataSource={this.dataSource}
renderRow={(item, previousItem) => this.props.renderRow(item, previousItem)} renderRow={(item, previousItem) => this.props.renderRow(item, previousItem)}
initialListSize={20} initialListSize={20}

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Text, View, Button } from 'react-native'; import { Text, View, Button, LayoutAnimation } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
// import { bindActionCreators } from 'redux'; // import { bindActionCreators } from 'redux';
import equal from 'deep-equal'; import equal from 'deep-equal';
@ -91,8 +91,8 @@ export default class RoomView extends LoggedView {
this.onEndReached.stop(); this.onEndReached.stop();
} }
onEndReached = debounce((lastRowData) => { onEndReached = debounce((lastRowData, length) => {
if (!lastRowData) { if (!lastRowData || length < 20) {
this.setState({ end: true }); this.setState({ end: true });
return; return;
} }
@ -141,6 +141,7 @@ export default class RoomView extends LoggedView {
} }
sendMessage = (message) => { sendMessage = (message) => {
LayoutAnimation.easeInEaseOut();
RocketChat.sendMessage(this.rid, message).then(() => { RocketChat.sendMessage(this.rid, message).then(() => {
this.props.setLastOpen(null); this.props.setLastOpen(null);
}); });

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Text, View, Platform, TouchableOpacity, TextInput } from 'react-native'; import { Text, View, Platform, TouchableOpacity, TextInput, LayoutAnimation } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons'; import Icon from 'react-native-vector-icons/Ionicons';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -68,10 +68,13 @@ export default class RoomsListHeaderView extends React.Component {
}; };
} }
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps, nextState) {
if (!equal(this.props, nextProps)) { if (!equal(this.props, nextProps)) {
return true; return true;
} }
if (!equal(this.state, nextState)) {
return true;
}
return false; return false;
} }
@ -89,14 +92,20 @@ export default class RoomsListHeaderView extends React.Component {
} }
onPressCancelSearchButton() { onPressCancelSearchButton() {
this.setState({ searching: false }); requestAnimationFrame(() => {
this.props.setSearch(''); LayoutAnimation.easeInEaseOut();
this.setState({ searching: false });
this.props.setSearch('');
});
} }
onPressSearchButton() { onPressSearchButton() {
this.setState({ searching: true });
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.inputSearch.focus(); LayoutAnimation.easeInEaseOut();
this.setState({ searching: true });
if (this.inputSearch) {
this.inputSearch.focus();
}
}); });
} }

View File

@ -2,7 +2,7 @@ import ActionButton from 'react-native-action-button';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/Ionicons'; import Icon from 'react-native-vector-icons/Ionicons';
import { Platform, View, TextInput, FlatList, LayoutAnimation } from 'react-native'; import { Platform, View, TextInput, FlatList } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import database from '../../lib/realm'; import database from '../../lib/realm';
@ -70,7 +70,7 @@ export default class RoomsListView extends LoggedView {
} }
updateState = debounce(() => { updateState = debounce(() => {
LayoutAnimation.easeInEaseOut(); // LayoutAnimation.easeInEaseOut();
this.setState({ rooms: this.data.slice() }); this.setState({ rooms: this.data.slice() });
}) })

293
package-lock.json generated
View File

@ -1243,9 +1243,9 @@
} }
}, },
"@types/react-native": { "@types/react-native": {
"version": "0.55.18", "version": "0.55.19",
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.55.18.tgz", "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.55.19.tgz",
"integrity": "sha512-4HaCc8Hk04pZ+v47K0j0sG3B5m7Ez/1uKHSHre9nNjevw9viAJcjhUZ0mqhhar+Hvavp3rHnbZwqxODluyWsTA==", "integrity": "sha512-US1gb6YA4lYW8wYW4afUj/PM7yhmCArGVdISJlbBgLyC3ZJWpEveuKh5ukooihp0E5/uHEOspdWmg2M7su0sQA==",
"requires": { "requires": {
"@types/react": "16.3.17" "@types/react": "16.3.17"
} }
@ -1350,12 +1350,6 @@
"resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz", "resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
"integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg==" "integrity": "sha512-z55ocwKBRLryBs394Sm3ushTtBeg6VAeuku7utSoSnsJKvKcnXFIyC6vh27n3rXyxSgkJBBCAvyOn7gSUcTYjg=="
}, },
"after": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
"integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
"dev": true
},
"agent-base": { "agent-base": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
@ -1859,12 +1853,6 @@
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
"integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
}, },
"arraybuffer.slice": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz",
"integrity": "sha1-8zshWfBTKj8xB6JywMz70a0peco=",
"dev": true
},
"arrify": { "arrify": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
@ -3385,12 +3373,6 @@
"resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
"integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
}, },
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
"dev": true
},
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@ -3436,12 +3418,6 @@
"integrity": "sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==", "integrity": "sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==",
"dev": true "dev": true
}, },
"base64-arraybuffer": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
"integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
"dev": true
},
"base64-js": { "base64-js": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz",
@ -3464,15 +3440,6 @@
"tweetnacl": "0.14.5" "tweetnacl": "0.14.5"
} }
}, },
"better-assert": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
"dev": true,
"requires": {
"callsite": "1.0.0"
}
},
"big-integer": { "big-integer": {
"version": "1.6.28", "version": "1.6.28",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.28.tgz", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.28.tgz",
@ -3497,12 +3464,6 @@
"safe-buffer": "5.1.1" "safe-buffer": "5.1.1"
} }
}, },
"blob": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
"dev": true
},
"block-stream": { "block-stream": {
"version": "0.0.9", "version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@ -3853,12 +3814,6 @@
"callsites": "0.2.0" "callsites": "0.2.0"
} }
}, },
"callsite": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
"integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
"dev": true
},
"callsites": { "callsites": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
@ -4683,23 +4638,11 @@
"integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==",
"dev": true "dev": true
}, },
"component-bind": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
"integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
"dev": true
},
"component-emitter": { "component-emitter": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
}, },
"component-inherit": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
"integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
"dev": true
},
"compressible": { "compressible": {
"version": "2.0.13", "version": "2.0.13",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz",
@ -5853,63 +5796,6 @@
"once": "1.4.0" "once": "1.4.0"
} }
}, },
"engine.io-client": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.8.5.tgz",
"integrity": "sha512-AYTgHyeVUPitsseqjoedjhYJapNVoSPShbZ+tEUX9/73jgZ/Z3sUlJf9oYgdEBBdVhupUpUqSxH0kBCXlQnmZg==",
"dev": true,
"requires": {
"component-emitter": "1.2.1",
"component-inherit": "0.0.3",
"debug": "2.3.3",
"engine.io-parser": "1.3.2",
"has-cors": "1.1.0",
"indexof": "0.0.1",
"parsejson": "0.0.3",
"parseqs": "0.0.5",
"parseuri": "0.0.5",
"ws": "1.1.5",
"xmlhttprequest-ssl": "1.5.3",
"yeast": "0.1.2"
},
"dependencies": {
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
"dev": true
},
"debug": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
"integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
"dev": true,
"requires": {
"ms": "0.7.2"
}
},
"ms": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
"integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
"dev": true
}
}
},
"engine.io-parser": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.3.2.tgz",
"integrity": "sha1-k3sHnwAH0Ik+xW1GyyILjLQ1Igo=",
"dev": true,
"requires": {
"after": "0.8.2",
"arraybuffer.slice": "0.0.6",
"base64-arraybuffer": "0.1.5",
"blob": "0.0.4",
"has-binary": "0.1.7",
"wtf-8": "1.0.0"
}
},
"enhanced-resolve": { "enhanced-resolve": {
"version": "3.4.1", "version": "3.4.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
@ -8274,21 +8160,6 @@
"ansi-regex": "2.1.1" "ansi-regex": "2.1.1"
} }
}, },
"has-binary": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz",
"integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=",
"dev": true,
"requires": {
"isarray": "0.0.1"
}
},
"has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
"dev": true
},
"has-flag": { "has-flag": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
@ -12436,12 +12307,6 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
}, },
"object-component": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
"integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
"dev": true
},
"object-copy": { "object-copy": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
@ -12856,33 +12721,6 @@
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
"dev": true "dev": true
}, },
"parsejson": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz",
"integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=",
"dev": true,
"requires": {
"better-assert": "1.0.2"
}
},
"parseqs": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
"integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
"dev": true,
"requires": {
"better-assert": "1.0.2"
}
},
"parseuri": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
"integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
"dev": true,
"requires": {
"better-assert": "1.0.2"
}
},
"parseurl": { "parseurl": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
@ -15117,7 +14955,7 @@
"version": "git+https://github.com/RocketChat/react-native-markdown-renderer.git#cecc6d0a2c940ac7a1e1e98c624d8b9b4d37ab68", "version": "git+https://github.com/RocketChat/react-native-markdown-renderer.git#cecc6d0a2c940ac7a1e1e98c624d8b9b4d37ab68",
"requires": { "requires": {
"@types/markdown-it": "0.0.4", "@types/markdown-it": "0.0.4",
"@types/react-native": "0.55.18", "@types/react-native": "0.55.19",
"markdown-it": "8.4.1", "markdown-it": "8.4.1",
"prop-types": "15.6.1", "prop-types": "15.6.1",
"react-native-fit-image": "1.5.4" "react-native-fit-image": "1.5.4"
@ -15500,19 +15338,23 @@
} }
}, },
"reactotron-react-native": { "reactotron-react-native": {
"version": "1.14.0", "version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/reactotron-react-native/-/reactotron-react-native-1.14.0.tgz", "resolved": "https://registry.npmjs.org/reactotron-react-native/-/reactotron-react-native-2.0.0-beta.6.tgz",
"integrity": "sha512-jyx5EOmqHGrdOzL0pksso4qDFZQRiD6zycM3KgIN3Nq49HmOofDjdOEoN/b4V+W1ftvEp/gjc/S5HXWmCh+dUQ==", "integrity": "sha512-9J5/F1xmhTeNQKpHJh5eNRO5Y8DKWGidHb8SsThInbn9+UGaHEw/HyOYctu2h7WlIPCau6SmI1G459lFYtKluA==",
"dev": true, "dev": true,
"requires": { "requires": {
"json-stringify-safe": "5.0.1",
"mitt": "1.1.3", "mitt": "1.1.3",
"prop-types": "15.6.1", "prop-types": "15.6.1",
"ramda": "0.24.1", "reactotron-core-client": "2.0.0-beta.6",
"ramdasauce": "2.1.0", "rn-host-detect": "1.1.3"
"reactotron-core-client": "1.13.0", },
"rn-host-detect": "1.1.3", "dependencies": {
"socket.io-client": "1.7.4" "reactotron-core-client": {
"version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/reactotron-core-client/-/reactotron-core-client-2.0.0-beta.6.tgz",
"integrity": "sha512-Wh9gNOieSlbwSPhe0DNoOur0o0qQKeYorGcmIykzbMV097lQ3+lt9lkort2yOzhosF5Sk9MfyvhhQ2qqEXZeiA==",
"dev": true
}
} }
}, },
"reactotron-redux": { "reactotron-redux": {
@ -17215,83 +17057,6 @@
} }
} }
}, },
"socket.io-client": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.7.4.tgz",
"integrity": "sha1-7J+CA1btme9tNX8HVtZIcXvdQoE=",
"dev": true,
"requires": {
"backo2": "1.0.2",
"component-bind": "1.0.0",
"component-emitter": "1.2.1",
"debug": "2.3.3",
"engine.io-client": "1.8.5",
"has-binary": "0.1.7",
"indexof": "0.0.1",
"object-component": "0.0.3",
"parseuri": "0.0.5",
"socket.io-parser": "2.3.1",
"to-array": "0.1.4"
},
"dependencies": {
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
"integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
"dev": true
},
"debug": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
"integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
"dev": true,
"requires": {
"ms": "0.7.2"
}
},
"ms": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
"integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
"dev": true
}
}
},
"socket.io-parser": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.3.1.tgz",
"integrity": "sha1-3VMgJRA85Clpcya+/WQAX8/ltKA=",
"dev": true,
"requires": {
"component-emitter": "1.1.2",
"debug": "2.2.0",
"isarray": "0.0.1",
"json3": "3.3.2"
},
"dependencies": {
"component-emitter": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz",
"integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=",
"dev": true
},
"debug": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
"dev": true,
"requires": {
"ms": "0.7.1"
}
},
"ms": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
"dev": true
}
}
},
"sockjs-client": { "sockjs-client": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz",
@ -18301,12 +18066,6 @@
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE="
}, },
"to-array": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
"integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
"dev": true
},
"to-arraybuffer": { "to-arraybuffer": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
@ -19379,12 +19138,6 @@
} }
} }
}, },
"wtf-8": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wtf-8/-/wtf-8-1.0.0.tgz",
"integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
"dev": true
},
"xcode": { "xcode": {
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/xcode/-/xcode-0.9.3.tgz", "resolved": "https://registry.npmjs.org/xcode/-/xcode-0.9.3.tgz",
@ -19464,12 +19217,6 @@
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz",
"integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk="
}, },
"xmlhttprequest-ssl": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz",
"integrity": "sha1-GFqIjATspGw+QHDZn3tJ3jUomS0=",
"dev": true
},
"xpipe": { "xpipe": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/xpipe/-/xpipe-1.0.5.tgz", "resolved": "https://registry.npmjs.org/xpipe/-/xpipe-1.0.5.tgz",
@ -19542,12 +19289,6 @@
} }
} }
}, },
"yeast": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
"dev": true
},
"zip": { "zip": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/zip/-/zip-1.2.0.tgz", "resolved": "https://registry.npmjs.org/zip/-/zip-1.2.0.tgz",

View File

@ -15,7 +15,8 @@
"snyk-protect": "snyk protect", "snyk-protect": "snyk protect",
"prepare": "exit 0", "prepare": "exit 0",
"fabric-ios": "./scripts/fabric-ios.sh", "fabric-ios": "./scripts/fabric-ios.sh",
"fabric-android": "./scripts/fabric-android.sh" "fabric-android": "./scripts/fabric-android.sh",
"postinstall": "cp ./temp/react.gradle ./node_modules/react-native"
}, },
"rnpm": { "rnpm": {
"assets": [ "assets": [
@ -104,7 +105,7 @@
"react-dom": "^16.4.0", "react-dom": "^16.4.0",
"react-native-bundle-visualizer": "^1.2.0", "react-native-bundle-visualizer": "^1.2.0",
"react-test-renderer": "^16.4.0", "react-test-renderer": "^16.4.0",
"reactotron-react-native": "^1.14.0", "reactotron-react-native": "^2.0.0-beta.6",
"reactotron-redux": "^1.13.0", "reactotron-redux": "^1.13.0",
"reactotron-redux-saga": "^1.13.0" "reactotron-redux-saga": "^1.13.0"
}, },

135
temp/react.gradle Normal file
View File

@ -0,0 +1,135 @@
// Workaround to "error: Duplicate file. Original is here. The version qualifier may be implied. With gradle assembleRelease"
// https://github.com/facebook/react-native/issues/19211#issuecomment-389125030
import org.apache.tools.ant.taskdefs.condition.Os
def config = project.hasProperty("react") ? project.react : [];
def cliPath = config.cliPath ?: "node_modules/react-native/local-cli/cli.js"
def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
def entryFile = config.entryFile ?: "index.android.js"
def bundleCommand = config.bundleCommand ?: "bundle"
// because elvis operator
def elvisFile(thing) {
return thing ? file(thing) : null;
}
def reactRoot = elvisFile(config.root) ?: file("../../")
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
def bundleConfig = config.bundleConfig ? "${reactRoot}/${config.bundleConfig}" : null ;
void runBefore(String dependentTaskName, Task task) {
Task dependentTask = tasks.findByPath(dependentTaskName);
if (dependentTask != null) {
dependentTask.dependsOn task
}
}
gradle.projectsEvaluated {
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type -> type.name }
def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
// When no product flavors defined, use empty
if (!productFlavors) productFlavors.add('')
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
// Create variant and target names
def flavorNameCapitalized = "${productFlavorName.capitalize()}"
def buildNameCapitalized = "${buildTypeName.capitalize()}"
def targetName = "${flavorNameCapitalized}${buildNameCapitalized}"
def targetPath = productFlavorName ?
"${productFlavorName}/${buildTypeName}" :
"${buildTypeName}"
// React js bundle directories
def jsBundleDirConfigName = "jsBundleDir${targetName}"
def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
file("$buildDir/intermediates/assets/${targetPath}")
def resourcesDirConfigName = "resourcesDir${targetName}"
def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
file("$buildDir/intermediates/res/merged/${targetPath}")
def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
// Bundle task name for variant
def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets"
// Additional node and packager commandline arguments
def nodeExecutableAndArgs = config.nodeExecutableAndArgs ?: ["node"]
def extraPackagerArgs = config.extraPackagerArgs ?: []
def currentBundleTask = tasks.create(
name: bundleJsAndAssetsTaskName,
type: Exec) {
group = "react"
description = "bundle JS and assets for ${targetName}."
// Create dirs if they are not there (e.g. the "clean" task just ran)
doFirst {
jsBundleDir.mkdirs()
resourcesDir.mkdirs()
}
// Set up inputs and outputs so gradle can cache the result
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
outputs.dir jsBundleDir
outputs.dir resourcesDir
// Set up the call to the react-native cli
workingDir reactRoot
// Set up dev mode
def devEnabled = !(config."devDisabledIn${targetName}"
|| targetName.toLowerCase().contains("release"))
def extraArgs = extraPackagerArgs;
if (bundleConfig) {
extraArgs = extraArgs.clone()
extraArgs.add("--config");
extraArgs.add(bundleConfig);
}
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine("cmd", "/c", *nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}",
"--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs)
} else {
commandLine(*nodeExecutableAndArgs, cliPath, bundleCommand, "--platform", "android", "--dev", "${devEnabled}",
"--reset-cache", "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir, *extraArgs)
}
enabled config."bundleIn${targetName}" ||
config."bundleIn${buildTypeName.capitalize()}" ?:
targetName.toLowerCase().contains("release")
doLast {
def moveFunc = { resSuffix ->
File originalDir = file("${resourcesDir}/drawable-${resSuffix}")
if (originalDir.exists()) {
File destDir = file("${resourcesDir}/drawable-${resSuffix}-v4")
ant.move(file: originalDir, tofile: destDir)
}
}
moveFunc.curry("ldpi").call()
moveFunc.curry("mdpi").call()
moveFunc.curry("hdpi").call()
moveFunc.curry("xhdpi").call()
moveFunc.curry("xxhdpi").call()
moveFunc.curry("xxxhdpi").call()
}
}
// Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
currentBundleTask.dependsOn("merge${targetName}Resources")
currentBundleTask.dependsOn("merge${targetName}Assets")
runBefore("process${flavorNameCapitalized}Armeabi-v7a${buildNameCapitalized}Resources", currentBundleTask)
runBefore("process${flavorNameCapitalized}X86${buildNameCapitalized}Resources", currentBundleTask)
runBefore("processUniversal${targetName}Resources", currentBundleTask)
runBefore("process${targetName}Resources", currentBundleTask)
runBefore("dataBindingProcessLayouts${targetName}", currentBundleTask)
}
}
}