Unread separator and Date separator (#154)

This commit is contained in:
Diego Mello 2018-01-16 18:27:57 -02:00 committed by Guilherme Gazzo
parent 0636fd0266
commit d3acc17fc1
6 changed files with 112 additions and 11 deletions

View File

@ -75,7 +75,7 @@ export default class MessageActions extends React.Component {
};
this.handleActionPress = this.handleActionPress.bind(this);
this.options = [''];
const { roles } = this.props.room[0];
const { roles } = this.props.room;
const roomRoles = Array.from(Object.keys(roles), i => roles[i].value);
const userRoles = this.props.user.roles || [];
this.mergedRoles = [...new Set([...roomRoles, ...userRoles])];
@ -142,7 +142,7 @@ export default class MessageActions extends React.Component {
let msg = `[ ](${ nextProps.permalink }) `;
// if original message wasn't sent by current user and neither from a direct room
if (this.props.user.username !== this.props.actionMessage.u.username && this.props.room[0].t !== 'd') {
if (this.props.user.username !== this.props.actionMessage.u.username && this.props.room.t !== 'd') {
msg += `@${ this.props.actionMessage.u.username } `;
}
this.props.setInput({ msg });

View File

@ -20,7 +20,6 @@ import styles from './styles';
const avatar = { marginRight: 10 };
const flex = { flexDirection: 'row', flex: 1 };
@connect(state => ({
message: state.messages.message,
editing: state.messages.editing,

View File

@ -0,0 +1,42 @@
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
import PropTypes from 'prop-types';
import moment from 'moment';
const styles = StyleSheet.create({
dateSeparator: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginVertical: 5
},
dateSeparatorLine: {
borderTopColor: '#eaeaea',
borderTopWidth: StyleSheet.hairlineWidth,
flex: 1
},
dateSeparatorBadge: {
color: '#444444',
backgroundColor: '#fff',
fontSize: 11,
paddingHorizontal: 10,
transform: [{ scaleY: -1 }]
}
});
const DateSeparator = ({ ts }) => {
const text = moment(ts).format('MMMM DD, YYYY');
return (
<View style={styles.dateSeparator}>
<View style={styles.dateSeparatorLine} />
<Text style={styles.dateSeparatorBadge}>{text}</Text>
<View style={styles.dateSeparatorLine} />
</View>
);
};
DateSeparator.propTypes = {
ts: PropTypes.instanceOf(Date)
};
export default DateSeparator;

View File

@ -2,6 +2,10 @@ import { ListView as OldList } from 'realm/react-native';
import React from 'react';
import cloneReferencedElement from 'react-clone-referenced-element';
import { ScrollView, ListView as OldList2 } from 'react-native';
import moment from 'moment';
import { connect } from 'react-redux';
import DateSeparator from './DateSeparator';
import UnreadSeparator from './UnreadSeparator';
const DEFAULT_SCROLL_CALLBACK_THROTTLE = 50;
@ -15,6 +19,10 @@ export class DataSource extends OldList.DataSource {
return false;
}
}
@connect(state => ({
lastOpen: state.room.lastOpen
}))
export class ListView extends OldList2 {
constructor(props) {
super(props);
@ -92,6 +100,19 @@ export class ListView extends OldList2 {
rowID,
this._onRowHighlighted,
)());
if (rowIdx !== rowIDs.length - 1) {
const nextRowID = rowIDs[rowIdx + 1];
const nextData = dataSource._dataBlob[sectionID][nextRowID];
if (!moment(data.ts).isSame(nextData.ts, 'day')) {
bodyComponents.push(<DateSeparator key={data.ts.toISOString()} ts={data.ts} />);
}
if (this.props.lastOpen &&
moment(data.ts).isAfter(this.props.lastOpen) &&
moment(nextData.ts).isBefore(this.props.lastOpen)
) {
bodyComponents.push(<UnreadSeparator key='unread-separator' />);
}
}
// totalIndex += 1;
rowCount += 1;
if (rowCount === this.state.curRenderedRowsCount) {

View File

@ -0,0 +1,32 @@
import React from 'react';
import { View, StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
firstUnread: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginVertical: 5
},
firstUnreadLine: {
borderTopColor: 'red',
borderTopWidth: StyleSheet.hairlineWidth,
flex: 1
},
firstUnreadBadge: {
color: 'red',
backgroundColor: '#fff',
fontSize: 11,
paddingHorizontal: 10,
transform: [{ scaleY: -1 }]
}
});
const UnreadSeparator = () => (
<View style={styles.firstUnread}>
<View style={styles.firstUnreadLine} />
<Text style={styles.firstUnreadBadge}>unread messages</Text>
</View>
);
export default UnreadSeparator;

View File

@ -7,7 +7,7 @@ import equal from 'deep-equal';
import { ListView } from './ListView';
import * as actions from '../../actions';
import { openRoom } from '../../actions/room';
import { openRoom, setLastOpen } from '../../actions/room';
import { editCancel } from '../../actions/messages';
import database from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
@ -33,20 +33,20 @@ const typing = () => <Typing />;
Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
Message_TimeFormat: state.settings.Message_TimeFormat,
loading: state.messages.isFetching,
user: state.login.user,
lastOpened: state.room.lastOpen
user: state.login.user
}),
dispatch => ({
actions: bindActionCreators(actions, dispatch),
openRoom: room => dispatch(openRoom(room)),
editCancel: () => dispatch(editCancel())
editCancel: () => dispatch(editCancel()),
setLastOpen: date => dispatch(setLastOpen(date))
})
)
export default class RoomView extends React.Component {
static propTypes = {
// lastOpened: PropTypes.instanceOf(Date),
navigation: PropTypes.object.isRequired,
openRoom: PropTypes.func.isRequired,
setLastOpen: PropTypes.func.isRequired,
user: PropTypes.object.isRequired,
editCancel: PropTypes.func,
rid: PropTypes.string,
@ -73,7 +73,7 @@ export default class RoomView extends React.Component {
.filtered('rid = $0', this.rid)
.sorted('ts', true);
const rowIds = this.data.map((row, index) => index);
this.room = database.objects('subscriptions').filtered('rid = $0', this.rid);
[this.room] = database.objects('subscriptions').filtered('rid = $0', this.rid);
this.state = {
dataSource: ds.cloneWithRows(this.data, rowIds),
loaded: true,
@ -85,7 +85,12 @@ export default class RoomView extends React.Component {
this.props.navigation.setParams({
title: this.name
});
this.props.openRoom({ rid: this.rid, name: this.name });
this.props.openRoom({ rid: this.rid, name: this.name, ls: this.room.ls });
if (this.room.alert || this.room.unread || this.room.userMentions) {
this.props.setLastOpen(this.room.ls);
} else {
this.props.setLastOpen(null);
}
this.data.addListener(this.updateState);
}
shouldComponentUpdate(nextProps, nextState) {
@ -129,7 +134,9 @@ export default class RoomView extends React.Component {
});
}, 50);
sendMessage = message => RocketChat.sendMessage(this.rid, message);
sendMessage = message => RocketChat.sendMessage(this.rid, message).then(() => {
this.props.setLastOpen(null);
});
joinRoom = async() => {
await RocketChat.joinRoom(this.props.rid);