message-list.jsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import PropTypes from 'prop-types'
  2. import moment from 'moment'
  3. import Message from './message'
  4. const FIVE_MINUTES = 5 * 60 * 1000
  5. function formatTimestamp(date) {
  6. if (!date) {
  7. return 'N/A'
  8. } else {
  9. return `${moment(date).format('h:mm a')} ${moment(date).calendar()}`
  10. }
  11. }
  12. function MessageList({ messages, resetUnreadMessages, userId }) {
  13. function shouldRenderDate(messageIndex) {
  14. if (messageIndex === 0) {
  15. return true
  16. } else {
  17. const message = messages[messageIndex]
  18. const previousMessage = messages[messageIndex - 1]
  19. return message.timestamp - previousMessage.timestamp > FIVE_MINUTES
  20. }
  21. }
  22. return (
  23. // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
  24. <ul
  25. className="list-unstyled"
  26. onClick={resetUnreadMessages}
  27. onKeyDown={resetUnreadMessages}
  28. >
  29. {messages.map((message, index) => (
  30. // new messages are added to the beginning of the list, so we use a reversed index
  31. <li key={message.id} className="message">
  32. {shouldRenderDate(index) && (
  33. <div className="date">
  34. <time
  35. dateTime={
  36. message.timestamp
  37. ? moment(message.timestamp).format()
  38. : undefined
  39. }
  40. >
  41. {formatTimestamp(message.timestamp)}
  42. </time>
  43. </div>
  44. )}
  45. <Message message={message} userId={userId} />
  46. </li>
  47. ))}
  48. </ul>
  49. )
  50. }
  51. MessageList.propTypes = {
  52. messages: PropTypes.arrayOf(
  53. PropTypes.shape({
  54. id: PropTypes.string.isRequired,
  55. timestamp: PropTypes.number,
  56. })
  57. ).isRequired,
  58. resetUnreadMessages: PropTypes.func.isRequired,
  59. userId: PropTypes.string,
  60. }
  61. export default MessageList