listview
This commit is contained in:
parent
0e1cb6e5ed
commit
138546e4c9
|
@ -71,7 +71,6 @@ export default class Message extends React.PureComponent {
|
||||||
|
|
||||||
let initials = usernameParts.length > 1 ? usernameParts[0][0] + usernameParts[usernameParts.length - 1][0] : username.replace(/[^A-Za-z0-9]/g, '').substr(0, 2);
|
let initials = usernameParts.length > 1 ? usernameParts[0][0] + usernameParts[usernameParts.length - 1][0] : username.replace(/[^A-Za-z0-9]/g, '').substr(0, 2);
|
||||||
initials = initials.toUpperCase();
|
initials = initials.toUpperCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.message, extraStyle]}>
|
<View style={[styles.message, extraStyle]}>
|
||||||
<View style={[styles.avatarContainer, { backgroundColor: color }]}>
|
<View style={[styles.avatarContainer, { backgroundColor: color }]}>
|
||||||
|
|
|
@ -17,6 +17,7 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
textBoxInput: {
|
textBoxInput: {
|
||||||
height: 40,
|
height: 40,
|
||||||
|
alignSelf: 'stretch',
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
flexGrow: 1
|
flexGrow: 1
|
||||||
},
|
},
|
||||||
|
@ -44,14 +45,15 @@ export default class MessageBox extends React.PureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
submit = () => {
|
submit(message) {
|
||||||
if (this.state.text.trim() === '') {
|
// console.log(this.state);
|
||||||
|
const text = message;
|
||||||
|
this.setState({ text: '' });
|
||||||
|
if (text.trim() === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.props.onSubmit(text);
|
||||||
this.props.onSubmit(this.state.text);
|
}
|
||||||
this.setState({ text: '' });
|
|
||||||
};
|
|
||||||
|
|
||||||
addFile = () => {
|
addFile = () => {
|
||||||
const options = {
|
const options = {
|
||||||
|
@ -106,13 +108,15 @@ export default class MessageBox extends React.PureComponent {
|
||||||
<View style={styles.textBox}>
|
<View style={styles.textBox}>
|
||||||
<Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} />
|
<Icon style={styles.fileButton} name='add-circle-outline' onPress={this.addFile} />
|
||||||
<TextInput
|
<TextInput
|
||||||
|
ref={component => this.component = component}
|
||||||
style={styles.textBoxInput}
|
style={styles.textBoxInput}
|
||||||
value={this.state.text}
|
value={this.state.text}
|
||||||
onChangeText={text => this.setState({ text })}
|
onChangeText={text => this.setState({ text })}
|
||||||
returnKeyType='send'
|
returnKeyType='send'
|
||||||
onSubmitEditing={this.submit}
|
onSubmitEditing={event => this.submit(event.nativeEvent.text)}
|
||||||
blurOnSubmit={false}
|
blurOnSubmit={false}
|
||||||
placeholder='New message'
|
placeholder='New message'
|
||||||
|
underlineColorAndroid='transparent'
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,10 +35,10 @@ const subscriptionSchema = {
|
||||||
open: { type: 'bool', optional: true },
|
open: { type: 'bool', optional: true },
|
||||||
alert: { type: 'bool', optional: true },
|
alert: { type: 'bool', optional: true },
|
||||||
// roles: [ 'owner' ],
|
// roles: [ 'owner' ],
|
||||||
unread: { type: 'int', optional: true }
|
unread: { type: 'int', optional: true },
|
||||||
// userMentions: 0,
|
// userMentions: 0,
|
||||||
// groupMentions: 0,
|
// groupMentions: 0,
|
||||||
// _updatedAt: Fri Jul 28 2017 18:31:35 GMT-0300 (-03),
|
_updatedAt: { type: 'date', optional: true }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,11 +80,10 @@ const realm = new Realm({
|
||||||
export default realm;
|
export default realm;
|
||||||
|
|
||||||
// Clear settings
|
// Clear settings
|
||||||
realm.write(() => {
|
// realm.write(() => {
|
||||||
// const allSettins = realm.objects('settings');
|
// // const allSettins = realm.objects('settings');
|
||||||
// realm.delete(allSettins);
|
// // realm.delete(allSettins);
|
||||||
|
//
|
||||||
// realm.create('servers', { id: 'https://demo.rocket.chat', current: false }, true);
|
// // 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: 'http://localhost:3000', current: false }, true);
|
||||||
// realm.create('servers', { id: 'http://10.0.2.2:3000', current: false }, true);
|
// });
|
||||||
});
|
|
||||||
|
|
|
@ -1,9 +1,37 @@
|
||||||
import Meteor from 'react-native-meteor';
|
import Meteor from 'react-native-meteor';
|
||||||
import Random from 'react-native-meteor/lib/Random';
|
import Random from 'react-native-meteor/lib/Random';
|
||||||
import realm from './realm';
|
import realm from './realm';
|
||||||
|
import debounce from '../utils/debounce';
|
||||||
|
|
||||||
export { Accounts } from 'react-native-meteor';
|
export { Accounts } from 'react-native-meteor';
|
||||||
|
|
||||||
|
const call = (method, ...params) => new Promise((resolve, reject) => {
|
||||||
|
Meteor.call(method, ...params, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const write = (() => {
|
||||||
|
const cache = [];
|
||||||
|
const run = debounce(() => {
|
||||||
|
if (!cache.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
realm.write(() => {
|
||||||
|
cache.forEach(([name, obj]) => {
|
||||||
|
realm.create(name, obj, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// cache = [];
|
||||||
|
}, 1000);
|
||||||
|
return (name, obj) => {
|
||||||
|
cache.push([name, obj]);
|
||||||
|
run();
|
||||||
|
};
|
||||||
|
})();
|
||||||
const RocketChat = {
|
const RocketChat = {
|
||||||
|
|
||||||
createChannel({ name, users, type }) {
|
createChannel({ name, users, type }) {
|
||||||
|
@ -45,6 +73,7 @@ const RocketChat = {
|
||||||
if (typeof item.value === 'string') {
|
if (typeof item.value === 'string') {
|
||||||
setting.value = item.value;
|
setting.value = item.value;
|
||||||
}
|
}
|
||||||
|
// write('settings', setting);
|
||||||
realm.create('settings', setting, true);
|
realm.create('settings', setting, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -61,17 +90,36 @@ const RocketChat = {
|
||||||
const message = ddbMessage.fields.args[0];
|
const message = ddbMessage.fields.args[0];
|
||||||
message.temp = false;
|
message.temp = false;
|
||||||
message._server = { id: RocketChat.currentServer };
|
message._server = { id: RocketChat.currentServer };
|
||||||
|
// write('messages', message);
|
||||||
realm.create('messages', message, true);
|
realm.create('messages', message, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.subCache = this.subCache || {};
|
||||||
|
this.roomCache = this.roomCache || {};
|
||||||
|
this.cache = {};
|
||||||
if (ddbMessage.collection === 'stream-notify-user') {
|
if (ddbMessage.collection === 'stream-notify-user') {
|
||||||
console.log(ddbMessage);
|
|
||||||
realm.write(() => {
|
|
||||||
const data = ddbMessage.fields.args[1];
|
const data = ddbMessage.fields.args[1];
|
||||||
data._server = { id: RocketChat.currentServer };
|
let key;
|
||||||
realm.create('subscriptions', data, true);
|
if (ddbMessage.fields.eventName && ddbMessage.fields.eventName.indexOf('rooms-changed') > -1) {
|
||||||
});
|
this.roomCache[data._id] = data;
|
||||||
|
key = data._id;
|
||||||
|
} else {
|
||||||
|
this.subCache[data.rid] = data;
|
||||||
|
key = data.rid;
|
||||||
|
delete this.subCache[key]._updatedAt;
|
||||||
|
}
|
||||||
|
this.cache[key] = this.cache[key] ||
|
||||||
|
setTimeout(() => {
|
||||||
|
this.subCache[key] = this.subCache[key] || realm.objects('subscriptions').filtered('rid = $0', key).slice(0, 1)[0];
|
||||||
|
if (this.roomCache[key]) {
|
||||||
|
this.subCache[key]._updatedAt = this.roomCache[key]._updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
write('subscriptions', this.subCache[key]);
|
||||||
|
delete this.subCache[key];
|
||||||
|
delete this.roomCache[key];
|
||||||
|
delete this.cache[key];
|
||||||
|
}, 550);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -86,7 +134,7 @@ const RocketChat = {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
if (data.length) {
|
||||||
realm.write(() => {
|
realm.write(() => {
|
||||||
data.forEach((subscription) => {
|
data.forEach((subscription) => {
|
||||||
// const subscription = {
|
// const subscription = {
|
||||||
|
@ -96,9 +144,11 @@ const RocketChat = {
|
||||||
// subscription.value = item.value;
|
// subscription.value = item.value;
|
||||||
// }
|
// }
|
||||||
subscription._server = { id: RocketChat.currentServer };
|
subscription._server = { id: RocketChat.currentServer };
|
||||||
|
write('subscriptions', subscription);
|
||||||
realm.create('subscriptions', subscription, true);
|
realm.create('subscriptions', subscription, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return cb && cb();
|
return cb && cb();
|
||||||
});
|
});
|
||||||
|
@ -113,14 +163,16 @@ const RocketChat = {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (data.messages.length) {
|
||||||
realm.write(() => {
|
realm.write(() => {
|
||||||
data.messages.forEach((message) => {
|
data.messages.forEach((message) => {
|
||||||
message.temp = false;
|
message.temp = false;
|
||||||
message._server = { id: RocketChat.currentServer };
|
message._server = { id: RocketChat.currentServer };
|
||||||
|
// write('messages', message);
|
||||||
realm.create('messages', message, true);
|
realm.create('messages', message, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
if (data.messages.length < 20) {
|
if (data.messages.length < 20) {
|
||||||
|
@ -139,6 +191,19 @@ const RocketChat = {
|
||||||
const user = Meteor.user();
|
const user = Meteor.user();
|
||||||
|
|
||||||
realm.write(() => {
|
realm.write(() => {
|
||||||
|
// write('messages', {
|
||||||
|
// _id,
|
||||||
|
// rid,
|
||||||
|
// msg,
|
||||||
|
// ts: new Date(),
|
||||||
|
// _updatedAt: new Date(),
|
||||||
|
// temp: true,
|
||||||
|
// _server: { id: RocketChat.currentServer },
|
||||||
|
// u: {
|
||||||
|
// _id: user._id,
|
||||||
|
// username: user.username
|
||||||
|
// }
|
||||||
|
// });
|
||||||
realm.create('messages', {
|
realm.create('messages', {
|
||||||
_id,
|
_id,
|
||||||
rid,
|
rid,
|
||||||
|
@ -185,7 +250,9 @@ const RocketChat = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
readMessages(rid) {
|
||||||
|
return call('readMessages', rid);
|
||||||
|
},
|
||||||
joinRoom(rid) {
|
joinRoom(rid) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Meteor.call('joinRoom', rid, (error, result) => {
|
Meteor.call('joinRoom', rid, (error, result) => {
|
||||||
|
@ -252,13 +319,14 @@ const RocketChat = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RocketChat;
|
export default RocketChat;
|
||||||
|
|
||||||
Meteor.Accounts.onLogin(() => {
|
Meteor.Accounts.onLogin(() => {
|
||||||
Meteor.call('subscriptions/get', (err, data) => {
|
Promise.all([call('subscriptions/get'), call('rooms/get')]).then(([subscriptions, rooms]) => {
|
||||||
if (err) {
|
subscriptions = subscriptions.sort((s1, s2) => (s1.rid > s2.rid ? 1 : -1));
|
||||||
console.error(err);
|
rooms = rooms.sort((s1, s2) => (s1._id > s2._id ? 1 : -1));
|
||||||
}
|
const data = subscriptions.map((subscription, index) => {
|
||||||
|
subscription._updatedAt = rooms[index]._updatedAt;
|
||||||
|
return subscription;
|
||||||
|
});
|
||||||
realm.write(() => {
|
realm.write(() => {
|
||||||
data.forEach((subscription) => {
|
data.forEach((subscription) => {
|
||||||
// const subscription = {
|
// const subscription = {
|
||||||
|
@ -268,9 +336,13 @@ Meteor.Accounts.onLogin(() => {
|
||||||
// subscription.value = item.value;
|
// subscription.value = item.value;
|
||||||
// }
|
// }
|
||||||
subscription._server = { id: RocketChat.currentServer };
|
subscription._server = { id: RocketChat.currentServer };
|
||||||
|
// write('subscriptions', subscription);
|
||||||
realm.create('subscriptions', subscription, true);
|
realm.create('subscriptions', subscription, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}).then(() => {
|
||||||
Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/subscriptions-changed`, false);
|
Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/subscriptions-changed`, false);
|
||||||
|
Meteor.subscribe('stream-notify-user', `${ Meteor.userId() }/rooms-changed`, false);
|
||||||
|
console.log('subscriptions done.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -61,6 +61,6 @@ export default new StackNavigator({
|
||||||
initialRouteName: 'Main',
|
initialRouteName: 'Main',
|
||||||
cardStyle: {
|
cardStyle: {
|
||||||
backgroundColor: '#fff'
|
backgroundColor: '#fff'
|
||||||
},
|
}
|
||||||
mode: 'modal'
|
// mode: 'modal'
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
export default function debounce(func, wait, immediate) {
|
||||||
|
let timeout;
|
||||||
|
return function _debounce(...args) {
|
||||||
|
const context = this;
|
||||||
|
const later = function __debounce() {
|
||||||
|
timeout = null;
|
||||||
|
if (!immediate) { func.apply(context, args); }
|
||||||
|
};
|
||||||
|
const callNow = immediate && !timeout;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
if (callNow) { func.apply(context, args); }
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
export default function throttle(fn, threshhold = 250, scope) {
|
||||||
|
let last,
|
||||||
|
deferTimer;
|
||||||
|
return function() {
|
||||||
|
const context = scope || this;
|
||||||
|
|
||||||
|
let now = +new Date(),
|
||||||
|
args = arguments;
|
||||||
|
if (last && now < last + threshhold) {
|
||||||
|
// hold on to it
|
||||||
|
clearTimeout(deferTimer);
|
||||||
|
deferTimer = setTimeout(() => {
|
||||||
|
last = now;
|
||||||
|
fn.apply(context, args);
|
||||||
|
}, threshhold);
|
||||||
|
} else {
|
||||||
|
last = now;
|
||||||
|
fn.apply(context, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Text, View, FlatList, StyleSheet, Button } from 'react-native';
|
import { Text, View, StyleSheet, Button } from 'react-native';
|
||||||
|
import { ListView } from 'realm/react-native';
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import debounce from '../utils/throttle';
|
||||||
import Message from '../components/Message';
|
import Message from '../components/Message';
|
||||||
import MessageBox from '../components/MessageBox';
|
import MessageBox from '../components/MessageBox';
|
||||||
import KeyboardView from '../components/KeyboardView';
|
// import KeyboardView from '../components/KeyboardView';
|
||||||
|
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1
|
flex: 1
|
||||||
|
@ -45,17 +46,18 @@ export default class RoomView extends React.Component {
|
||||||
title: navigation.state.params.name || realm.objectForPrimaryKey('subscriptions', navigation.state.params.sid).name
|
title: navigation.state.params.name || realm.objectForPrimaryKey('subscriptions', navigation.state.params.sid).name
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.rid = props.navigation.state.params.rid || realm.objectForPrimaryKey('subscriptions', props.navigation.state.params.sid).rid;
|
this.rid = props.navigation.state.params.rid || realm.objectForPrimaryKey('subscriptions', props.navigation.state.params.sid).rid;
|
||||||
// this.rid = 'GENERAL';
|
// this.rid = 'GENERAL';
|
||||||
|
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', RocketChat.currentServer, this.rid).sorted('ts', true);
|
||||||
this.state = {
|
this.state = {
|
||||||
dataSource: [],
|
dataSource: ds.cloneWithRows(this.data.slice(0, 10)),
|
||||||
loaded: true,
|
loaded: true,
|
||||||
joined: typeof props.navigation.state.params.rid === 'undefined'
|
joined: typeof props.navigation.state.params.rid === 'undefined'
|
||||||
};
|
};
|
||||||
|
// console.log(this.messages);
|
||||||
this.url = realm.objectForPrimaryKey('settings', 'Site_Url').value;
|
this.url = realm.objectForPrimaryKey('settings', 'Site_Url').value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,16 +70,13 @@ export default class RoomView extends React.Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
loaded: true
|
loaded: true
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
this.data = realm.objects('messages').filtered('_server.id = $0 AND rid = $1', RocketChat.currentServer, this.rid).sorted('ts', true);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
dataSource: this.data
|
|
||||||
});
|
|
||||||
this.data.addListener(this.updateState);
|
this.data.addListener(this.updateState);
|
||||||
|
});
|
||||||
|
this.updateState();
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
return RocketChat.readMessages(this.rid);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.data.removeListener(this.updateState);
|
this.data.removeListener(this.updateState);
|
||||||
}
|
}
|
||||||
|
@ -85,12 +84,12 @@ export default class RoomView extends React.Component {
|
||||||
onEndReached = () => {
|
onEndReached = () => {
|
||||||
if (this.state.dataSource.length && this.state.loaded && this.state.loadingMore !== true && this.state.end !== true) {
|
if (this.state.dataSource.length && this.state.loaded && this.state.loadingMore !== true && this.state.end !== true) {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
// ...this.state,
|
||||||
loadingMore: true
|
loadingMore: true
|
||||||
});
|
});
|
||||||
RocketChat.loadMessagesForRoom(this.rid, this.state.dataSource[this.state.dataSource.length - 1].ts, ({ end }) => {
|
RocketChat.loadMessagesForRoom(this.rid, this.state.dataSource[this.state.dataSource.length - 1].ts, ({ end }) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
// ...this.state,
|
||||||
loadingMore: false,
|
loadingMore: false,
|
||||||
end
|
end
|
||||||
});
|
});
|
||||||
|
@ -98,11 +97,15 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateState = (data) => {
|
updateState = debounce(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
dataSource: data
|
dataSource: ds.cloneWithRows(this.data)
|
||||||
});
|
});
|
||||||
};
|
// RocketChat.readMessages(this.rid);
|
||||||
|
// this.setState({
|
||||||
|
// messages: this.messages
|
||||||
|
// });
|
||||||
|
}, 100);
|
||||||
|
|
||||||
sendMessage = message => RocketChat.sendMessage(this.rid, message);
|
sendMessage = message => RocketChat.sendMessage(this.rid, message);
|
||||||
|
|
||||||
|
@ -148,6 +151,7 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<MessageBox
|
<MessageBox
|
||||||
|
ref={box => this.box = box}
|
||||||
onSubmit={this.sendMessage}
|
onSubmit={this.sendMessage}
|
||||||
rid={this.rid}
|
rid={this.rid}
|
||||||
/>
|
/>
|
||||||
|
@ -165,22 +169,24 @@ export default class RoomView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
// data={this.state.dataSource}
|
||||||
|
// extraData={this.state}
|
||||||
|
// renderItem={this.renderItem}
|
||||||
|
// keyExtractor={item => item._id}
|
||||||
|
//
|
||||||
return (
|
return (
|
||||||
<KeyboardView style={styles.container} keyboardVerticalOffset={64}>
|
<View style={styles.container}>
|
||||||
{this.renderBanner()}
|
{this.renderBanner()}
|
||||||
<FlatList
|
<ListView
|
||||||
ref={ref => this.listView = ref}
|
|
||||||
style={styles.list}
|
style={styles.list}
|
||||||
data={this.state.dataSource}
|
|
||||||
extraData={this.state}
|
|
||||||
renderItem={this.renderItem}
|
|
||||||
keyExtractor={item => item._id}
|
|
||||||
onEndReached={this.onEndReached}
|
|
||||||
onEndReachedThreshold={0.1}
|
onEndReachedThreshold={0.1}
|
||||||
ListFooterComponent={this.renderHeader()}
|
ListFooterComponent={this.renderHeader()}
|
||||||
|
onEndReached={this.onEndReached}
|
||||||
|
dataSource={this.state.dataSource}
|
||||||
|
renderRow={item => this.renderItem({ item })}
|
||||||
/>
|
/>
|
||||||
{this.renderFooter()}
|
{this.renderFooter()}
|
||||||
</KeyboardView>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import ActionButton from 'react-native-action-button';
|
import ActionButton from 'react-native-action-button';
|
||||||
|
import { ListView } from 'realm/react-native';
|
||||||
import Icon from 'react-native-vector-icons/Ionicons';
|
import Icon from 'react-native-vector-icons/Ionicons';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Button, Text, View, FlatList, StyleSheet, TouchableOpacity, Platform, TextInput } from 'react-native';
|
import { Button, Text, View, StyleSheet, TouchableOpacity, Platform, TextInput } from 'react-native';
|
||||||
import Meteor from 'react-native-meteor';
|
import Meteor from 'react-native-meteor';
|
||||||
import realm from '../lib/realm';
|
import realm from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import RoomItem from '../components/RoomItem';
|
import RoomItem from '../components/RoomItem';
|
||||||
|
import debounce from '../utils/debounce';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -72,6 +74,28 @@ Meteor.Accounts.onLogin(() => {
|
||||||
console.log('onLogin');
|
console.log('onLogin');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
|
||||||
|
class RoomsListItem extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
item: PropTypes.object.isRequired,
|
||||||
|
onPress: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
_onPress = (...args) => {
|
||||||
|
this.props.onPress(...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { item } = this.props;
|
||||||
|
return (
|
||||||
|
<TouchableOpacity key={item._id} onPress={() => this.props.onPress(item._id, item)}>
|
||||||
|
<RoomItem
|
||||||
|
id={item._id}
|
||||||
|
item={item}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
export default class RoomsListView extends React.Component {
|
export default class RoomsListView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigation: PropTypes.object.isRequired
|
navigation: PropTypes.object.isRequired
|
||||||
|
@ -95,9 +119,9 @@ export default class RoomsListView extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.data = realm.objects('subscriptions').filtered('_server.id = $0', RocketChat.currentServer).sorted('_updatedAt', true);
|
||||||
this.state = {
|
this.state = {
|
||||||
dataSource: [],
|
dataSource: ds.cloneWithRows(this.data.sorted('_updatedAt', true).slice(0, 10)),
|
||||||
searching: false,
|
searching: false,
|
||||||
searchDataSource: [],
|
searchDataSource: [],
|
||||||
searchText: ''
|
searchText: ''
|
||||||
|
@ -168,40 +192,23 @@ export default class RoomsListView extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInitialData = () => {
|
setInitialData = () => {
|
||||||
if (this.data) {
|
if (this.data) {
|
||||||
this.data.removeListener(this.updateState);
|
this.data.removeListener(this.updateState);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data = realm.objects('subscriptions').filtered('_server.id = $0', RocketChat.currentServer).sorted('name');
|
|
||||||
|
|
||||||
this.data.addListener(this.updateState);
|
this.data.addListener(this.updateState);
|
||||||
|
|
||||||
|
this.updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSubscriptions = () => this.data.sorted('_updatedAt', true)
|
||||||
|
|
||||||
|
updateState = debounce(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
dataSource: this.sort(this.data)
|
dataSource: ds.cloneWithRows(this.data)
|
||||||
});
|
});
|
||||||
}
|
}, 500);
|
||||||
|
|
||||||
sort = (data) => {
|
|
||||||
return data.slice().sort((a, b) => {
|
|
||||||
if (a.unread < b.unread) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.unread > b.unread) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateState = (data) => {
|
|
||||||
this.setState({
|
|
||||||
dataSource: this.sort(data)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPressItem = (id, item = {}) => {
|
_onPressItem = (id, item = {}) => {
|
||||||
const { navigate } = this.props.navigation;
|
const { navigate } = this.props.navigation;
|
||||||
|
@ -222,8 +229,8 @@ export default class RoomsListView extends React.Component {
|
||||||
.then(subs => navigate('Room', { sid: subs[0]._id }))
|
.then(subs => navigate('Room', { sid: subs[0]._id }))
|
||||||
.then(() => clearSearch());
|
.then(() => clearSearch());
|
||||||
} else {
|
} else {
|
||||||
navigate('Room', { rid: item._id, name: item.name });
|
|
||||||
clearSearch();
|
clearSearch();
|
||||||
|
navigate('Room', { rid: item._id, name: item.name });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -256,12 +263,7 @@ export default class RoomsListView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem = ({ item }) => (
|
renderItem = ({ item }) => (
|
||||||
<TouchableOpacity onPress={() => this._onPressItem(item._id, item)}>
|
<RoomsListItem item={item} onPress={() => this._onPressItem(item._id, item)} />
|
||||||
<RoomItem
|
|
||||||
id={item._id}
|
|
||||||
item={item}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
renderSeparator = () => (
|
renderSeparator = () => (
|
||||||
|
@ -282,25 +284,25 @@ export default class RoomsListView extends React.Component {
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
renderList = () => {
|
// if (!this.state.searching && !this.state.dataSource.length) {
|
||||||
if (!this.state.searching && !this.state.dataSource.length) {
|
// return (
|
||||||
return (
|
// <View style={styles.emptyView}>
|
||||||
<View style={styles.emptyView}>
|
// <Text style={styles.emptyText}>No rooms</Text>
|
||||||
<Text style={styles.emptyText}>No rooms</Text>
|
// </View>
|
||||||
</View>
|
// );
|
||||||
);
|
// }
|
||||||
}
|
renderList = () => (
|
||||||
|
// data={this.state.searching ? this.state.searchDataSource : this.state.dataSource}
|
||||||
return (
|
// keyExtractor={item => item._id}
|
||||||
<FlatList
|
// ItemSeparatorComponent={this.renderSeparator}
|
||||||
|
// renderItem={this.renderItem}
|
||||||
|
<ListView
|
||||||
|
dataSource={this.state.dataSource}
|
||||||
style={styles.list}
|
style={styles.list}
|
||||||
data={this.state.searching ? this.state.searchDataSource : this.state.dataSource}
|
renderRow={item => this.renderItem({ item })}
|
||||||
renderItem={this.renderItem}
|
|
||||||
keyExtractor={item => item._id}
|
|
||||||
ItemSeparatorComponent={this.renderSeparator}
|
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
|
||||||
renderCreateButtons() {
|
renderCreateButtons() {
|
||||||
return (
|
return (
|
||||||
<ActionButton buttonColor='rgba(231,76,60,1)'>
|
<ActionButton buttonColor='rgba(231,76,60,1)'>
|
||||||
|
|
|
@ -3683,6 +3683,26 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-native-action-button/-/react-native-action-button-2.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-action-button/-/react-native-action-button-2.7.2.tgz",
|
||||||
"integrity": "sha1-BvEYjo/h0Y0D/JBg1LYEybgbtso="
|
"integrity": "sha1-BvEYjo/h0Y0D/JBg1LYEybgbtso="
|
||||||
},
|
},
|
||||||
|
"react-native-auto-grow-textinput": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-auto-grow-textinput/-/react-native-auto-grow-textinput-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-O+mT2GOrDRzJdg2GbdfuGlO/nn/J8c9pdBCPahLYA8yiAjayAG67XOujGrfuv/wNCF7W94NsYdyfaf2hlOIhYQ=="
|
||||||
|
},
|
||||||
|
"react-native-autogrow-input": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-autogrow-input/-/react-native-autogrow-input-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-vWcfqGqzDw4XqRJr4HnHC+dcGAfJDYZiF2B0tBZjtjA6MNSv2TNz5knYZjvLggRgmEflj02r88scvfFputsRig=="
|
||||||
|
},
|
||||||
|
"react-native-autogrow-textinput": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-autogrow-textinput/-/react-native-autogrow-textinput-4.1.0.tgz",
|
||||||
|
"integrity": "sha1-p+WxfrPBarCOMbv7iNkkiO2H8nY="
|
||||||
|
},
|
||||||
|
"react-native-console-time-polyfill": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-console-time-polyfill/-/react-native-console-time-polyfill-0.0.6.tgz",
|
||||||
|
"integrity": "sha1-eCPYb+g0OcdEgNGxJKkrGnhXGIk="
|
||||||
|
},
|
||||||
"react-native-dismiss-keyboard": {
|
"react-native-dismiss-keyboard": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz",
|
||||||
|
@ -3718,6 +3738,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-native-form-generator/-/react-native-form-generator-0.9.9.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-form-generator/-/react-native-form-generator-0.9.9.tgz",
|
||||||
"integrity": "sha1-aKribR6Nw+MAc8zXuymPvf3OG8o="
|
"integrity": "sha1-aKribR6Nw+MAc8zXuymPvf3OG8o="
|
||||||
},
|
},
|
||||||
|
"react-native-image-picker": {
|
||||||
|
"version": "0.26.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.3.tgz",
|
||||||
|
"integrity": "sha1-CtLu3klQGnBG2ARqc4E2llOcPc0="
|
||||||
|
},
|
||||||
"react-native-img-cache": {
|
"react-native-img-cache": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-img-cache/-/react-native-img-cache-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-img-cache/-/react-native-img-cache-1.4.0.tgz",
|
||||||
|
@ -3735,6 +3760,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/react-native-meteor/-/react-native-meteor-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-meteor/-/react-native-meteor-1.1.0.tgz",
|
||||||
"integrity": "sha1-Vake/i1GbTqMzrW1QZeZru3NZ1Y="
|
"integrity": "sha1-Vake/i1GbTqMzrW1QZeZru3NZ1Y="
|
||||||
},
|
},
|
||||||
|
"react-native-optimized-flatlist": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-optimized-flatlist/-/react-native-optimized-flatlist-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-2+6C8gi0i+8jxssm8dXzrFjmdbI="
|
||||||
|
},
|
||||||
"react-native-svg": {
|
"react-native-svg": {
|
||||||
"version": "5.4.1",
|
"version": "5.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-5.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-5.4.1.tgz",
|
||||||
|
|
|
@ -16,12 +16,17 @@
|
||||||
"react-emojione": "^3.1.10",
|
"react-emojione": "^3.1.10",
|
||||||
"react-native": "0.46.1",
|
"react-native": "0.46.1",
|
||||||
"react-native-action-button": "^2.7.2",
|
"react-native-action-button": "^2.7.2",
|
||||||
|
"react-native-auto-grow-textinput": "^1.2.0",
|
||||||
|
"react-native-autogrow-input": "^0.2.1",
|
||||||
|
"react-native-autogrow-textinput": "^4.1.0",
|
||||||
|
"react-native-console-time-polyfill": "0.0.6",
|
||||||
"react-native-easy-markdown": "git+https://github.com/lappalj4/react-native-easy-markdown.git",
|
"react-native-easy-markdown": "git+https://github.com/lappalj4/react-native-easy-markdown.git",
|
||||||
"react-native-fetch-blob": "^0.10.8",
|
"react-native-fetch-blob": "^0.10.8",
|
||||||
"react-native-form-generator": "^0.9.9",
|
"react-native-form-generator": "^0.9.9",
|
||||||
"react-native-image-picker": "^0.26.3",
|
"react-native-image-picker": "^0.26.3",
|
||||||
"react-native-img-cache": "^1.4.0",
|
"react-native-img-cache": "^1.4.0",
|
||||||
"react-native-meteor": "^1.1.0",
|
"react-native-meteor": "^1.1.0",
|
||||||
|
"react-native-optimized-flatlist": "^1.0.1",
|
||||||
"react-native-svg": "^5.4.1",
|
"react-native-svg": "^5.4.1",
|
||||||
"react-native-svg-image": "^1.1.4",
|
"react-native-svg-image": "^1.1.4",
|
||||||
"react-native-vector-icons": "^4.3.0",
|
"react-native-vector-icons": "^4.3.0",
|
||||||
|
|
Loading…
Reference in New Issue