diff --git a/app/components/channel_loader/index.js b/app/components/channel_loader/index.js index ec68326d9..0e5d93b75 100644 --- a/app/components/channel_loader/index.js +++ b/app/components/channel_loader/index.js @@ -6,10 +6,9 @@ import {getTheme} from 'app/selectors/preferences'; import ChannelLoader from './channel_loader'; -function mapStateToProps(state, ownProps) { +function mapStateToProps(state) { const {deviceWidth} = state.device.dimension; return { - ...ownProps, channelIsLoading: state.views.channel.loading, deviceWidth, theme: getTheme(state) diff --git a/app/components/offline_indicator/index.js b/app/components/offline_indicator/index.js index 6b39265bf..3c0a23dec 100644 --- a/app/components/offline_indicator/index.js +++ b/app/components/offline_indicator/index.js @@ -1,37 +1,22 @@ // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; -import {close as closeWebSocket, init as initWebSocket} from 'mattermost-redux/actions/websocket'; - import {getConnection} from 'app/selectors/device'; import OfflineIndicator from './offline_indicator'; -function mapStateToProps(state, ownProps) { +function mapStateToProps(state) { const {websocket} = state.requests.general; - const {appState} = state.entities.general; const webSocketStatus = websocket.status; - const isConnecting = websocket.error >= 2; + const isConnecting = websocket.error > 1; return { - appState, isConnecting, isOnline: getConnection(state), - webSocketStatus, - ...ownProps + webSocketStatus }; } -function mapDispatchToProps(dispatch) { - return { - actions: bindActionCreators({ - closeWebSocket, - initWebSocket - }, dispatch) - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(OfflineIndicator); +export default connect(mapStateToProps)(OfflineIndicator); diff --git a/app/components/offline_indicator/offline_indicator.js b/app/components/offline_indicator/offline_indicator.js index ac2d3d5f7..2f23976d1 100644 --- a/app/components/offline_indicator/offline_indicator.js +++ b/app/components/offline_indicator/offline_indicator.js @@ -1,14 +1,13 @@ // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import React, {PureComponent} from 'react'; +import React, {Component} from 'react'; import PropTypes from 'prop-types'; import { ActivityIndicator, Animated, Platform, StyleSheet, - TouchableOpacity, View } from 'react-native'; import IonIcon from 'react-native-vector-icons/Ionicons'; @@ -24,20 +23,14 @@ const OFFLINE = 'offline'; const CONNECTING = 'connecting'; const CONNECTED = 'connected'; -export default class OfflineIndicator extends PureComponent { +export default class OfflineIndicator extends Component { static propTypes = { - actions: PropTypes.shape({ - closeWebSocket: PropTypes.func.isRequired, - initWebSocket: PropTypes.func.isRequired - }).isRequired, - appState: PropTypes.bool, isConnecting: PropTypes.bool, isOnline: PropTypes.bool, webSocketStatus: PropTypes.string }; static defaultProps: { - appState: true, isOnline: true }; @@ -53,42 +46,30 @@ export default class OfflineIndicator extends PureComponent { } componentWillReceiveProps(nextProps) { - const {appState, isConnecting, isOnline, webSocketStatus} = nextProps; - if (appState) { // The app is in the foreground - if (isOnline) { - if (this.state.network && webSocketStatus === RequestStatus.SUCCESS) { - // Show the connected animation only if we had a previous network status - this.connected(); - } else if ((webSocketStatus === RequestStatus.STARTED || webSocketStatus === RequestStatus.FAILURE) && isConnecting) { - // Show the connecting bar if it failed to connect at least twice - this.connecting(); - } - } else { - this.offline(); + const {webSocketStatus} = this.props; + if (nextProps.isOnline) { + if (this.state.network && webSocketStatus === RequestStatus.STARTED && nextProps.webSocketStatus === RequestStatus.SUCCESS) { + // Show the connected animation only if we had a previous network status + this.connected(); + } else if (webSocketStatus === RequestStatus.STARTED && nextProps.webSocketStatus === RequestStatus.FAILURE && nextProps.isConnecting) { + // Show the connecting bar if it failed to connect at least twice + this.connecting(); } + } else { + this.offline(); } } + shouldComponentUpdate(nextProps, nextState) { + return nextState.network !== this.state.network && nextState.network; + } + offline = () => { this.setState({network: OFFLINE}, () => { this.show(); }); }; - connect = () => { - const {actions, isOnline, webSocketStatus} = this.props; - const {closeWebSocket, initWebSocket} = actions; - initWebSocket(Platform.OS); - - // close the WS connection after trying for 5 seconds - setTimeout(() => { - if (webSocketStatus !== RequestStatus.SUCCESS) { - closeWebSocket(true); - this.setState({network: isOnline ? OFFLINE : CONNECTING}); - } - }, 5000); - }; - connecting = () => { const prevState = this.state.network; this.setState({network: CONNECTING}, () => { @@ -111,7 +92,7 @@ export default class OfflineIndicator extends PureComponent { this.state.top, { toValue: INITIAL_TOP, duration: 300, - delay: 1000 + delay: 500 } ) ]).start(() => { @@ -146,18 +127,6 @@ export default class OfflineIndicator extends PureComponent { case OFFLINE: i18nId = 'mobile.offlineIndicator.offline'; defaultMessage = 'No internet connection'; - action = ( - - - - ); break; case CONNECTING: i18nId = 'mobile.offlineIndicator.connecting'; diff --git a/app/screens/options_modal/index.js b/app/screens/options_modal/index.js index 929aa5201..c3184277c 100644 --- a/app/screens/options_modal/index.js +++ b/app/screens/options_modal/index.js @@ -7,9 +7,8 @@ import {getDimensions} from 'app/selectors/device'; import OptionsModal from './options_modal'; -function mapStateToProps(state, ownProps) { +function mapStateToProps(state) { return { - ...ownProps, ...getDimensions(state) }; } diff --git a/app/screens/root/index.js b/app/screens/root/index.js index 0306e9d03..d2af2aa99 100644 --- a/app/screens/root/index.js +++ b/app/screens/root/index.js @@ -10,11 +10,9 @@ import {getTheme} from 'app/selectors/preferences'; import Root from './root'; -function mapStateToProps(state, ownProps) { +function mapStateToProps(state) { return { - ...ownProps, credentials: state.entities.general.credentials, - loginRequest: state.requests.users.login, theme: getTheme(state) }; } diff --git a/app/screens/root/root.js b/app/screens/root/root.js index 261a66f9f..aa740d71d 100644 --- a/app/screens/root/root.js +++ b/app/screens/root/root.js @@ -1,21 +1,19 @@ // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import React, {PureComponent} from 'react'; +import React, {Component} from 'react'; import PropTypes from 'prop-types'; import {Client, Client4} from 'mattermost-redux/client'; -import {RequestStatus} from 'mattermost-redux/constants'; import Loading from 'app/components/loading'; import {stripTrailingSlashes} from 'app/utils/url'; -export default class Root extends PureComponent { +export default class Root extends Component { static propTypes = { allowOtherServers: PropTypes.bool, credentials: PropTypes.object, justInit: PropTypes.bool, - loginRequest: PropTypes.object, navigator: PropTypes.object, theme: PropTypes.object, actions: PropTypes.shape({ @@ -23,6 +21,13 @@ export default class Root extends PureComponent { }).isRequired }; + shouldComponentUpdate(nextProps) { + if (nextProps.credentials !== this.props.credentials) { + return true; + } + return false; + } + componentDidMount() { if (!this.props.justInit) { this.loadStoreAndScene(); @@ -66,21 +71,15 @@ export default class Root extends PureComponent { }; loadStoreAndScene = () => { - const {actions, credentials, loginRequest} = this.props; + const {actions, credentials} = this.props; const {loadMe} = actions; if (credentials.token && credentials.url) { - // Will probably need to make this optimistic since we - // assume that the stored token is good. - if (loginRequest.status === RequestStatus.NOT_STARTED) { - Client.setToken(credentials.token); - Client4.setToken(credentials.token); - Client4.setUrl(stripTrailingSlashes(credentials.url)); - Client.setUrl(stripTrailingSlashes(credentials.url)); + Client.setToken(credentials.token); + Client4.setToken(credentials.token); + Client4.setUrl(stripTrailingSlashes(credentials.url)); + Client.setUrl(stripTrailingSlashes(credentials.url)); - loadMe().then(this.goToLoadTeam).catch(this.goToLoadTeam); - } else { - this.goToLoadTeam(); - } + loadMe().then(this.goToLoadTeam).catch(this.goToLoadTeam); } else { this.goToSelectServer(); } diff --git a/app/screens/select_server/index.js b/app/screens/select_server/index.js index 89f6c5057..098929fa0 100644 --- a/app/screens/select_server/index.js +++ b/app/screens/select_server/index.js @@ -14,7 +14,7 @@ import SelectServer from './select_server'; function mapStateToProps(state) { const {config: configRequest, license: licenseRequest, server: pingRequest} = state.requests.general; - const {config, license, serverVersion} = state.entities.general; + const {config, license} = state.entities.general; const success = RequestStatus.SUCCESS; const transition = (pingRequest.status === success && configRequest.status === success && licenseRequest.status === success); @@ -26,7 +26,6 @@ function mapStateToProps(state) { licenseRequest, config, license, - serverVersion, transition, theme: getTheme(state) }; diff --git a/app/screens/select_server/select_server.js b/app/screens/select_server/select_server.js index 7d6612a7b..a9bff1c98 100644 --- a/app/screens/select_server/select_server.js +++ b/app/screens/select_server/select_server.js @@ -15,7 +15,6 @@ import { View } from 'react-native'; import Button from 'react-native-button'; -import semver from 'semver'; import {RequestStatus} from 'mattermost-redux/constants'; import {Client, Client4} from 'mattermost-redux/client'; @@ -43,7 +42,6 @@ class SelectServer extends PureComponent { pingRequest: PropTypes.object.isRequired, configRequest: PropTypes.object.isRequired, licenseRequest: PropTypes.object.isRequired, - serverVersion: PropTypes.string.isRequired, actions: PropTypes.shape({ getPing: PropTypes.func.isRequired, resetPing: PropTypes.func.isRequired, @@ -85,10 +83,9 @@ class SelectServer extends PureComponent { } handleLoginOptions = () => { - const {config, intl, license, serverVersion, theme} = this.props; - const version = serverVersion.match(/^[0-9]*.[0-9]*.[0-9]*(-[a-zA-Z0-9.-]*)?/g)[0]; + const {config, intl, license, theme} = this.props; const samlEnabled = config.EnableSaml === 'true' && license.IsLicensed === 'true' && license.SAML === 'true'; - const gitlabEnabled = config.EnableSignUpWithGitLab === 'true' && semver.valid(version) && semver.gte(version, 'v3.10.0'); + const gitlabEnabled = config.EnableSignUpWithGitLab === 'true'; let options = 0; if (samlEnabled || gitlabEnabled) { diff --git a/app/screens/thread/thread.js b/app/screens/thread/thread.js index 050771de0..e16b82edc 100644 --- a/app/screens/thread/thread.js +++ b/app/screens/thread/thread.js @@ -1,7 +1,7 @@ // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import React, {PureComponent} from 'react'; +import React, {Component} from 'react'; import PropTypes from 'prop-types'; import KeyboardLayout from 'app/components/layout/keyboard_layout'; @@ -10,7 +10,7 @@ import PostTextbox from 'app/components/post_textbox'; import StatusBar from 'app/components/status_bar'; import {makeStyleSheetFromTheme} from 'app/utils/theme'; -export default class Thread extends PureComponent { +export default class Thread extends Component { static propTypes = { actions: PropTypes.shape({ selectPost: PropTypes.func.isRequired @@ -25,6 +25,21 @@ export default class Thread extends PureComponent { state = {}; + shouldComponentUpdate(nextProps) { + if (nextProps.posts.length !== this.props.posts.length) { + return true; + } + + const length = nextProps.posts.length; + for (let i = 0; i < length; i++) { + if (nextProps.posts[i].id !== this.props.posts[i].id) { + return true; + } + } + + return false; + } + componentWillReceiveProps(nextProps) { if (!this.state.lastViewedAt) { this.setState({lastViewedAt: nextProps.myMember.last_viewed_at});