You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // @flow
  2. import { v4 as uuidv4 } from 'uuid';
  3. import { ReducerRegistry } from '../base/redux';
  4. import {
  5. ADD_MESSAGE,
  6. CLEAR_MESSAGES,
  7. CLOSE_CHAT,
  8. EDIT_MESSAGE,
  9. OPEN_CHAT,
  10. SET_PRIVATE_MESSAGE_RECIPIENT,
  11. SET_IS_POLL_TAB_FOCUSED,
  12. SET_LOBBY_CHAT_RECIPIENT,
  13. SET_LOBBY_CHAT_ACTIVE_STATE,
  14. REMOVE_LOBBY_CHAT_PARTICIPANT
  15. } from './actionTypes';
  16. const DEFAULT_STATE = {
  17. isOpen: false,
  18. isPollsTabFocused: false,
  19. lastReadMessage: undefined,
  20. lastReadPoll: undefined,
  21. messages: [],
  22. nbUnreadMessages: 0,
  23. privateMessageRecipient: undefined,
  24. lobbyMessageRecipient: undefined,
  25. isLobbyChatActive: false
  26. };
  27. ReducerRegistry.register('features/chat', (state = DEFAULT_STATE, action) => {
  28. switch (action.type) {
  29. case ADD_MESSAGE: {
  30. const newMessage = {
  31. displayName: action.displayName,
  32. error: action.error,
  33. id: action.id,
  34. isReaction: action.isReaction,
  35. messageId: uuidv4(),
  36. messageType: action.messageType,
  37. message: action.message,
  38. privateMessage: action.privateMessage,
  39. lobbyChat: action.lobbyChat,
  40. recipient: action.recipient,
  41. timestamp: action.timestamp
  42. };
  43. // React native, unlike web, needs a reverse sorted message list.
  44. const messages = navigator.product === 'ReactNative'
  45. ? [
  46. newMessage,
  47. ...state.messages
  48. ]
  49. : [
  50. ...state.messages,
  51. newMessage
  52. ];
  53. return {
  54. ...state,
  55. lastReadMessage:
  56. action.hasRead ? newMessage : state.lastReadMessage,
  57. nbUnreadMessages: state.isPollsTabFocused ? state.nbUnreadMessages + 1 : state.nbUnreadMessages,
  58. messages
  59. };
  60. }
  61. case CLEAR_MESSAGES:
  62. return {
  63. ...state,
  64. lastReadMessage: undefined,
  65. messages: []
  66. };
  67. case EDIT_MESSAGE: {
  68. let found = false;
  69. const newMessage = action.message;
  70. const messages = state.messages.map(m => {
  71. if (m.messageId === newMessage.messageId) {
  72. found = true;
  73. return newMessage;
  74. }
  75. return m;
  76. });
  77. // no change
  78. if (!found) {
  79. return state;
  80. }
  81. return {
  82. ...state,
  83. messages
  84. };
  85. }
  86. case SET_PRIVATE_MESSAGE_RECIPIENT:
  87. return {
  88. ...state,
  89. privateMessageRecipient: action.participant
  90. };
  91. case OPEN_CHAT:
  92. return {
  93. ...state,
  94. isOpen: true,
  95. privateMessageRecipient: action.participant
  96. };
  97. case CLOSE_CHAT:
  98. return {
  99. ...state,
  100. isOpen: false,
  101. lastReadMessage: state.messages[
  102. navigator.product === 'ReactNative' ? 0 : state.messages.length - 1],
  103. privateMessageRecipient: action.participant,
  104. isLobbyChatActive: false
  105. };
  106. case SET_IS_POLL_TAB_FOCUSED: {
  107. return {
  108. ...state,
  109. isPollsTabFocused: action.isPollsTabFocused,
  110. nbUnreadMessages: 0
  111. }; }
  112. case SET_LOBBY_CHAT_RECIPIENT:
  113. return {
  114. ...state,
  115. isLobbyChatActive: true,
  116. lobbyMessageRecipient: action.participant,
  117. privateMessageRecipient: undefined,
  118. isOpen: action.open
  119. };
  120. case SET_LOBBY_CHAT_ACTIVE_STATE:
  121. return {
  122. ...state,
  123. isLobbyChatActive: action.payload,
  124. isOpen: action.payload || state.isOpen,
  125. privateMessageRecipient: undefined
  126. };
  127. case REMOVE_LOBBY_CHAT_PARTICIPANT:
  128. return {
  129. ...state,
  130. messages: state.messages.filter(m => {
  131. if (action.removeLobbyChatMessages) {
  132. return !m.lobbyChat;
  133. }
  134. return true;
  135. }),
  136. isOpen: state.isOpen && state.isLobbyChatActive ? false : state.isOpen,
  137. isLobbyChatActive: false,
  138. lobbyMessageRecipient: undefined
  139. };
  140. }
  141. return state;
  142. });