Improve code organization a bit

This commit is contained in:
Diego Sampaio 2017-08-08 22:40:55 -03:00
parent 783e564c10
commit 2eee28797a
No known key found for this signature in database
GPG Key ID: E060152B30502562
14 changed files with 156 additions and 143 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
__tests__

View File

@ -6,7 +6,7 @@ import Index from '../index.android.js';
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
const tree = renderer.create(
<Index />
);
});

View File

@ -6,7 +6,7 @@ import Index from '../index.ios.js';
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const tree = renderer.create(
<Index />
);
const tree = renderer.create(
<Index />
);
});

43
app/components/Message.js Normal file
View File

@ -0,0 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, Text, StyleSheet, Image } from 'react-native';
const styles = StyleSheet.create({
message: {
borderColor: '#aaa',
padding: 14,
flexDirection: 'row',
transform: [{ scaleY: -1 }]
}
});
export default class Message extends React.PureComponent {
static propTypes = {
item: PropTypes.object.isRequired,
baseUrl: PropTypes.string.isRequired
}
render() {
const extraStyle = {};
if (this.props.item.temp) {
extraStyle.opacity = 0.3;
}
return (
<View style={[styles.message, extraStyle]}>
<Image style={styles.avatar} source={{ uri: `${ this.props.baseUrl }/avatar/${ this.props.item.u.username }` }} />
<View style={styles.texts}>
<Text onPress={this._onPress} style={styles.username}>
{this.props.item.u.username}
</Text>
<Text style={styles.msg}>
{this.props.item.msg}
</Text>
{/* <Markdown whitelist={['link', 'url']}>
{this.props.item.msg}
</Markdown> */}
</View>
</View>
);
}
}

View File

@ -0,0 +1,30 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Text, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
roomItem: {
lineHeight: 18,
borderTopWidth: 2,
borderColor: '#aaa',
padding: 14
}
});
export default class RoomItem extends React.PureComponent {
static propTypes = {
onPressItem: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
id: PropTypes.string.isRequired
}
_onPress = () => {
this.props.onPressItem(this.props.id);
};
render() {
return (
<Text onPress={this._onPress} style={styles.roomItem}>{ this.props.title }</Text>
);
}
}

View File

@ -33,25 +33,23 @@ export function connect(cb) {
cb();
});
Meteor.ddp.on("changed", ddbMessage => {
Meteor.ddp.on('changed', (ddbMessage) => {
console.log('changed', ddbMessage);
if (ddbMessage.collection === 'stream-room-messages') {
setTimeout(function() {
setTimeout(() => {
realm.write(() => {
const message = ddbMessage.fields.args[0];
message.temp = false;
realm.create('messages', message, true);
});
}, 1000)
}, 1000);
}
});
});
}
export function loginWithPassword(selector, password, cb) {
Meteor.loginWithPassword(selector, password, (err, data) => {
cb && cb();
});
Meteor.loginWithPassword(selector, password, () => cb && cb());
}
export function loadSubscriptions(cb) {
@ -72,7 +70,7 @@ export function loadSubscriptions(cb) {
});
});
cb && cb();
return cb && cb();
});
}
@ -102,8 +100,8 @@ export function sendMessage(rid, msg, cb) {
_id,
rid,
msg,
ts: new Date,
_updatedAt: new Date,
ts: new Date(),
_updatedAt: new Date(),
temp: true,
u: {
_id: user._id,
@ -112,7 +110,5 @@ export function sendMessage(rid, msg, cb) {
}, true);
});
Meteor.call('sendMessage', {_id, rid, msg}, (err, data) => {
cb && cb();
});
Meteor.call('sendMessage', { _id, rid, msg }, () => cb && cb());
}

View File

@ -1,9 +1,9 @@
import { StackNavigator } from 'react-navigation';
import LoginView from './login';
import NewServerView from './servers/new';
import ListServerView from './servers/list';
import RoomsView from './rooms';
import RoomView from './room';
import LoginView from './views/login';
import NewServerView from './views/serverNew';
import ListServerView from './views/serverList';
import RoomsListView from './views/roomsList';
import RoomView from './views/room';
const navigationOptions = {
// headerStyle: {
@ -24,7 +24,7 @@ export default new StackNavigator({
navigationOptions
},
Login: { screen: LoginView },
Rooms: { screen: RoomsView },
Rooms: { screen: RoomsListView },
Room: {
screen: RoomView
// navigationOptions: {

View File

@ -1,9 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, TextInput, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
import realm from './realm';
import { loginWithPassword, loadSubscriptions, Accounts } from './meteor';
import { TextInput, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
import realm from '../lib/realm';
import { loginWithPassword, loadSubscriptions, Accounts } from '../lib/meteor';
const styles = StyleSheet.create({
view: {

View File

@ -1,18 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, KeyboardAvoidingView, Text, TextInput, FlatList, StyleSheet, Image, Platform } from 'react-native';
import { View, KeyboardAvoidingView, TextInput, FlatList, StyleSheet, Platform } from 'react-native';
// import Markdown from 'react-native-simple-markdown';
import realm from './realm';
import { loadMessagesForRoom, sendMessage } from './meteor';
import realm from '../lib/realm';
import { loadMessagesForRoom, sendMessage } from '../lib/meteor';
import Message from '../components/Message';
const styles = StyleSheet.create({
roomItem: {
borderColor: '#aaa',
padding: 14,
flexDirection: 'row',
transform: [{ scaleY: -1 }]
},
avatar: {
backgroundColor: '#ccc',
width: 40,
@ -54,36 +49,6 @@ const styles = StyleSheet.create({
}
});
class RoomItem extends React.PureComponent {
static propTypes = {
item: PropTypes.object.isRequired
}
render() {
const extraStyle = {};
if (this.props.item.temp) {
extraStyle.opacity = .3;
}
return (
<View style={[styles.roomItem, extraStyle]}>
<Image style={styles.avatar} source={{ uri: `${ this.props.baseUrl }/avatar/${ this.props.item.u.username }` }} />
<View style={styles.texts}>
<Text onPress={this._onPress} style={styles.username}>
{this.props.item.u.username}
</Text>
<Text style={styles.msg}>
{this.props.item.msg}
</Text>
{/* <Markdown whitelist={['link', 'url']}>
{this.props.item.msg}
</Markdown> */}
</View>
</View>
);
}
}
export default class RoomView extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired
@ -106,16 +71,6 @@ export default class RoomView extends React.Component {
this.url = realm.objectForPrimaryKey('settings', 'Site_Url').value;
}
getMessages = () => {
return realm.objects('messages').filtered('rid = $0', this.rid).sorted('ts', true);
}
updateState = () => {
this.setState({
dataSource: this.getMessages()
});
};
componentWillMount() {
loadMessagesForRoom(this.rid);
realm.addListener('change', this.updateState);
@ -125,17 +80,13 @@ export default class RoomView extends React.Component {
realm.removeListener('change', this.updateState);
}
renderItem = ({ item }) => (
<RoomItem
id={item._id}
item={item}
baseUrl={this.url}
/>
);
getMessages = () => realm.objects('messages').filtered('rid = $0', this.rid).sorted('ts', true)
renderSeparator = () => (
<View style={styles.separator} />
);
updateState = () => {
this.setState({
dataSource: this.getMessages()
});
};
submit = () => {
console.log(this.state.text);
@ -149,7 +100,19 @@ export default class RoomView extends React.Component {
...this.state,
text: ''
});
}
};
renderSeparator = () => (
<View style={styles.separator} />
);
renderItem = ({ item }) => (
<Message
id={item._id}
item={item}
baseUrl={this.url}
/>
);
render() {
return (
@ -172,7 +135,7 @@ export default class RoomView extends React.Component {
onSubmitEditing={this.submit}
autoFocus
placeholder='New message'
></TextInput>
/>
</View>
</KeyboardAvoidingView>
);

View File

@ -1,16 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import realm from './realm';
import { View, FlatList, StyleSheet } from 'react-native';
import realm from '../lib/realm';
import RoomItem from '../components/RoomItem';
const styles = StyleSheet.create({
roomItem: {
lineHeight: 18,
borderTopWidth: 2,
borderColor: '#aaa',
padding: 14
},
container: {
flex: 1
},
@ -22,25 +17,7 @@ const styles = StyleSheet.create({
}
});
class RoomItem extends React.PureComponent {
static propTypes = {
onPressItem: PropTypes.func.isRequired,
title: PropTypes.string.isRequired,
id: PropTypes.string.isRequired
}
_onPress = () => {
this.props.onPressItem(this.props.id);
};
render() {
return (
<Text onPress={this._onPress} style={styles.roomItem}>{ this.props.title }</Text>
);
}
}
export default class RoomsView extends React.Component {
export default class RoomsListView extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired
}
@ -53,10 +30,6 @@ export default class RoomsView extends React.Component {
};
}
componentWillMount() {
realm.addListener('change', () => this.setState(getState()));
}
_onPressItem = (id) => {
const { navigate } = this.props.navigation;
console.log('pressed', id);

View File

@ -1,10 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import Zeroconf from 'react-native-zeroconf';
import { H1, View, TouchableOpacity, Text, TextInput, SectionList, Button, StyleSheet } from 'react-native';
import { View, Text, SectionList, Button, StyleSheet } from 'react-native';
import realm from '../realm';
import { connect } from '../meteor';
import realm from '../lib/realm';
import { connect } from '../lib/meteor';
const styles = StyleSheet.create({
view: {
@ -53,12 +53,12 @@ export default class ListServerView extends React.Component {
navigation: PropTypes.object.isRequired
}
static navigationOptions = ({navigation}) => ({
static navigationOptions = ({ navigation }) => ({
title: 'Servers',
headerRight: (
<Button
title = "Add"
onPress = {() => navigation.navigate('NewServer')}
title='Add'
onPress={() => navigation.navigate('NewServer')}
/>
)
});
@ -78,16 +78,17 @@ export default class ListServerView extends React.Component {
}];
if (this.state.nearBy) {
const nearBy = Object.keys(this.state.nearBy).filter(key => this.state.nearBy[key].addresses);
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 }`
const address = `http://${ server.addresses[0] }:${ server.port }`;
return {
id: address
}
};
})
});
}
@ -108,7 +109,7 @@ export default class ListServerView extends React.Component {
const currentServer = realm.objects('servers').filtered('current = true')[0];
if (currentServer) {
connect(() => {
navigation.navigate('Login')
navigation.navigate('Login');
});
}
@ -121,12 +122,14 @@ export default class ListServerView extends React.Component {
realm.addListener('change', () => this.setState(getState()));
this.state = getState();
return null;
}
onPressItem(item) {
const { navigate } = this.props.navigation;
realm.write(() => {
realm.objects('servers').filtered('current = true').forEach(item => (item.current = false));
realm.objects('servers').filtered('current = true').forEach(server => (server.current = false));
realm.create('servers', { id: item.id, current: true }, true);
});
@ -138,7 +141,7 @@ export default class ListServerView extends React.Component {
renderItem = ({ item }) => (
<Text
style={styles.listItem}
onPress={() => {this.onPressItem(item)}}
onPress={() => { this.onPressItem(item); }}
>
{item.id}
</Text>
@ -160,11 +163,10 @@ export default class ListServerView extends React.Component {
sections={this.state.sections}
renderItem={this.renderItem}
renderSectionHeader={this.renderSectionHeader}
keyExtractor={(item) => item.id}
keyExtractor={item => item.id}
ItemSeparatorComponent={this.renderSeparator}
/>
</View>
);
}
}

View File

@ -1,11 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import Zeroconf from 'react-native-zeroconf';
import { View, Text, TextInput, Button, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
import { NavigationActions } from 'react-navigation'
import { TextInput, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
import realm from '../realm';
import { connect } from '../meteor';
import realm from '../lib/realm';
import { connect } from '../lib/meteor';
const styles = StyleSheet.create({
view: {
@ -28,14 +26,12 @@ const styles = StyleSheet.create({
}
});
const zeroconf = new Zeroconf();
export default class NewServerView extends React.Component {
static propTypes = {
navigation: PropTypes.object.isRequired
}
static navigationOptions = ({navigation}) => ({
static navigationOptions = () => ({
title: 'New Server Connection'
});
@ -69,7 +65,7 @@ export default class NewServerView extends React.Component {
});
connect(() => {
navigate('ListServer', {newServer: url});
navigate('ListServer', { newServer: url });
});
};
}

10
package-lock.json generated
View File

@ -1488,6 +1488,11 @@
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz",
"integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg="
},
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
},
"exec-sh": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.0.tgz",
@ -4192,6 +4197,11 @@
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-0.0.65.tgz",
"integrity": "sha1-toXqMIH/fJZIbNmXNhAmxAcwLFk="
},
"react-native-zeroconf": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/react-native-zeroconf/-/react-native-zeroconf-0.7.1.tgz",
"integrity": "sha1-zb+/JVCqcc89r4LYJnWI7+44uwE="
},
"react-navigation": {
"version": "1.0.0-beta.11",
"resolved": "https://registry.npmjs.org/react-navigation/-/react-navigation-1.0.0-beta.11.tgz",