diff --git a/app/containers/MessageActions.js b/app/containers/MessageActions.js index c56adaf13..c13ffba13 100644 --- a/app/containers/MessageActions.js +++ b/app/containers/MessageActions.js @@ -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 }); diff --git a/app/containers/message/index.js b/app/containers/message/index.js index da060ef56..7ab119870 100644 --- a/app/containers/message/index.js +++ b/app/containers/message/index.js @@ -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, diff --git a/app/views/RoomView/DateSeparator.js b/app/views/RoomView/DateSeparator.js new file mode 100644 index 000000000..5d26fe697 --- /dev/null +++ b/app/views/RoomView/DateSeparator.js @@ -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 ( + + + {text} + + + ); +}; + +DateSeparator.propTypes = { + ts: PropTypes.instanceOf(Date) +}; + +export default DateSeparator; diff --git a/app/views/RoomView/ListView.js b/app/views/RoomView/ListView.js index 385e7bcd4..3eacad9cb 100644 --- a/app/views/RoomView/ListView.js +++ b/app/views/RoomView/ListView.js @@ -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(); + } + if (this.props.lastOpen && + moment(data.ts).isAfter(this.props.lastOpen) && + moment(nextData.ts).isBefore(this.props.lastOpen) + ) { + bodyComponents.push(); + } + } // totalIndex += 1; rowCount += 1; if (rowCount === this.state.curRenderedRowsCount) { diff --git a/app/views/RoomView/UnreadSeparator.js b/app/views/RoomView/UnreadSeparator.js new file mode 100644 index 000000000..c2856e677 --- /dev/null +++ b/app/views/RoomView/UnreadSeparator.js @@ -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 = () => ( + + + unread messages + +); + +export default UnreadSeparator; diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 145cacf2d..8f754b8bd 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -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 = () => ; 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);