chat-context.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import React, {
  2. createContext,
  3. useCallback,
  4. useContext,
  5. useState,
  6. useEffect
  7. } from 'react'
  8. import PropTypes from 'prop-types'
  9. import { useApplicationContext } from '../../../shared/context/application-context'
  10. import { useEditorContext } from '../../../shared/context/editor-context'
  11. import { ChatStore } from '../store/chat-store'
  12. import useBrowserWindow from '../../../infrastructure/browser-window-hook'
  13. export const ChatContext = createContext()
  14. export function ChatProvider({ children }) {
  15. const {
  16. hasFocus: windowHasFocus,
  17. flashTitle,
  18. stopFlashingTitle
  19. } = useBrowserWindow()
  20. const { user } = useApplicationContext()
  21. const {
  22. projectId,
  23. ui: { chatIsOpen }
  24. } = useEditorContext()
  25. const [unreadMessageCount, setUnreadMessageCount] = useState(0)
  26. function resetUnreadMessageCount() {
  27. setUnreadMessageCount(0)
  28. }
  29. const [atEnd, setAtEnd] = useState(false)
  30. const [loading, setLoading] = useState(false)
  31. const [messages, setMessages] = useState([])
  32. const [store] = useState(() => new ChatStore(user, projectId))
  33. useEffect(() => {
  34. if (windowHasFocus) {
  35. stopFlashingTitle()
  36. if (chatIsOpen) {
  37. setUnreadMessageCount(0)
  38. }
  39. }
  40. if (!windowHasFocus && unreadMessageCount > 0) {
  41. flashTitle('New Message')
  42. }
  43. }, [
  44. windowHasFocus,
  45. chatIsOpen,
  46. unreadMessageCount,
  47. flashTitle,
  48. stopFlashingTitle
  49. ])
  50. useEffect(() => {
  51. function updateState() {
  52. setAtEnd(store.atEnd)
  53. setLoading(store.loading)
  54. setMessages(store.messages)
  55. }
  56. function handleNewMessage() {
  57. setUnreadMessageCount(prevCount => prevCount + 1)
  58. }
  59. store.on('updated', updateState)
  60. store.on('message-received', handleNewMessage)
  61. updateState()
  62. return () => store.destroy()
  63. }, [store])
  64. const loadMoreMessages = useCallback(() => store.loadMoreMessages(), [store])
  65. const sendMessage = useCallback(message => store.sendMessage(message), [
  66. store
  67. ])
  68. const value = {
  69. userId: user.id,
  70. atEnd,
  71. loading,
  72. messages,
  73. unreadMessageCount,
  74. resetUnreadMessageCount,
  75. loadMoreMessages,
  76. sendMessage
  77. }
  78. return <ChatContext.Provider value={value}>{children}</ChatContext.Provider>
  79. }
  80. ChatProvider.propTypes = {
  81. children: PropTypes.any
  82. }
  83. export function useChatContext() {
  84. return useContext(ChatContext)
  85. }