2017-08-03 18:23:43 +00:00
|
|
|
import React from 'react';
|
2017-08-05 18:16:32 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2017-08-12 20:52:55 +00:00
|
|
|
import { Navigation } from 'react-native-navigation';
|
2017-08-11 15:47:18 +00:00
|
|
|
import { Text, TextInput, View, StyleSheet } from 'react-native';
|
|
|
|
import _ from 'underscore';
|
2017-08-14 01:13:48 +00:00
|
|
|
import realm from '../lib/realm';
|
2017-08-07 00:34:35 +00:00
|
|
|
|
2017-08-09 13:12:00 +00:00
|
|
|
import KeyboardView from '../components/KeyboardView';
|
|
|
|
|
2017-08-03 18:23:43 +00:00
|
|
|
const styles = StyleSheet.create({
|
|
|
|
view: {
|
|
|
|
flex: 1,
|
2017-08-07 00:34:35 +00:00
|
|
|
flexDirection: 'column',
|
2017-08-12 20:52:55 +00:00
|
|
|
alignItems: 'stretch',
|
|
|
|
backgroundColor: '#fff'
|
2017-08-03 18:23:43 +00:00
|
|
|
},
|
|
|
|
input: {
|
|
|
|
height: 40,
|
|
|
|
borderColor: '#aaa',
|
|
|
|
margin: 20,
|
|
|
|
padding: 5,
|
|
|
|
borderWidth: 0,
|
|
|
|
backgroundColor: '#f8f8f8'
|
2017-08-07 00:34:35 +00:00
|
|
|
},
|
|
|
|
text: {
|
|
|
|
textAlign: 'center',
|
|
|
|
color: '#888'
|
2017-08-11 15:47:18 +00:00
|
|
|
},
|
|
|
|
validateText: {
|
|
|
|
position: 'absolute',
|
|
|
|
color: 'green',
|
|
|
|
textAlign: 'center',
|
|
|
|
paddingLeft: 50,
|
|
|
|
paddingRight: 50,
|
|
|
|
width: '100%'
|
|
|
|
},
|
|
|
|
validText: {
|
|
|
|
color: 'green'
|
|
|
|
},
|
|
|
|
invalidText: {
|
|
|
|
color: 'red'
|
|
|
|
},
|
|
|
|
validatingText: {
|
|
|
|
color: '#aaa'
|
|
|
|
},
|
|
|
|
spaceView: {
|
|
|
|
flexGrow: 1
|
2017-08-03 18:23:43 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-08-05 18:16:32 +00:00
|
|
|
export default class NewServerView extends React.Component {
|
|
|
|
static propTypes = {
|
2017-08-12 20:52:55 +00:00
|
|
|
navigator: PropTypes.object.isRequired
|
2017-08-05 18:16:32 +00:00
|
|
|
}
|
|
|
|
|
2017-08-09 01:40:55 +00:00
|
|
|
static navigationOptions = () => ({
|
2017-08-07 00:34:35 +00:00
|
|
|
title: 'New Server Connection'
|
|
|
|
});
|
|
|
|
|
2017-08-03 18:23:43 +00:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.state = {
|
2017-08-07 00:34:35 +00:00
|
|
|
defaultServer: 'https://demo.rocket.chat',
|
2017-08-11 15:47:18 +00:00
|
|
|
editable: true,
|
2017-08-03 18:23:43 +00:00
|
|
|
text: ''
|
|
|
|
};
|
|
|
|
|
|
|
|
this.submit = () => {
|
|
|
|
let url = this.state.text.trim();
|
|
|
|
if (!url) {
|
2017-08-07 00:34:35 +00:00
|
|
|
url = this.state.defaultServer;
|
2017-08-11 15:47:18 +00:00
|
|
|
} else {
|
|
|
|
url = this.completeUrl(this.state.text);
|
2017-08-03 18:23:43 +00:00
|
|
|
}
|
|
|
|
|
2017-08-11 15:47:18 +00:00
|
|
|
this.setState({
|
|
|
|
editable: false
|
|
|
|
});
|
|
|
|
|
|
|
|
this.inputElement.blur();
|
|
|
|
this.validateServer(url).then(() => {
|
2017-08-14 01:13:48 +00:00
|
|
|
realm.write(() => {
|
|
|
|
realm.create('servers', { id: url, current: false }, true);
|
|
|
|
});
|
2017-08-12 20:52:55 +00:00
|
|
|
Navigation.dismissModal({
|
|
|
|
animationType: 'slide-down'
|
|
|
|
});
|
2017-08-11 15:47:18 +00:00
|
|
|
}).catch(() => {
|
|
|
|
this.setState({
|
|
|
|
editable: true
|
|
|
|
});
|
|
|
|
this.inputElement.focus();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this._mounted = true;
|
2017-08-12 20:52:55 +00:00
|
|
|
|
|
|
|
this.props.navigator.setTitle({
|
|
|
|
title: 'New server'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.props.navigator.setButtons({
|
|
|
|
rightButtons: [{
|
|
|
|
id: 'close',
|
|
|
|
title: 'Cancel'
|
|
|
|
}],
|
|
|
|
animated: true
|
|
|
|
});
|
|
|
|
|
|
|
|
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
2017-08-11 15:47:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
this._mounted = false;
|
|
|
|
}
|
|
|
|
|
2017-08-12 20:52:55 +00:00
|
|
|
onNavigatorEvent = (event) => {
|
|
|
|
if (event.type === 'NavBarButtonPress') {
|
|
|
|
if (event.id === 'close') {
|
|
|
|
Navigation.dismissModal({
|
|
|
|
animationType: 'slide-down'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-11 15:47:18 +00:00
|
|
|
onChangeText = (text) => {
|
|
|
|
this.setState({ text });
|
2017-08-07 00:34:35 +00:00
|
|
|
|
2017-08-11 15:47:18 +00:00
|
|
|
this.validateServerDebounced(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
validateServer = url => new Promise((resolve, reject) => {
|
|
|
|
url = this.completeUrl(url);
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
validating: false,
|
|
|
|
url
|
|
|
|
});
|
|
|
|
|
|
|
|
if (/^(https?:\/\/)?(((\w|[0-9])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) {
|
|
|
|
this.setState({
|
|
|
|
validating: true
|
|
|
|
});
|
|
|
|
|
2017-08-14 01:13:48 +00:00
|
|
|
fetch(url, { method: 'HEAD' })
|
2017-08-11 15:47:18 +00:00
|
|
|
.then((response) => {
|
|
|
|
if (!this._mounted) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (response.status === 200 && response.headers.get('x-instance-id') != null && response.headers.get('x-instance-id').length) {
|
|
|
|
this.setState({
|
|
|
|
validInstance: true,
|
|
|
|
validating: false
|
|
|
|
});
|
|
|
|
resolve(url);
|
|
|
|
} else {
|
|
|
|
this.setState({
|
|
|
|
validInstance: false,
|
|
|
|
validating: false
|
|
|
|
});
|
|
|
|
reject(url);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
if (!this._mounted) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.setState({
|
|
|
|
validInstance: false,
|
|
|
|
validating: false
|
|
|
|
});
|
|
|
|
reject(url);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.setState({
|
|
|
|
validInstance: undefined
|
|
|
|
});
|
|
|
|
reject(url);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
validateServerDebounced = _.debounce(this.validateServer, 1000)
|
|
|
|
|
|
|
|
completeUrl = (url) => {
|
|
|
|
url = url.trim();
|
|
|
|
|
|
|
|
if (/^(\w|[0-9-_]){3,}$/.test(url) && /^(htt(ps?)?)|(loca((l)?|(lh)?|(lho)?|(lhos)?|(lhost:?\d*)?)$)/.test(url) === false) {
|
|
|
|
url = `${ url }.rocket.chat`;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (/^(https?:\/\/)?(((\w|[0-9])+(\.(\w|[0-9-_])+)+)|localhost)(:\d+)?$/.test(url)) {
|
|
|
|
if (/^localhost(:\d+)?/.test(url)) {
|
|
|
|
url = `http://${ url }`;
|
|
|
|
} else if (/^https?:\/\//.test(url) === false) {
|
2017-08-07 00:34:35 +00:00
|
|
|
url = `https://${ url }`;
|
|
|
|
}
|
2017-08-11 15:47:18 +00:00
|
|
|
}
|
2017-08-03 18:23:43 +00:00
|
|
|
|
2017-08-11 15:47:18 +00:00
|
|
|
url = url.replace(/\/+$/, '');
|
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
renderValidation = () => {
|
|
|
|
if (this.state.validating) {
|
|
|
|
return (
|
|
|
|
<Text style={[styles.validateText, styles.validatingText]}>
|
|
|
|
Validating {this.state.url} ...
|
|
|
|
</Text>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.state.validInstance) {
|
|
|
|
return (
|
|
|
|
<Text style={[styles.validateText, styles.validText]}>
|
|
|
|
{this.state.url} is a valid Rocket.Chat instance
|
|
|
|
</Text>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.state.validInstance === false) {
|
|
|
|
return (
|
|
|
|
<Text style={[styles.validateText, styles.invalidText]}>
|
|
|
|
{this.state.url} is not a valid Rocket.Chat instance
|
|
|
|
</Text>
|
|
|
|
);
|
|
|
|
}
|
2017-08-03 18:23:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
2017-08-11 15:47:18 +00:00
|
|
|
<KeyboardView style={styles.view} keyboardVerticalOffset={64}>
|
|
|
|
<View style={styles.spaceView} />
|
2017-08-03 18:23:43 +00:00
|
|
|
<TextInput
|
2017-08-11 15:47:18 +00:00
|
|
|
ref={ref => this.inputElement = ref}
|
2017-08-03 18:23:43 +00:00
|
|
|
style={styles.input}
|
2017-08-11 15:47:18 +00:00
|
|
|
onChangeText={this.onChangeText}
|
2017-08-03 18:23:43 +00:00
|
|
|
keyboardType='url'
|
|
|
|
autoCorrect={false}
|
|
|
|
returnKeyType='done'
|
|
|
|
autoCapitalize='none'
|
2017-08-05 18:16:32 +00:00
|
|
|
autoFocus
|
2017-08-11 15:47:18 +00:00
|
|
|
editable={this.state.editable}
|
2017-08-03 18:23:43 +00:00
|
|
|
onSubmitEditing={this.submit}
|
2017-08-07 00:34:35 +00:00
|
|
|
placeholder={this.state.defaultServer}
|
2017-08-05 18:16:32 +00:00
|
|
|
/>
|
2017-08-11 15:47:18 +00:00
|
|
|
<View style={styles.spaceView}>
|
|
|
|
{this.renderValidation()}
|
|
|
|
</View>
|
2017-08-09 13:12:00 +00:00
|
|
|
</KeyboardView>
|
2017-08-03 18:23:43 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|