From bf9146328403ff203d092182b1b89c672b591d69 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 18 Sep 2020 18:51:22 -0500 Subject: [PATCH] Chats: add timestamps, fixes #370 --- .../chats/components/chat_message_list.js | 88 ++++++++++++++----- app/styles/chats.scss | 8 ++ 2 files changed, 73 insertions(+), 23 deletions(-) diff --git a/app/soapbox/features/chats/components/chat_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js index bd20ffade..6e2c63ce6 100644 --- a/app/soapbox/features/chats/components/chat_message_list.js +++ b/app/soapbox/features/chats/components/chat_message_list.js @@ -2,7 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl } from 'react-intl'; +import { injectIntl, defineMessages } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { fetchChatMessages } from 'soapbox/actions/chats'; @@ -13,6 +13,22 @@ import { escape, throttle } from 'lodash'; import { MediaGallery } from 'soapbox/features/ui/util/async-components'; import Bundle from 'soapbox/features/ui/components/bundle'; +const messages = defineMessages({ + today: { id: 'chats.dividers.today', defaultMessage: 'Today' }, +}); + +const timeChange = (prev, curr) => { + const prevDate = new Date(prev.get('created_at')).getDate(); + const currDate = new Date(curr.get('created_at')).getDate(); + const nowDate = new Date().getDate(); + + if (prevDate !== currDate) { + return currDate === nowDate ? 'today' : 'date'; + }; + + return null; +}; + const makeEmojiMap = record => record.get('emojis', ImmutableList()).reduce((map, emoji) => { return map.set(`:${emoji.get('shortcode')}:`, emoji); }, ImmutableMap()); @@ -191,32 +207,58 @@ class ChatMessageList extends ImmutablePureComponent { this.node = c; } + renderDivider = (text) => ( +
{text}
+ ) + + renderMessage = (chatMessage) => { + const { me } = this.props; + + return ( +
+
+ {this.maybeRenderMedia(chatMessage)} + +
+
+ ); + } + render() { - const { chatMessages, me } = this.props; + const { chatMessages, intl } = this.props; return (
- {chatMessages.map(chatMessage => ( -
-
- {this.maybeRenderMedia(chatMessage)} - -
-
- ))} + {chatMessages.reduce((acc, curr, idx) => { + const lastMessage = chatMessages.get(idx-1); + + if (lastMessage) { + switch(timeChange(lastMessage, curr)) { + case 'today': + acc.push(this.renderDivider(intl.formatMessage(messages.today))); + break; + case 'date': + acc.push(this.renderDivider(new Date(curr.get('created_at')).toDateString())); + break; + } + } + + acc.push(this.renderMessage(curr)); + return acc; + }, [])}
); diff --git a/app/styles/chats.scss b/app/styles/chats.scss index 6cb6ef929..126c371a2 100644 --- a/app/styles/chats.scss +++ b/app/styles/chats.scss @@ -439,3 +439,11 @@ object-fit: contain; } } + +.chat-messages__divider { + text-align: center; + text-transform: uppercase; + font-size: 13px; + padding: 14px 0 2px; + opacity: 0.8; +}