From 1f0dd960f6fcba960e4aa9bf21ae63f35744221a Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Thu, 30 Nov 2017 18:13:23 -0500 Subject: [PATCH] RN-469 Added the ability to cancel a ping when on the select server screen (#1234) * RN-469 Added the ability to cancel a ping when on the select server screen * RN-369 Added i18n strings for new button * Made sure config and license are downloaded before moving to login screen * Have SelectServer screen still show connecting while waiting for config * Don't show SelectServer screen as connected if an error occurs --- app/screens/select_server/index.js | 12 +- app/screens/select_server/select_server.js | 199 +++++++++++++++------ assets/base/i18n/en.json | 4 +- 3 files changed, 152 insertions(+), 63 deletions(-) diff --git a/app/screens/select_server/index.js b/app/screens/select_server/index.js index be7db4ab8..2c1b99380 100644 --- a/app/screens/select_server/index.js +++ b/app/screens/select_server/index.js @@ -15,25 +15,19 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences'; import SelectServer from './select_server'; function mapStateToProps(state) { - const {config: configRequest, license: licenseRequest, server: pingRequest} = state.requests.general; + const {config: configRequest, license: licenseRequest} = state.requests.general; const {config, license} = state.entities.general; const {currentVersion, latestVersion, minVersion} = getClientUpgrade(state); - const success = RequestStatus.SUCCESS; - const transition = (pingRequest.status === success && configRequest.status === success && licenseRequest.status === success); - return { ...state.views.selectServer, config, - configRequest, currentVersion, - pingRequest, + hasConfigAndLicense: configRequest.status === RequestStatus.SUCCESS && licenseRequest.status === RequestStatus.SUCCESS, latestVersion, license, - licenseRequest, minVersion, - theme: getTheme(state), - transition + theme: getTheme(state) }; } diff --git a/app/screens/select_server/select_server.js b/app/screens/select_server/select_server.js index afdc74ce2..0b21909b1 100644 --- a/app/screens/select_server/select_server.js +++ b/app/screens/select_server/select_server.js @@ -11,13 +11,14 @@ import { KeyboardAvoidingView, Platform, StatusBar, + StyleSheet, + Text, TouchableWithoutFeedback, View } from 'react-native'; import Button from 'react-native-button'; import urlParse from 'url-parse'; -import {RequestStatus} from 'mattermost-redux/constants'; import {Client, Client4} from 'mattermost-redux/client'; import Config from 'assets/config'; @@ -42,31 +43,32 @@ class SelectServer extends PureComponent { }).isRequired, allowOtherServers: PropTypes.bool, config: PropTypes.object, - configRequest: PropTypes.object.isRequired, currentVersion: PropTypes.string, + hasConfigAndLicense: PropTypes.bool.isRequired, intl: intlShape.isRequired, latestVersion: PropTypes.string, license: PropTypes.object, - licenseRequest: PropTypes.object.isRequired, minVersion: PropTypes.string, navigator: PropTypes.object, - pingRequest: PropTypes.object.isRequired, serverUrl: PropTypes.string.isRequired, - theme: PropTypes.object, - transition: PropTypes.bool.isRequired + theme: PropTypes.object }; constructor(props) { super(props); this.state = { + connected: false, + connecting: false, error: null }; + + this.cancelPing = null; } componentDidMount() { - const {allowOtherServers, pingRequest, serverUrl} = this.props; - if (pingRequest.status === RequestStatus.NOT_STARTED && !allowOtherServers && serverUrl) { + const {allowOtherServers, serverUrl} = this.props; + if (!allowOtherServers && serverUrl) { // If the app is managed or AutoSelectServerUrl is true in the Config, the server url is set and the user can't change it // we automatically trigger the ping to move to the next screen this.onClick(); @@ -75,21 +77,23 @@ class SelectServer extends PureComponent { if (Platform.OS === 'android') { Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard); } + + this.props.navigator.setOnNavigatorEvent(this.handleNavigatorEvent); } - componentWillReceiveProps(nextProps) { - if (!this.props.transition && nextProps.transition) { + componentWillUpdate(nextProps, nextState) { + if (nextState.connected && nextProps.hasConfigAndLicense && !(this.state.connected && this.props.hasConfigAndLicense)) { if (Config.EnableMobileClientUpgrade) { this.props.actions.setLastUpgradeCheck(); const {currentVersion, minVersion, latestVersion} = nextProps; const upgradeType = checkUpgradeType(currentVersion, minVersion, latestVersion); if (upgradeType === UpgradeTypes.NO_UPGRADE) { - this.handleLoginOptions(); + this.handleLoginOptions(nextProps); } else { this.handleShowClientUpgrade(upgradeType); } } else { - this.handleLoginOptions(); + this.handleLoginOptions(nextProps); } } } @@ -100,6 +104,14 @@ class SelectServer extends PureComponent { } } + handleNavigatorEvent = (event) => { + if (event.id === 'didDisappear') { + this.setState({ + connected: false + }); + } + }; + handleShowClientUpgrade = (upgradeType) => { const {intl, theme} = this.props; @@ -123,8 +135,8 @@ class SelectServer extends PureComponent { }); } - handleLoginOptions = () => { - const {config, intl, license, theme} = this.props; + handleLoginOptions = (props) => { + const {config, intl, license, theme} = props; const samlEnabled = config.EnableSaml === 'true' && license.IsLicensed === 'true' && license.SAML === 'true'; const gitlabEnabled = config.EnableSignUpWithGitLab === 'true'; @@ -167,27 +179,75 @@ class SelectServer extends PureComponent { onClick = wrapWithPreventDoubleTap(async () => { const preUrl = urlParse(this.props.serverUrl, true); const url = stripTrailingSlashes(preUrl.protocol + '//' + preUrl.host); - let error = null; Keyboard.dismiss(); - if (isValidUrl(url)) { - Client4.setUrl(url); - Client.setUrl(url); - this.props.actions.handleServerUrlChanged(url); - await this.props.actions.getPing(); - } else { - error = { - intl: { - id: 'mobile.server_url.invalid_format', - defaultMessage: 'URL must start with http:// or https://' - } - }; + if (this.state.connecting || this.state.connected) { + this.cancelPing(); + + return; } - this.setState({error}); + if (!isValidUrl(url)) { + this.setState({ + error: { + intl: { + id: 'mobile.server_url.invalid_format', + defaultMessage: 'URL must start with http:// or https://' + } + } + }); + + return; + } + + this.pingServer(url); }); + pingServer = (url) => { + this.setState({ + connected: false, + connecting: true, + error: null + }); + + Client4.setUrl(url); + Client.setUrl(url); + this.props.actions.handleServerUrlChanged(url); + + let cancel = false; + this.cancelPing = () => { + cancel = true; + + this.setState({ + connected: false, + connecting: false + }); + + this.cancelPing = null; + }; + + this.props.actions.getPing().then((result) => { + if (cancel) { + return; + } + + this.setState({ + connected: !result.error, + connecting: false, + error: result.error + }); + }).catch(() => { + if (cancel) { + return; + } + + this.setState({ + connecting: false + }); + }); + }; + inputRef = (ref) => { this.textInput = ref; }; @@ -199,44 +259,56 @@ class SelectServer extends PureComponent { }; render() { - const {allowOtherServers, serverUrl, pingRequest, configRequest, licenseRequest} = this.props; - const isLoading = pingRequest.status === RequestStatus.STARTED || - configRequest.status === RequestStatus.STARTED || - licenseRequest.status === RequestStatus.STARTED; + const { + allowOtherServers, + serverUrl + } = this.props; + const { + connected, + connecting, + error + } = this.state; - let proceed; - if (isLoading) { - proceed = ( + let buttonIcon; + let buttonText; + if (connected || connecting) { + buttonIcon = ( + ); + buttonText = ( + ); } else { - proceed = ( - + buttonText = ( + ); } - const error = pingRequest.error || configRequest.error || licenseRequest.error; let statusStyle = 'dark-content'; if (Platform.OS === 'android') { statusStyle = 'light-content'; } + const inputDisabled = !allowOtherServers || connected || connecting; + const inputStyle = [GlobalStyles.inputBox]; + if (inputDisabled) { + inputStyle.push(style.disabledInput); + } + return ( @@ -256,10 +328,10 @@ class SelectServer extends PureComponent { - {proceed} - + + @@ -276,4 +356,19 @@ class SelectServer extends PureComponent { } } +const style = StyleSheet.create({ + container: { + flex: 1 + }, + disabledInput: { + backgroundColor: '#e3e3e3' + }, + connectButton: { + alignItems: 'center' + }, + connectingIndicator: { + marginRight: 5 + } +}); + export default injectIntl(SelectServer); diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index 7002c9fe3..39df9f3bd 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -1951,9 +1951,9 @@ "mobile.commands.error_title": "Error Executing Command", "mobile.components.channels_list_view.yourChannels": "Your channels:", "mobile.components.error_list.dismiss_all": "Dismiss All", - "mobile.components.select_server_view.continue": "Continue", + "mobile.components.select_server_view.connect": "Connect", + "mobile.components.select_server_view.connecting": "Connecting...", "mobile.components.select_server_view.enterServerUrl": "Enter Server URL", - "mobile.components.select_server_view.proceed": "Proceed", "mobile.components.select_server_view.siteUrlPlaceholder": "https://mattermost.example.com", "mobile.edit_channel": "Save", "mobile.create_channel": "Create",