Rocket.Chat.ReactNative/app/views/serverNew.js

257 lines
5.1 KiB
JavaScript
Raw Normal View History

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';
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'
},
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',
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;
} else {
url = this.completeUrl(this.state.text);
2017-08-03 18:23:43 +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'
});
}).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));
}
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'
});
}
}
}
onChangeText = (text) => {
this.setState({ text });
2017-08-07 00:34:35 +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' })
.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-03 18:23:43 +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 (
<KeyboardView style={styles.view} keyboardVerticalOffset={64}>
<View style={styles.spaceView} />
2017-08-03 18:23:43 +00:00
<TextInput
ref={ref => this.inputElement = ref}
2017-08-03 18:23:43 +00:00
style={styles.input}
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
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
/>
<View style={styles.spaceView}>
{this.renderValidation()}
</View>
2017-08-09 13:12:00 +00:00
</KeyboardView>
2017-08-03 18:23:43 +00:00
);
}
}