Improve app view flow

This commit is contained in:
Rodrigo Nascimento 2017-08-09 13:19:17 -03:00
parent e01a2d0aaf
commit 9f31e2606e
8 changed files with 203 additions and 108 deletions

View File

@ -1 +1,2 @@
__tests__
node_modules

View File

@ -6,7 +6,10 @@ export default class KeyboardView extends React.PureComponent {
static propTypes = {
style: KeyboardAvoidingView.propTypes.style,
keyboardVerticalOffset: PropTypes.number,
children: PropTypes.array.isRequired
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
}
render() {

View File

@ -20,6 +20,27 @@ const RocketChat = {
export default RocketChat;
Meteor.Accounts.onLogin(() => {
Meteor.call('subscriptions/get', (err, data) => {
if (err) {
console.error(err);
}
realm.write(() => {
data.forEach((subscription) => {
// const subscription = {
// _id: item._id
// };
// if (typeof item.value === 'string') {
// subscription.value = item.value;
// }
subscription._server = { id: RocketChat.currentServer };
realm.create('subscriptions', subscription, true);
});
});
});
});
export function connect(cb) {
const url = `${ RocketChat.currentServer }/websocket`;
@ -52,14 +73,12 @@ export function connect(cb) {
Meteor.ddp.on('changed', (ddbMessage) => {
console.log('changed', ddbMessage);
if (ddbMessage.collection === 'stream-room-messages') {
setTimeout(() => {
realm.write(() => {
const message = ddbMessage.fields.args[0];
message.temp = false;
message._server = { id: RocketChat.currentServer };
realm.create('messages', message, true);
});
}, 1000);
realm.write(() => {
const message = ddbMessage.fields.args[0];
message.temp = false;
message._server = { id: RocketChat.currentServer };
realm.create('messages', message, true);
});
}
});
});

View File

@ -84,6 +84,6 @@ realm.write(() => {
const allSettins = realm.objects('settings');
realm.delete(allSettins);
// realm.create('servers', {id: 'https://demo.rocket.chat', current: false}, true);
// realm.create('servers', {id: 'http://localhost:3000', current: false}, true);
// realm.create('servers', { id: 'https://demo.rocket.chat', current: false }, true);
// realm.create('servers', { id: 'http://localhost:3000', current: false }, true);
});

View File

@ -1,3 +1,5 @@
import React from 'react';
import { Button } from 'react-native';
import { StackNavigator } from 'react-navigation';
import LoginView from './views/login';
import NewServerView from './views/serverNew';
@ -5,26 +7,14 @@ import ListServerView from './views/serverList';
import RoomsListView from './views/roomsList';
import RoomView from './views/room';
const navigationOptions = {
// headerStyle: {
// backgroundColor: '#c1272d'
// },
// headerTitleStyle: {
// color: '#fff'
// }
};
export default new StackNavigator({
ListServer: {
screen: ListServerView,
navigationOptions
const MainCardNavigator = StackNavigator({
Rooms: {
screen: RoomsListView,
navigationOptions: ({ navigation }) => ({
headerLeft: <Button title='Servers' onPress={() => navigation.navigate('ListServerModal')} />
})
},
NewServer: {
screen: NewServerView,
navigationOptions
},
Login: { screen: LoginView },
Rooms: { screen: RoomsListView },
Room: {
screen: RoomView
// navigationOptions: {
@ -32,8 +22,41 @@ export default new StackNavigator({
// }
}
}, {
// initialRouteName: 'Room',
initialRouteName: 'Rooms',
cardStyle: {
backgroundColor: '#fff'
}
});
export default new StackNavigator({
Main: {
screen: MainCardNavigator,
navigationOptions: {
header: null
}
},
Login: {
screen: LoginView,
navigationOptions: ({ navigation }) => ({
headerLeft: <Button title='Cancel' onPress={() => navigation.dispatch({ type: 'Navigation/BACK' })} />
})
},
ListServerModal: {
screen: ListServerView,
navigationOptions: ({ navigation }) => ({
headerLeft: <Button title='Close' onPress={() => navigation.dispatch({ type: 'Navigation/BACK' })} />
})
},
NewServerModal: {
screen: NewServerView,
navigationOptions: ({ navigation }) => ({
headerLeft: <Button title='Close' onPress={() => navigation.dispatch({ type: 'Navigation/BACK' })} />
})
}
}, {
initialRouteName: 'Main',
cardStyle: {
backgroundColor: '#fff'
},
mode: 'modal'
});

View File

@ -1,8 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { TextInput, StyleSheet } from 'react-native';
import realm from '../lib/realm';
import { loginWithPassword, loadSubscriptions, Accounts } from '../lib/meteor';
import { loginWithPassword } from '../lib/meteor';
import KeyboardView from '../components/KeyboardView';
@ -25,19 +24,13 @@ const styles = StyleSheet.create({
}
});
Accounts.onLogin(() => {
loadSubscriptions(() => {
navigate('Rooms');
});
});
export default class LoginView extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired
}
static navigationOptions = () => ({
title: realm.objectForPrimaryKey('settings', 'Site_Name').value
title: 'Login'
});
constructor(props) {
@ -48,10 +41,10 @@ export default class LoginView extends React.Component {
password: ''
};
navigate = this.props.navigation.navigate;
this.submit = () => {
loginWithPassword({ username: this.state.username }, this.state.password);
loginWithPassword({ username: this.state.username }, this.state.password, () => {
this.props.navigation.dispatch({ type: 'Navigation/BACK' });
});
};
}

View File

@ -1,34 +1,87 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, FlatList, StyleSheet } from 'react-native';
import { Text, View, FlatList, StyleSheet } from 'react-native';
import Meteor from 'react-native-meteor';
import realm from '../lib/realm';
import RocketChat from '../lib/meteor';
import RocketChat, { connect } from '../lib/meteor';
import RoomItem from '../components/RoomItem';
const styles = StyleSheet.create({
container: {
flex: 1
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
separator: {
height: 1,
// width: "86%",
backgroundColor: '#CED0CE'
// marginLeft: "14%"
},
list: {
width: '100%'
},
emptyText: {
textAlign: 'center',
fontSize: 18,
color: '#ccc'
}
});
let navigation;
Meteor.getData().on('loggingIn', () => {
setTimeout(() => {
if (Meteor._isLoggingIn === false && Meteor.userId() == null) {
console.log('loggingIn', Meteor.userId());
navigation.navigate('Login');
}
}, 100);
});
Meteor.Accounts.onLogin(() => {
console.log('onLogin');
});
export default class RoomsListView extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired
}
static navigationOptions = () => ({
title: 'Rooms'
});
constructor(props) {
super(props);
this.state = {
dataSource: realm.objects('subscriptions').filtered('_server.id = $0', RocketChat.currentServer).sorted('name')
};
this.state = this.getState();
}
componentWillMount() {
realm.addListener('change', this.updateState);
navigation = this.props.navigation;
const currentServer = realm.objects('servers').filtered('current = true')[0];
if (currentServer) {
connect(() => {
// navigation.navigate('Login');
});
} else {
navigation.navigate('ListServerModal');
}
}
componentWillUnmount() {
realm.removeListener('change', this.updateState);
}
getState = () => ({
dataSource: realm.objects('subscriptions').filtered('_server.id = $0', RocketChat.currentServer).sorted('name')
})
updateState = () => {
this.setState(this.getState());
}
_onPressItem = (id) => {
@ -48,9 +101,9 @@ export default class RoomsListView extends React.Component {
<View style={styles.separator} />
);
render() {
return (
<View style={styles.container}>
renderList = () => {
if (this.state.dataSource.length) {
return (
<FlatList
style={styles.list}
data={this.state.dataSource}
@ -58,6 +111,18 @@ export default class RoomsListView extends React.Component {
keyExtractor={item => item._id}
ItemSeparatorComponent={this.renderSeparator}
/>
);
}
return (
<Text style={styles.emptyText}>No rooms</Text>
);
}
render() {
return (
<View style={styles.container}>
{this.renderList()}
</View>
);
}

View File

@ -58,7 +58,7 @@ export default class ListServerView extends React.Component {
headerRight: (
<Button
title='Add'
onPress={() => navigation.navigate('NewServer')}
onPress={() => navigation.navigate('NewServerModal')}
/>
)
});
@ -70,69 +70,60 @@ export default class ListServerView extends React.Component {
};
}
componentDidMount() {
const getState = () => {
const sections = [{
title: 'My servers',
data: realm.objects('servers')
}];
componentWillMount() {
realm.addListener('change', this.updateState);
zeroconf.on('update', this.updateState);
if (this.state.nearBy) {
const nearBy = Object.keys(this.state.nearBy)
.filter(key => this.state.nearBy[key].addresses);
if (nearBy.length) {
sections.push({
title: 'Nearby',
data: nearBy.map((key) => {
const server = this.state.nearBy[key];
const address = `http://${ server.addresses[0] }:${ server.port }`;
return {
id: address
};
})
});
}
}
return {
...this.state,
sections
};
};
const { navigation } = this.props;
if (navigation && navigation.state.params && navigation.state.params.newServer) {
return navigation.navigate('Login');
}
const currentServer = realm.objects('servers').filtered('current = true')[0];
if (currentServer) {
connect(() => {
navigation.navigate('Login');
});
}
zeroconf.on('update', () => {
this.state.nearBy = zeroconf.getServices();
this.setState(getState());
});
zeroconf.scan('http', 'tcp', 'local.');
realm.addListener('change', () => this.setState(getState()));
this.state = this.getState();
}
this.state = getState();
return null;
componentWillUnmount() {
zeroconf.stop();
realm.removeListener('change', this.updateState);
zeroconf.removeListener('update', this.updateState);
}
onPressItem(item) {
const { navigate } = this.props.navigation;
RocketChat.currentServer = item.id;
connect(() => {
navigate('Login');
});
connect(() => {});
this.props.navigation.dispatch({ type: 'Navigation/BACK' });
}
getState = () => {
const sections = [{
title: 'My servers',
data: realm.objects('servers')
}];
this.state.nearBy = zeroconf.getServices();
if (this.state.nearBy) {
const nearBy = Object.keys(this.state.nearBy)
.filter(key => this.state.nearBy[key].addresses);
if (nearBy.length) {
sections.push({
title: 'Nearby',
data: nearBy.map((key) => {
const server = this.state.nearBy[key];
const address = `http://${ server.addresses[0] }:${ server.port }`;
return {
id: address
};
})
});
}
}
return {
...this.state,
sections
};
};
updateState = () => {
this.setState(this.getState());
}
renderItem = ({ item }) => (