chat-pane.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import React, { useEffect } from 'react'
  2. import PropTypes from 'prop-types'
  3. import MessageList from './message-list'
  4. import MessageInput from './message-input'
  5. import InfiniteScroll from './infinite-scroll'
  6. import Icon from '../../../shared/components/icon'
  7. import { useTranslation } from 'react-i18next'
  8. function ChatPane({
  9. atEnd,
  10. loading,
  11. loadMoreMessages,
  12. messages,
  13. resetUnreadMessages,
  14. sendMessage,
  15. userId
  16. }) {
  17. const { t } = useTranslation()
  18. useEffect(() => {
  19. loadMoreMessages()
  20. }, [])
  21. const shouldDisplayPlaceholder = !loading && messages.length === 0
  22. const messageContentCount = messages.reduce(
  23. (acc, { contents }) => acc + contents.length,
  24. 0
  25. )
  26. return (
  27. <aside className="chat">
  28. <InfiniteScroll
  29. atEnd={atEnd}
  30. className="messages"
  31. fetchData={loadMoreMessages}
  32. isLoading={loading}
  33. itemCount={messageContentCount}
  34. >
  35. <div>
  36. <h2 className="sr-only">{t('chat')}</h2>
  37. {loading && <LoadingSpinner />}
  38. {shouldDisplayPlaceholder && <Placeholder />}
  39. <MessageList
  40. messages={messages}
  41. userId={userId}
  42. resetUnreadMessages={resetUnreadMessages}
  43. />
  44. </div>
  45. </InfiniteScroll>
  46. <MessageInput
  47. resetUnreadMessages={resetUnreadMessages}
  48. sendMessage={sendMessage}
  49. />
  50. </aside>
  51. )
  52. }
  53. function LoadingSpinner() {
  54. const { t } = useTranslation()
  55. return (
  56. <div className="loading">
  57. <Icon type="fw" modifier="refresh" spin />
  58. {` ${t('loading')}…`}
  59. </div>
  60. )
  61. }
  62. function Placeholder() {
  63. const { t } = useTranslation()
  64. return (
  65. <>
  66. <div className="no-messages text-center small">{t('no_messages')}</div>
  67. <div className="first-message text-center">
  68. {t('send_first_message')}
  69. <br />
  70. <Icon type="arrow-down" />
  71. </div>
  72. </>
  73. )
  74. }
  75. ChatPane.propTypes = {
  76. atEnd: PropTypes.bool,
  77. loading: PropTypes.bool,
  78. loadMoreMessages: PropTypes.func.isRequired,
  79. messages: PropTypes.array.isRequired,
  80. resetUnreadMessages: PropTypes.func.isRequired,
  81. sendMessage: PropTypes.func.isRequired,
  82. userId: PropTypes.string.isRequired
  83. }
  84. export default ChatPane