From 22cbcf0b4081b427f6f63b69b680be4f44a0b22f Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Fri, 1 Jun 2018 14:56:59 -0300 Subject: [PATCH] Unread and date separator layout improved (#319) @RocketChat/ReactNative - [x] Unread and date separator layout - [x] "Start of conversation"/"Loading messages" label ![screen shot 2018-05-30 at 18 10 43](https://user-images.githubusercontent.com/804994/40747867-0424964a-6435-11e8-9293-31cc43c110ab.png) ![screen shot 2018-05-30 at 18 09 05](https://user-images.githubusercontent.com/804994/40747868-04484784-6435-11e8-8c31-92e0776276f0.png) --- app/lib/methods/loadMessagesForRoom.js | 19 ++------ app/views/RoomView/DateSeparator.js | 42 ---------------- app/views/RoomView/ListView.js | 23 +++++---- app/views/RoomView/Separator.js | 66 ++++++++++++++++++++++++++ app/views/RoomView/UnreadSeparator.js | 38 --------------- app/views/RoomView/index.js | 20 ++++---- 6 files changed, 90 insertions(+), 118 deletions(-) delete mode 100644 app/views/RoomView/DateSeparator.js create mode 100644 app/views/RoomView/Separator.js delete mode 100644 app/views/RoomView/UnreadSeparator.js diff --git a/app/lib/methods/loadMessagesForRoom.js b/app/lib/methods/loadMessagesForRoom.js index 5a5bf69c8..368379514 100644 --- a/app/lib/methods/loadMessagesForRoom.js +++ b/app/lib/methods/loadMessagesForRoom.js @@ -29,20 +29,6 @@ async function loadMessagesForRoomDDP(...args) { console.warn('loadMessagesForRoomDDP', e); return loadMessagesForRoomRest.call(this, ...args); } - - // } - // if (cb) { - // cb({ end: data && data.messages.length < 20 }); - // } - // return data.message; - // }, (err) => { - // if (err) { - // if (cb) { - // cb({ end: true }); - // } - // return Promise.reject(err); - // } - // }); } export default async function loadMessagesForRoom(...args) { @@ -52,13 +38,14 @@ export default async function loadMessagesForRoom(...args) { try { // eslint-disable-next-line const data = (await (false && this.ddp.status ? loadMessagesForRoomDDP.call(this, ...args) : loadMessagesForRoomRest.call(this, ...args))).map(buildMessage); - if (data) { + if (data && data.length) { InteractionManager.runAfterInteractions(() => { db.write(() => data.forEach(message => db.create('messages', message, true))); return resolve(data); }); + } else { + return resolve([]); } - return resolve([]); } catch (e) { log('loadMessagesForRoom', e); reject(e); diff --git a/app/views/RoomView/DateSeparator.js b/app/views/RoomView/DateSeparator.js deleted file mode 100644 index 68e2cb814..000000000 --- a/app/views/RoomView/DateSeparator.js +++ /dev/null @@ -1,42 +0,0 @@ -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 62801cbb0..a9036a6ef 100644 --- a/app/views/RoomView/ListView.js +++ b/app/views/RoomView/ListView.js @@ -6,8 +6,7 @@ import moment from 'moment'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; -import DateSeparator from './DateSeparator'; -import UnreadSeparator from './UnreadSeparator'; +import Separator from './Separator'; import styles from './styles'; import Typing from '../../containers/Typing'; import database from '../../lib/realm'; @@ -72,7 +71,7 @@ export class List extends React.Component { onEndReachedThreshold={100} renderFooter={this.props.renderFooter} renderHeader={() => } - onEndReached={() => this.props.onEndReached(this.data)} + onEndReached={() => this.props.onEndReached(this.data[this.data.length - 1])} dataSource={this.dataSource} renderRow={(item, previousItem) => this.props.renderRow(item, previousItem)} initialListSize={20} @@ -128,17 +127,21 @@ export class ListView extends OldList2 { if (!previousMessage) { + bodyComponents.push(); continue; // eslint-disable-line } - if (this.props.lastOpen && + const showUnreadSeparator = this.props.lastOpen && moment(message.ts).isAfter(this.props.lastOpen) && - moment(previousMessage.ts).isBefore(this.props.lastOpen) - ) { - bodyComponents.push(); - } - if (!moment(message.ts).isSame(previousMessage.ts, 'day')) { - bodyComponents.push(); + moment(previousMessage.ts).isBefore(this.props.lastOpen); + const showDateSeparator = !moment(message.ts).isSame(previousMessage.ts, 'day'); + + if (showUnreadSeparator || showDateSeparator) { + bodyComponents.push(); } } diff --git a/app/views/RoomView/Separator.js b/app/views/RoomView/Separator.js new file mode 100644 index 000000000..efb5a1f42 --- /dev/null +++ b/app/views/RoomView/Separator.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { View, StyleSheet, Text } from 'react-native'; +import PropTypes from 'prop-types'; +import moment from 'moment'; +import I18n from '../../i18n'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + marginVertical: 10 + }, + line: { + borderTopColor: '#eaeaea', + borderTopWidth: StyleSheet.hairlineWidth, + flex: 1 + }, + text: { + color: '#444444', + fontSize: 11, + paddingHorizontal: 10, + transform: [{ scaleY: -1 }] + }, + unreadLine: { + borderTopColor: 'red' + }, + unreadText: { + color: 'red' + } +}); + +const DateSeparator = ({ ts, unread }) => { + const date = ts ? moment(ts).format('MMMM DD, YYYY') : null; + if (ts && unread) { + return ( + + {date} + + {I18n.t('unread_messages')} + + ); + } + if (ts) { + return ( + + + {date} + + + ); + } + return ( + + + {I18n.t('unread_messages')} + + ); +}; + +DateSeparator.propTypes = { + ts: PropTypes.instanceOf(Date), + unread: PropTypes.bool +}; + +export default DateSeparator; diff --git a/app/views/RoomView/UnreadSeparator.js b/app/views/RoomView/UnreadSeparator.js deleted file mode 100644 index 00b4b9958..000000000 --- a/app/views/RoomView/UnreadSeparator.js +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import { View, StyleSheet, Text, LayoutAnimation } from 'react-native'; -import I18n from '../../i18n'; - -const styles = StyleSheet.create({ - firstUnread: { - flex: 1, - flexDirection: 'row', - alignItems: 'center', - marginVertical: -7 - }, - firstUnreadLine: { - borderTopColor: 'red', - borderTopWidth: StyleSheet.hairlineWidth, - flex: 1 - }, - firstUnreadBadge: { - color: 'red', - backgroundColor: '#fff', - fontSize: 11, - paddingHorizontal: 10, - transform: [{ scaleY: -1 }] - } -}); - -export default class UnreadSeparator extends React.PureComponent { - componentWillUnmount() { - LayoutAnimation.linear(); - } - render() { - return ( - - - {I18n.t('unread_messages')} - - ); - } -} diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 928da4fb1..28cfadb00 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -70,7 +70,8 @@ export default class RoomView extends LoggedView { this.state = { loaded: true, joined: typeof props.rid === 'undefined', - room: {} + room: {}, + end: false }; this.onReactionPress = this.onReactionPress.bind(this); } @@ -87,20 +88,15 @@ export default class RoomView extends LoggedView { this.props.editCancel(); } - onEndReached = (data) => { - if (this.props.loading || this.state.end) { + onEndReached = (lastRowData) => { + if (!lastRowData) { + this.setState({ end: true }); return; } - requestAnimationFrame(() => { - const lastRowData = data[data.length - 1]; - if (!lastRowData) { - return; - } - // TODO: fix - RocketChat.loadMessagesForRoom({ rid: this.rid, t: this.state.room.t, latest: lastRowData.ts }, ({ end }) => end && this.setState({ - end - })); + requestAnimationFrame(async() => { + const result = await RocketChat.loadMessagesForRoom({ rid: this.rid, t: this.state.room.t, latest: lastRowData.ts }); + this.setState({ end: result < 20 }); }); }