Use inline requires (#459)

* Update dependencies

* Lint and test

* Added react-native fork

* rn 57

* Lint and tests updated

* Update xcode on circleci

* Use legacy build system

* Update tests

* Inline requires

* Fix eslint and remove temp gradle

* Unnecessary renders

* Update isNotch and Readme

* Tests updated
This commit is contained in:
Diego Mello 2018-09-26 10:56:36 -03:00 committed by GitHub
parent 81c53acd60
commit e18491f589
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 267 additions and 283 deletions

View File

@ -2,3 +2,5 @@ __tests__
node_modules
coverage
e2e
android
ios

View File

@ -169,7 +169,7 @@ Readme will guide you on how to config.
| Channel Info screen -> Members | ✅ |
| Channel Info screen -> Pinned | ✅ |
| Channel Info screen -> Starred | ✅ |
| Channel Info screen -> Uploads | |
| Channel Info screen -> Uploads | |
| Star message | ✅ |
| Unstar message | ✅ |
| Channel Info screen -> Topic | ✅ |
@ -200,7 +200,7 @@ Readme will guide you on how to config.
| Deep links: Authentication | ✅ |
| Deep links: Rooms | ✅ |
| Draft per room | ❌ |
| Localized in Portuguese (pt-BR) | |
| Localized in Portuguese (pt-BR) | |
| Localized in Russian | ✅ |
| Localized in English | ✅ |
| Full name setting | ✅ |

View File

@ -650,6 +650,9 @@ exports[`render unread +999 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -660,9 +663,6 @@ exports[`render unread +999 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -912,6 +912,9 @@ exports[`render unread 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -922,9 +925,6 @@ exports[`render unread 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -1174,6 +1174,9 @@ exports[`renders correctly 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -1184,9 +1187,6 @@ exports[`renders correctly 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>

View File

@ -39,6 +39,9 @@ exports[`Storyshots Avatar avatar 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -49,9 +52,6 @@ exports[`Storyshots Avatar avatar 1`] = `
"width": 25,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -111,6 +111,9 @@ exports[`Storyshots Avatar avatar 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -121,9 +124,6 @@ exports[`Storyshots Avatar avatar 1`] = `
"width": 40,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -183,6 +183,9 @@ exports[`Storyshots Avatar avatar 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -193,9 +196,6 @@ exports[`Storyshots Avatar avatar 1`] = `
"width": 30,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -255,6 +255,9 @@ exports[`Storyshots Avatar avatar 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -265,9 +268,6 @@ exports[`Storyshots Avatar avatar 1`] = `
"width": 25,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -360,6 +360,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -370,9 +373,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -591,6 +591,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -601,9 +604,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -826,6 +826,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -836,9 +839,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -1083,6 +1083,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -1093,9 +1096,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -1344,6 +1344,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -1354,9 +1357,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -1601,6 +1601,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -1611,9 +1614,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -1858,6 +1858,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -1868,9 +1871,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -2115,6 +2115,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -2125,9 +2128,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -2372,6 +2372,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -2382,9 +2385,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -2603,6 +2603,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -2613,9 +2616,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>
@ -2834,6 +2834,9 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
<View
style={
Array [
Object {
"overflow": "hidden",
},
Array [
Object {
"position": "absolute",
@ -2844,9 +2847,6 @@ exports[`Storyshots Channel Cell Direct Messages 1`] = `
"width": 48,
},
],
Object {
"overflow": "hidden",
},
]
}
>

View File

@ -6,13 +6,10 @@ const prefix = isIOS ? 'ios' : 'md';
// icon name from provider: [ size of the uri, icon provider, name to be used later ]
const icons = {
[`${ prefix }-search`]: [30, Ionicons, 'search'],
[`${ prefix }-menu`]: [30, Ionicons, 'menu'],
[`${ prefix }-star`]: [30, Ionicons, 'star'],
[`${ prefix }-star-outline`]: [30, Ionicons, 'starOutline'],
[isIOS ? 'ios-create' : 'md-create']: [30, Ionicons, 'create'],
[`${ prefix }-more`]: [30, Ionicons, 'more'],
[`${ prefix }-add`]: [30, Ionicons, 'add'],
[isIOS ? 'ios-create' : 'md-create']: [30, Ionicons, 'create'],
[`${ prefix }-close`]: [30, Ionicons, 'close']
};

View File

@ -14,6 +14,9 @@ async function loadMessagesForRoomRest({ rid: roomId, latest, t }) {
const { token, id } = this.ddp._login;
const server = this.ddp.url.replace('ws', 'http');
const data = await get({ token, id, server }, `${ types[t] }.history`, { roomId, latest });
if (!data || data.status === 'error') {
return [];
}
return data.messages;
}

View File

@ -10,6 +10,9 @@ async function loadMissedMessagesRest({ rid: roomId, lastOpen: lastUpdate }) {
const server = this.ddp.url.replace('ws', 'http');
const { result } = await get({ token, id, server }, 'chat.syncMessages', { roomId, lastUpdate });
// TODO: api fix
if (!result) {
return [];
}
return result.updated || result.messages;
}

View File

@ -1,5 +1,7 @@
import { put, call, takeLatest } from 'redux-saga/effects';
import { AsyncStorage } from 'react-native';
import { Navigation } from 'react-native-navigation';
import { Provider } from 'react-redux';
import { NavigationActions } from '../Navigation';
import { SERVER } from '../actions/actionsTypes';
@ -10,6 +12,9 @@ import { setRoles } from '../actions/roles';
import RocketChat from '../lib/rocketchat';
import database from '../lib/realm';
import log from '../utils/log';
import store from '../lib/createStore';
let LoginSignupView = null;
const validate = function* validate(server) {
return yield RocketChat.testServer(server);
@ -43,6 +48,11 @@ const handleSelectServer = function* handleSelectServer({ server }) {
const handleServerRequest = function* handleServerRequest({ server }) {
try {
if (LoginSignupView == null) {
LoginSignupView = require('../views/LoginSignupView').default;
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
}
yield call(validate, server);
yield call(NavigationActions.push, { screen: 'LoginSignupView', title: server, backButtonTitle: '' });
database.databases.serversDB.write(() => {

View File

@ -1,7 +1,9 @@
import DeviceInfo from 'react-native-device-info';
const NOTCH_DEVICES = ['iPhone X', 'iPhone XS', 'iPhone XS Max', 'iPhone XR'];
export default {
isNotch: () => DeviceInfo.getModel() === 'iPhone X',
isNotch: () => NOTCH_DEVICES.includes(DeviceInfo.getModel()),
getBrand: () => DeviceInfo.getBrand(),
getReadableVersion: () => DeviceInfo.getReadableVersion()
};

View File

@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import {
Text, View, ScrollView, TouchableOpacity, LayoutAnimation, Image, StyleSheet, SafeAreaView
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import Icon from 'react-native-vector-icons/FontAwesome';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { Base64 } from 'js-base64';
@ -16,6 +17,7 @@ import random from '../utils/random';
import Button from '../containers/Button';
import Loading from '../containers/Loading';
import I18n from '../i18n';
import store from '../lib/createStore';
const styles = StyleSheet.create({
container: {
@ -45,6 +47,10 @@ const styles = StyleSheet.create({
}
});
let OAuthView = null;
let LoginView = null;
let RegisterView = null;
@connect(state => ({
server: state.server.server,
isFetching: state.login.isFetching,
@ -181,6 +187,11 @@ export default class LoginSignupView extends LoggedView {
}
openOAuth = (oAuthUrl) => {
if (OAuthView == null) {
OAuthView = require('./OAuthView').default;
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
}
const { navigator } = this.props;
navigator.showModal({
screen: 'OAuthView',
@ -192,6 +203,11 @@ export default class LoginSignupView extends LoggedView {
}
login = () => {
if (LoginView == null) {
LoginView = require('./LoginView').default;
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
}
const { navigator, server } = this.props;
navigator.push({
screen: 'LoginView',
@ -201,6 +217,11 @@ export default class LoginSignupView extends LoggedView {
}
register = () => {
if (RegisterView == null) {
RegisterView = require('./RegisterView').default;
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
}
const { navigator, server } = this.props;
navigator.push({
screen: 'RegisterView',

View File

@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import {
Keyboard, Text, ScrollView, View, SafeAreaView
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import { Answers } from 'react-native-fabric';
import RocketChat from '../lib/rocketchat';
@ -17,6 +18,10 @@ import { showToast } from '../utils/info';
import { COLOR_BUTTON_PRIMARY } from '../constants/colors';
import LoggedView from './View';
import I18n from '../i18n';
import store from '../lib/createStore';
let RegisterView = null;
let ForgotPasswordView = null;
@connect(state => ({
server: state.server.server,
@ -69,6 +74,11 @@ export default class LoginView extends LoggedView {
}
register = () => {
if (RegisterView == null) {
RegisterView = require('./RegisterView').default;
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
}
const { navigator, server } = this.props;
navigator.push({
screen: 'RegisterView',
@ -78,6 +88,11 @@ export default class LoginView extends LoggedView {
}
forgotPassword = () => {
if (ForgotPasswordView == null) {
ForgotPasswordView = require('./ForgotPasswordView').default;
Navigation.registerComponent('ForgotPasswordView', () => ForgotPasswordView, store, Provider);
}
const { navigator } = this.props;
navigator.push({
screen: 'ForgotPasswordView',

View File

@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import {
View, StyleSheet, SafeAreaView, FlatList, Text, Platform, Image
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import database from '../lib/realm';
import RocketChat from '../lib/rocketchat';
@ -14,6 +15,7 @@ import sharedStyles from './Styles';
import I18n from '../i18n';
import Touch from '../utils/touch';
import SearchBox from '../containers/SearchBox';
import store from '../lib/createStore';
const styles = StyleSheet.create({
safeAreaView: {
@ -43,6 +45,8 @@ const styles = StyleSheet.create({
}
});
let SelectedUsersView = null;
@connect(state => ({
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
}))
@ -110,6 +114,11 @@ export default class NewMessageView extends LoggedView {
}
createChannel = () => {
if (SelectedUsersView == null) {
SelectedUsersView = require('./SelectedUsersView').default;
Navigation.registerComponent('SelectedUsersView', () => SelectedUsersView, store, Provider);
}
const { navigator } = this.props;
navigator.push({
screen: 'SelectedUsersView',

View File

@ -4,7 +4,8 @@ import {
} from 'react-native';
import PropTypes from 'prop-types';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import { selectServerRequest, serverInitAdd, serverFinishAdd } from '../../actions/server';
import I18n from '../../i18n';
@ -13,6 +14,9 @@ import Button from './Button';
import styles from './styles';
import LoggedView from '../View';
import DeviceInfo from '../../utils/deviceInfo';
import store from '../../lib/createStore';
let NewServerView = null;
@connect(state => ({
currentServer: state.server.server,
@ -63,6 +67,11 @@ export default class OnboardingView extends LoggedView {
}
connectServer = () => {
if (NewServerView == null) {
NewServerView = require('../NewServerView').default;
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
}
const { navigator } = this.props;
navigator.push({
screen: 'NewServerView',
@ -74,6 +83,11 @@ export default class OnboardingView extends LoggedView {
}
joinCommunity = () => {
if (NewServerView == null) {
NewServerView = require('../NewServerView').default;
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
}
const { navigator } = this.props;
navigator.push({
screen: 'NewServerView',

View File

@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import {
Keyboard, Text, View, ScrollView, SafeAreaView
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import { registerSubmit as registerSubmitAction, setUsernameSubmit as setUsernameSubmitAction } from '../actions/login';
import TextInput from '../containers/TextInput';
@ -15,6 +16,10 @@ import { showToast } from '../utils/info';
import scrollPersistTaps from '../utils/scrollPersistTaps';
import LoggedView from './View';
import I18n from '../i18n';
import store from '../lib/createStore';
let TermsServiceView = null;
let PrivacyPolicyView = null;
@connect(state => ({
server: state.server.server,
@ -97,6 +102,11 @@ export default class RegisterView extends LoggedView {
}
termsService = () => {
if (TermsServiceView == null) {
TermsServiceView = require('./TermsServiceView').default;
Navigation.registerComponent('TermsServiceView', () => TermsServiceView, store, Provider);
}
const { navigator } = this.props;
navigator.push({
screen: 'TermsServiceView',
@ -106,6 +116,11 @@ export default class RegisterView extends LoggedView {
}
privacyPolicy = () => {
if (PrivacyPolicyView == null) {
PrivacyPolicyView = require('./PrivacyPolicyView').default;
Navigation.registerComponent('PrivacyPolicyView', () => PrivacyPolicyView, store, Provider);
}
const { navigator } = this.props;
navigator.push({
screen: 'PrivacyPolicyView',

View File

@ -5,7 +5,8 @@ import {
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import { leaveRoom as leaveRoomAction } from '../../actions/room';
import LoggedView from '../View';
@ -20,9 +21,12 @@ import log from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
import I18n from '../../i18n';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import store from '../../lib/createStore';
const renderSeparator = () => <View style={styles.separator} />;
const modules = {};
@connect(state => ({
userId: state.login.user && state.login.user.id,
username: state.login.user && state.login.user.username,
@ -68,6 +72,10 @@ export default class RoomActionsView extends LoggedView {
const { navigator } = this.props;
if (item.route) {
if (modules[item.route] == null) {
modules[item.route] = item.require();
Navigation.registerComponent(item.route, () => modules[item.route], store, Provider);
}
navigator.push({
screen: item.route,
title: item.name,
@ -80,7 +88,7 @@ export default class RoomActionsView extends LoggedView {
}
}
get canAddUser() { // Invite user
get canAddUser() {
const {
rid, t
} = this.room;
@ -128,7 +136,8 @@ export default class RoomActionsView extends LoggedView {
name: I18n.t('Room_Info'),
route: 'RoomInfoView',
params: { rid },
testID: 'room-actions-info'
testID: 'room-actions-info',
require: () => require('../RoomInfoView').default
}],
renderItem: this.renderRoomInfo
}, {
@ -154,28 +163,32 @@ export default class RoomActionsView extends LoggedView {
name: I18n.t('Files'),
route: 'RoomFilesView',
params: { rid },
testID: 'room-actions-files'
testID: 'room-actions-files',
require: () => require('../RoomFilesView').default
},
{
icon: 'ios-at',
name: I18n.t('Mentions'),
route: 'MentionedMessagesView',
params: { rid },
testID: 'room-actions-mentioned'
testID: 'room-actions-mentioned',
require: () => require('../MentionedMessagesView').default
},
{
icon: 'ios-star',
name: I18n.t('Starred'),
route: 'StarredMessagesView',
params: { rid },
testID: 'room-actions-starred'
testID: 'room-actions-starred',
require: () => require('../StarredMessagesView').default
},
{
icon: 'ios-search',
name: I18n.t('Search'),
route: 'SearchMessagesView',
params: { rid },
testID: 'room-actions-search'
testID: 'room-actions-search',
require: () => require('../SearchMessagesView').default
},
{
icon: 'ios-share',
@ -188,14 +201,16 @@ export default class RoomActionsView extends LoggedView {
name: I18n.t('Pinned'),
route: 'PinnedMessagesView',
params: { rid },
testID: 'room-actions-pinned'
testID: 'room-actions-pinned',
require: () => require('../PinnedMessagesView').default
},
{
icon: 'ios-code',
name: I18n.t('Snippets'),
route: 'SnippetedMessagesView',
params: { rid },
testID: 'room-actions-snippeted'
testID: 'room-actions-snippeted',
require: () => require('../SnippetedMessagesView').default
},
{
icon: `ios-notifications${ notifications ? '' : '-off' }`,
@ -232,7 +247,8 @@ export default class RoomActionsView extends LoggedView {
: I18n.t('N_online_members', { n: onlineMembers.length })),
route: 'RoomMembersView',
params: { rid, members: onlineMembers },
testID: 'room-actions-members'
testID: 'room-actions-members',
require: () => require('../RoomMembersView').default
});
}
@ -245,7 +261,8 @@ export default class RoomActionsView extends LoggedView {
nextAction: 'ADD_USER',
rid
},
testID: 'room-actions-add-user'
testID: 'room-actions-add-user',
require: () => require('../SelectedUsersView').default
});
}
sections[2].data = [...actions, ...sections[2].data];

View File

@ -3,8 +3,9 @@ import PropTypes from 'prop-types';
import {
View, Text, ScrollView, SafeAreaView
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import moment from 'moment';
import { Navigation } from 'react-native-navigation';
import LoggedView from '../View';
import Status from '../../containers/status';
@ -18,6 +19,7 @@ import log from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
import I18n from '../../i18n';
import { iconsMap } from '../../Icons';
import store from '../../lib/createStore';
const PERMISSION_EDIT_ROOM = 'edit-room';
@ -32,6 +34,8 @@ const getRoomTitle = room => (room.t === 'd'
)
);
let RoomInfoEditView = null;
@connect(state => ({
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
userId: state.login.user && state.login.user.id,
@ -80,6 +84,11 @@ export default class RoomInfoView extends LoggedView {
const { rid, navigator } = this.props;
if (event.type === 'NavBarButtonPress') {
if (event.id === 'edit') {
if (RoomInfoEditView == null) {
RoomInfoEditView = require('../RoomInfoEditView').default;
Navigation.registerComponent('RoomInfoEditView', () => RoomInfoEditView, store, Provider);
}
navigator.push({
screen: 'RoomInfoEditView',
title: I18n.t('Room_Info_Edit'),

View File

@ -3,9 +3,9 @@ import PropTypes from 'prop-types';
import {
Text, View, LayoutAnimation, ActivityIndicator, SafeAreaView
} from 'react-native';
import { connect } from 'react-redux';
import equal from 'deep-equal';
import { connect, Provider } from 'react-redux';
import { RectButton } from 'react-native-gesture-handler';
import { Navigation } from 'react-native-navigation';
import { openRoom as openRoomAction, closeRoom as closeRoomAction, setLastOpen as setLastOpenAction } from '../../actions/room';
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
@ -24,6 +24,9 @@ import log from '../../utils/log';
import I18n from '../../i18n';
import debounce from '../../utils/debounce';
import { iconsMap } from '../../Icons';
import store from '../../lib/createStore';
let RoomActionsView = null;
@connect(state => ({
user: {
@ -104,8 +107,23 @@ export default class RoomView extends LoggedView {
}
shouldComponentUpdate(nextProps, nextState) {
const { room } = this.state;
return !(equal(this.props, nextProps) && equal(this.state, nextState) && room.ro === nextState.room.ro);
const {
room, loaded, joined, end
} = this.state;
const { showActions } = this.props;
if (room.ro !== nextState.room.ro) {
return true;
} else if (loaded !== nextState.loaded) {
return true;
} else if (joined !== nextState.joined) {
return true;
} else if (end !== nextState.end) {
return true;
} else if (showActions !== nextProps.showActions) {
return true;
}
return false;
}
componentDidUpdate(prevProps, prevState) {
@ -141,6 +159,11 @@ export default class RoomView extends LoggedView {
if (event.type === 'NavBarButtonPress') {
if (event.id === 'more') {
if (RoomActionsView == null) {
RoomActionsView = require('../RoomActionsView').default;
Navigation.registerComponent('RoomActionsView', () => RoomActionsView, store, Provider);
}
navigator.push({
screen: 'RoomActionsView',
title: I18n.t('Actions'),

View File

@ -3,8 +3,9 @@ import PropTypes from 'prop-types';
import {
Platform, View, FlatList, BackHandler, ActivityIndicator, SafeAreaView, Text, Image, Dimensions, ScrollView, Keyboard
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { isEqual } from 'lodash';
import { Navigation } from 'react-native-navigation';
import SearchBox from '../../containers/SearchBox';
import database from '../../lib/realm';
@ -18,12 +19,15 @@ import SortDropdown from './SortDropdown';
import ServerDropdown from './ServerDropdown';
import Touch from '../../utils/touch';
import { toggleSortDropdown as toggleSortDropdownAction } from '../../actions/rooms';
import store from '../../lib/createStore';
const ROW_HEIGHT = 70;
const SCROLL_OFFSET = 56;
const isAndroid = () => Platform.OS === 'android';
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
const keyExtractor = item => item.rid;
const leftButtons = [{
id: 'settings',
icon: { uri: 'settings', scale: Dimensions.get('window').scale },
@ -42,6 +46,8 @@ if (Platform.OS === 'android') {
});
}
let NewMessageView = null;
@connect(state => ({
userId: state.login.user && state.login.user.id,
server: state.server.server,
@ -166,6 +172,11 @@ export default class RoomsListView extends LoggedView {
const { navigator } = this.props;
if (event.type === 'NavBarButtonPress') {
if (event.id === 'newMessage') {
if (NewMessageView == null) {
NewMessageView = require('../NewMessageView').default;
Navigation.registerComponent('NewMessageView', () => NewMessageView, store, Provider);
}
navigator.showModal({
screen: 'NewMessageView',
title: I18n.t('New_Message'),
@ -383,6 +394,8 @@ export default class RoomsListView extends LoggedView {
}, 100);
}
getScrollRef = ref => this.scroll = ref
renderHeader = () => {
const { search } = this.state;
if (search.length > 0) {
@ -456,7 +469,7 @@ export default class RoomsListView extends LoggedView {
<FlatList
data={data}
extraData={data}
keyExtractor={item => item.rid}
keyExtractor={keyExtractor}
style={styles.list}
renderItem={this.renderItem}
ItemSeparatorComponent={this.renderSeparator}
@ -485,7 +498,7 @@ export default class RoomsListView extends LoggedView {
<FlatList
data={search}
extraData={search}
keyExtractor={item => item.rid}
keyExtractor={keyExtractor}
style={styles.list}
renderItem={this.renderItem}
ItemSeparatorComponent={this.renderSeparator}
@ -519,7 +532,7 @@ export default class RoomsListView extends LoggedView {
return (
<ScrollView
ref={ref => this.scroll = ref}
ref={this.getScrollRef}
contentOffset={Platform.OS === 'ios' ? { x: 0, y: SCROLL_OFFSET } : {}}
keyboardShouldPersistTaps='always'
testID='rooms-list-view-list'

View File

@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import {
View, StyleSheet, SafeAreaView, FlatList, LayoutAnimation, Platform
} from 'react-native';
import { connect } from 'react-redux';
import { connect, Provider } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import {
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
@ -18,6 +19,7 @@ import I18n from '../i18n';
import log from '../utils/log';
import SearchBox from '../containers/SearchBox';
import sharedStyles from './Styles';
import store from '../lib/createStore';
const styles = StyleSheet.create({
safeAreaView: {
@ -32,6 +34,8 @@ const styles = StyleSheet.create({
}
});
let CreateChannelView = null;
@connect(state => ({
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
users: state.selectedUsers.users,
@ -108,6 +112,11 @@ export default class SelectedUsersView extends LoggedView {
if (event.id === 'create') {
const { nextAction, setLoadingInvite, navigator } = this.props;
if (nextAction === 'CREATE_CHANNEL') {
if (CreateChannelView == null) {
CreateChannelView = require('./CreateChannelView').default;
Navigation.registerComponent('CreateChannelView', () => CreateChannelView, store, Provider);
}
navigator.push({
screen: 'CreateChannelView',
title: I18n.t('Create_Channel'),

View File

@ -2,64 +2,22 @@ import { Navigation } from 'react-native-navigation';
import { Provider } from 'react-redux';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
import CreateChannelView from './CreateChannelView';
import ForgotPasswordView from './ForgotPasswordView';
import LoginSignupView from './LoginSignupView';
import LoginView from './LoginView';
import MentionedMessagesView from './MentionedMessagesView';
import NewMessageView from './NewMessageView';
import NewServerView from './NewServerView';
import OAuthView from './OAuthView';
import OnboardingView from './OnboardingView';
import PinnedMessagesView from './PinnedMessagesView';
import PrivacyPolicyView from './PrivacyPolicyView';
import ProfileView from './ProfileView';
import RegisterView from './RegisterView';
import RoomActionsView from './RoomActionsView';
import RoomFilesView from './RoomFilesView';
import RoomInfoEditView from './RoomInfoEditView';
import RoomInfoView from './RoomInfoView';
import RoomMembersView from './RoomMembersView';
import RoomsListHeaderView from './RoomsListView/Header';
import RoomsListSearchView from './RoomsListView/Search';
import RoomsListView from './RoomsListView';
import RoomView from './RoomView';
import SearchMessagesView from './SearchMessagesView';
import SelectedUsersView from './SelectedUsersView';
import SettingsView from './SettingsView';
import Sidebar from '../containers/Sidebar';
import SnippetedMessagesView from './SnippetedMessagesView';
import StarredMessagesView from './StarredMessagesView';
import TermsServiceView from './TermsServiceView';
export const registerScreens = (store) => {
Navigation.registerComponent('CreateChannelView', () => CreateChannelView, store, Provider);
Navigation.registerComponent('ForgotPasswordView', () => ForgotPasswordView, store, Provider);
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
Navigation.registerComponent('MentionedMessagesView', () => gestureHandlerRootHOC(MentionedMessagesView), store, Provider);
Navigation.registerComponent('NewMessageView', () => NewMessageView, store, Provider);
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
Navigation.registerComponent('PinnedMessagesView', () => gestureHandlerRootHOC(PinnedMessagesView), store, Provider);
Navigation.registerComponent('PrivacyPolicyView', () => PrivacyPolicyView, store, Provider);
Navigation.registerComponent('ProfileView', () => ProfileView, store, Provider);
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
Navigation.registerComponent('RoomActionsView', () => RoomActionsView, store, Provider);
Navigation.registerComponent('RoomFilesView', () => gestureHandlerRootHOC(RoomFilesView), store, Provider);
Navigation.registerComponent('RoomInfoEditView', () => RoomInfoEditView, store, Provider);
Navigation.registerComponent('RoomInfoView', () => RoomInfoView, store, Provider);
Navigation.registerComponent('RoomMembersView', () => RoomMembersView, store, Provider);
Navigation.registerComponent('RoomsListHeaderView', () => RoomsListHeaderView, store, Provider);
Navigation.registerComponent('RoomsListSearchView', () => RoomsListSearchView, store, Provider);
Navigation.registerComponent('RoomsListView', () => gestureHandlerRootHOC(RoomsListView), store, Provider);
Navigation.registerComponent('RoomView', () => gestureHandlerRootHOC(RoomView), store, Provider);
Navigation.registerComponent('SearchMessagesView', () => gestureHandlerRootHOC(SearchMessagesView), store, Provider);
Navigation.registerComponent('SelectedUsersView', () => SelectedUsersView, store, Provider);
Navigation.registerComponent('SettingsView', () => SettingsView, store, Provider);
Navigation.registerComponent('Sidebar', () => Sidebar, store, Provider);
Navigation.registerComponent('SnippetedMessagesView', () => gestureHandlerRootHOC(SnippetedMessagesView), store, Provider);
Navigation.registerComponent('StarredMessagesView', () => gestureHandlerRootHOC(StarredMessagesView), store, Provider);
Navigation.registerComponent('TermsServiceView', () => TermsServiceView, store, Provider);
};

28
package-lock.json generated
View File

@ -6788,9 +6788,9 @@
}
},
"detox": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/detox/-/detox-9.0.1.tgz",
"integrity": "sha512-KT0Sptt4JvWHTXP1dxMzqXc/LCJxZIB9bKGtjDjg6hdLwOmLAxY3Zfz22ASKGC33rLT6dw/uvyODjgwfVzlYfw==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/detox/-/detox-9.0.2.tgz",
"integrity": "sha512-TRPvaQpiWOzkYzh+qybefvPNHj7dSffY2kRQoKC7iJbMZUWfw5JNJ5htYEwvzH8g6kBR4zzlsYbf4/AwJvkQqw==",
"dev": true,
"requires": {
"bunyan": "^1.8.12",
@ -13737,7 +13737,7 @@
},
"rimraf": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"dev": true,
"optional": true,
@ -13873,7 +13873,7 @@
},
"ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"dev": true,
"optional": true
@ -16709,9 +16709,9 @@
}
},
"react-native-device-info": {
"version": "0.22.5",
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-0.22.5.tgz",
"integrity": "sha512-Pe+7eoWOR/TmZxWLaa8rmEmqRckyvPnniDXjiKxaUSk5oUCCtHjFajVYSVkWoJGPwd4xQYjrhx1gr/tcvjSEwQ=="
"version": "0.22.6",
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-0.22.6.tgz",
"integrity": "sha512-/w87PmHPvT5MY3HwzdVEWyFg/ib91lY6TlYJGNnNPaXNXY60ShB8HI+GXKyq4KAtbUc/WhRM1RQ8/WKJOal+UQ=="
},
"react-native-dialog": {
"version": "5.1.0",
@ -16728,9 +16728,9 @@
"integrity": "sha512-NKYXiH8w/DjNXoozko1twjAd5F8shL/UiTVx/PQ8QNaasWpbxlXgeJ5exhDSIcDXao0AUdcPWJunYdSCjq208g=="
},
"react-native-fast-image": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-5.0.3.tgz",
"integrity": "sha512-70XlQPt8b7yQSMwUEEIN5jTx7KOx1EBD2XhIRIEHChfNv5Gwn8dh28RSo/Dq9qezf4CWJXO3CAb4lq+Hu9d0vw=="
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-5.0.10.tgz",
"integrity": "sha512-9WRINd7xk0Hhv3ublbJqGpU+dEApzMmabHU/5ULGvQ0LBWdCFF/4ScQMPJlI0dnCMu/++/emRshn4ML6sQ1yhQ=="
},
"react-native-fit-image": {
"version": "1.5.4",
@ -19775,9 +19775,9 @@
}
},
"tail": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/tail/-/tail-1.3.0.tgz",
"integrity": "sha512-9Blh9bCW3lQyr10UAh//7K3kqljspQ+NcMa5nwVXicnxFXfiUizZrEC71kqVKPhe2UcMLXDEb+YnqR+tzvOEDQ==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/tail/-/tail-1.4.0.tgz",
"integrity": "sha512-wjwfZw6wcMFTB1Po7NFUf4TdCDwX8duZjdTMhnHBEC677Q6mFRcVZE7f/nZDhG2Fpf/wEEKOJP9L7/b11/vlHQ==",
"dev": true
},
"tapable": {

View File

@ -14,8 +14,7 @@
"storybook": "storybook start -p 7007",
"snyk-protect": "snyk protect",
"fabric-ios": "./scripts/fabric-ios.sh",
"fabric-android": "./scripts/fabric-android.sh",
"postinstall": "cp ./temp/react.gradle ./node_modules/react-native"
"fabric-android": "./scripts/fabric-android.sh"
},
"rnpm": {
"assets": [
@ -38,10 +37,10 @@
"react-native": "^0.57.1",
"react-native-actionsheet": "^2.4.2",
"react-native-audio": "^4.2.0",
"react-native-device-info": "^0.22.5",
"react-native-device-info": "^0.22.6",
"react-native-dialog": "^5.1.0",
"react-native-fabric": "^0.5.1",
"react-native-fast-image": "^5.0.3",
"react-native-fast-image": "^5.0.10",
"react-native-gesture-handler": "^1.0.7",
"react-native-i18n": "^2.0.15",
"react-native-image-crop-picker": "git+https://github.com/RocketChat/react-native-image-crop-picker.git",
@ -87,7 +86,7 @@
"babel-plugin-transform-remove-console": "^6.9.4",
"babel-runtime": "^6.26.0",
"codecov": "^3.1.0",
"detox": "^9.0.1",
"detox": "^9.0.2",
"eslint": "^5.6.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",

View File

@ -1,135 +0,0 @@
// 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.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)
}
}
}