Unread separator and Date separator (#154)
This commit is contained in:
parent
0636fd0266
commit
d3acc17fc1
|
@ -75,7 +75,7 @@ export default class MessageActions extends React.Component {
|
||||||
};
|
};
|
||||||
this.handleActionPress = this.handleActionPress.bind(this);
|
this.handleActionPress = this.handleActionPress.bind(this);
|
||||||
this.options = [''];
|
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 roomRoles = Array.from(Object.keys(roles), i => roles[i].value);
|
||||||
const userRoles = this.props.user.roles || [];
|
const userRoles = this.props.user.roles || [];
|
||||||
this.mergedRoles = [...new Set([...roomRoles, ...userRoles])];
|
this.mergedRoles = [...new Set([...roomRoles, ...userRoles])];
|
||||||
|
@ -142,7 +142,7 @@ export default class MessageActions extends React.Component {
|
||||||
let msg = `[ ](${ nextProps.permalink }) `;
|
let msg = `[ ](${ nextProps.permalink }) `;
|
||||||
|
|
||||||
// if original message wasn't sent by current user and neither from a direct room
|
// 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 } `;
|
msg += `@${ this.props.actionMessage.u.username } `;
|
||||||
}
|
}
|
||||||
this.props.setInput({ msg });
|
this.props.setInput({ msg });
|
||||||
|
|
|
@ -20,7 +20,6 @@ import styles from './styles';
|
||||||
const avatar = { marginRight: 10 };
|
const avatar = { marginRight: 10 };
|
||||||
const flex = { flexDirection: 'row', flex: 1 };
|
const flex = { flexDirection: 'row', flex: 1 };
|
||||||
|
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
message: state.messages.message,
|
message: state.messages.message,
|
||||||
editing: state.messages.editing,
|
editing: state.messages.editing,
|
||||||
|
|
|
@ -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;
|
|
@ -2,6 +2,10 @@ import { ListView as OldList } from 'realm/react-native';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import cloneReferencedElement from 'react-clone-referenced-element';
|
import cloneReferencedElement from 'react-clone-referenced-element';
|
||||||
import { ScrollView, ListView as OldList2 } from 'react-native';
|
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;
|
const DEFAULT_SCROLL_CALLBACK_THROTTLE = 50;
|
||||||
|
|
||||||
|
@ -15,6 +19,10 @@ export class DataSource extends OldList.DataSource {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@connect(state => ({
|
||||||
|
lastOpen: state.room.lastOpen
|
||||||
|
}))
|
||||||
export class ListView extends OldList2 {
|
export class ListView extends OldList2 {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -92,6 +100,19 @@ export class ListView extends OldList2 {
|
||||||
rowID,
|
rowID,
|
||||||
this._onRowHighlighted,
|
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;
|
// totalIndex += 1;
|
||||||
rowCount += 1;
|
rowCount += 1;
|
||||||
if (rowCount === this.state.curRenderedRowsCount) {
|
if (rowCount === this.state.curRenderedRowsCount) {
|
||||||
|
|
|
@ -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;
|
|
@ -7,7 +7,7 @@ import equal from 'deep-equal';
|
||||||
|
|
||||||
import { ListView } from './ListView';
|
import { ListView } from './ListView';
|
||||||
import * as actions from '../../actions';
|
import * as actions from '../../actions';
|
||||||
import { openRoom } from '../../actions/room';
|
import { openRoom, setLastOpen } from '../../actions/room';
|
||||||
import { editCancel } from '../../actions/messages';
|
import { editCancel } from '../../actions/messages';
|
||||||
import database from '../../lib/realm';
|
import database from '../../lib/realm';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
@ -33,20 +33,20 @@ const typing = () => <Typing />;
|
||||||
Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
|
Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
Message_TimeFormat: state.settings.Message_TimeFormat,
|
Message_TimeFormat: state.settings.Message_TimeFormat,
|
||||||
loading: state.messages.isFetching,
|
loading: state.messages.isFetching,
|
||||||
user: state.login.user,
|
user: state.login.user
|
||||||
lastOpened: state.room.lastOpen
|
|
||||||
}),
|
}),
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
actions: bindActionCreators(actions, dispatch),
|
actions: bindActionCreators(actions, dispatch),
|
||||||
openRoom: room => dispatch(openRoom(room)),
|
openRoom: room => dispatch(openRoom(room)),
|
||||||
editCancel: () => dispatch(editCancel())
|
editCancel: () => dispatch(editCancel()),
|
||||||
|
setLastOpen: date => dispatch(setLastOpen(date))
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
export default class RoomView extends React.Component {
|
export default class RoomView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
// lastOpened: PropTypes.instanceOf(Date),
|
|
||||||
navigation: PropTypes.object.isRequired,
|
navigation: PropTypes.object.isRequired,
|
||||||
openRoom: PropTypes.func.isRequired,
|
openRoom: PropTypes.func.isRequired,
|
||||||
|
setLastOpen: PropTypes.func.isRequired,
|
||||||
user: PropTypes.object.isRequired,
|
user: PropTypes.object.isRequired,
|
||||||
editCancel: PropTypes.func,
|
editCancel: PropTypes.func,
|
||||||
rid: PropTypes.string,
|
rid: PropTypes.string,
|
||||||
|
@ -73,7 +73,7 @@ export default class RoomView extends React.Component {
|
||||||
.filtered('rid = $0', this.rid)
|
.filtered('rid = $0', this.rid)
|
||||||
.sorted('ts', true);
|
.sorted('ts', true);
|
||||||
const rowIds = this.data.map((row, index) => index);
|
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 = {
|
this.state = {
|
||||||
dataSource: ds.cloneWithRows(this.data, rowIds),
|
dataSource: ds.cloneWithRows(this.data, rowIds),
|
||||||
loaded: true,
|
loaded: true,
|
||||||
|
@ -85,7 +85,12 @@ export default class RoomView extends React.Component {
|
||||||
this.props.navigation.setParams({
|
this.props.navigation.setParams({
|
||||||
title: this.name
|
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);
|
this.data.addListener(this.updateState);
|
||||||
}
|
}
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
@ -129,7 +134,9 @@ export default class RoomView extends React.Component {
|
||||||
});
|
});
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
sendMessage = message => RocketChat.sendMessage(this.rid, message);
|
sendMessage = message => RocketChat.sendMessage(this.rid, message).then(() => {
|
||||||
|
this.props.setLastOpen(null);
|
||||||
|
});
|
||||||
|
|
||||||
joinRoom = async() => {
|
joinRoom = async() => {
|
||||||
await RocketChat.joinRoom(this.props.rid);
|
await RocketChat.joinRoom(this.props.rid);
|
||||||
|
|
Loading…
Reference in New Issue