@webinex/chatify 1.0.3-rc3 → 2.0.0-alpha3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. package/dist/css/chatify.css +253 -118
  2. package/dist/esm/index.js +10 -1
  3. package/dist/esm/index.js.map +1 -1
  4. package/dist/esm/types/core/api/api.d.ts +12696 -0
  5. package/dist/esm/types/core/api/baseApi.d.ts +15 -0
  6. package/dist/esm/types/core/api/index.d.ts +1 -0
  7. package/dist/esm/types/core/client.d.ts +57 -9
  8. package/dist/esm/types/core/constants.d.ts +1 -0
  9. package/dist/esm/types/core/debounce.d.ts +27 -0
  10. package/dist/esm/types/core/index.d.ts +3 -16
  11. package/dist/esm/types/core/types.d.ts +102 -0
  12. package/dist/esm/types/index.d.ts +0 -1
  13. package/dist/esm/types/ui/Chat/ChatContext.d.ts +10 -0
  14. package/dist/esm/types/ui/Chat/ChatEditableHeaderName.d.ts +2 -0
  15. package/dist/esm/types/ui/Chat/ChatHeaderActions.d.ts +2 -0
  16. package/dist/esm/types/ui/Chat/ChatPanel.d.ts +13 -0
  17. package/dist/esm/types/ui/Chat/ChatView.d.ts +17 -0
  18. package/dist/esm/types/ui/Chat/Members/ChatMembersButton.d.ts +2 -0
  19. package/dist/esm/types/ui/Chat/Members/ChatMembersPanel.d.ts +2 -0
  20. package/dist/esm/types/ui/Chat/Members/ChatMembersPreview.d.ts +2 -0
  21. package/dist/esm/types/ui/Chat/Members/index.d.ts +11 -0
  22. package/dist/esm/types/ui/Chat/index.d.ts +6 -0
  23. package/dist/esm/types/ui/ChatGroup/ChatGroupContext.d.ts +12 -0
  24. package/dist/esm/types/ui/ChatGroup/ChatGroupPanel.d.ts +15 -0
  25. package/dist/esm/types/ui/ChatGroup/Create/CreateChatButton.d.ts +2 -0
  26. package/dist/esm/types/ui/{CreateChatPanel → ChatGroup/Create}/CreateChatForm.d.ts +1 -1
  27. package/dist/esm/types/ui/ChatGroup/Create/CreateChatMemberInput.d.ts +5 -0
  28. package/dist/esm/types/ui/ChatGroup/Create/CreateChatNameInput.d.ts +5 -0
  29. package/dist/esm/types/ui/ChatGroup/Create/CreateChatPanel.d.ts +2 -0
  30. package/dist/esm/types/ui/ChatGroup/Create/index.d.ts +17 -0
  31. package/dist/esm/types/ui/ChatGroup/Layout/ChatGroupAside.d.ts +2 -0
  32. package/dist/esm/types/ui/ChatGroup/Layout/ChatGroupBody.d.ts +2 -0
  33. package/dist/esm/types/ui/ChatGroup/Layout/ChatGroupFooter.d.ts +2 -0
  34. package/dist/esm/types/ui/ChatGroup/Layout/ChatGroupHeader.d.ts +2 -0
  35. package/dist/esm/types/ui/ChatGroup/Layout/ChatGroupMain.d.ts +2 -0
  36. package/dist/esm/types/ui/ChatGroup/Layout/index.d.ts +17 -0
  37. package/dist/esm/types/ui/ChatGroup/List/ChatList.d.ts +2 -0
  38. package/dist/esm/types/ui/ChatGroup/List/ChatListItemAvatar.d.ts +3 -0
  39. package/dist/esm/types/ui/ChatGroup/List/ChatListItemBox.d.ts +6 -0
  40. package/dist/esm/types/ui/ChatGroup/List/ChatListItemLastMessage.d.ts +3 -0
  41. package/dist/esm/types/ui/ChatGroup/List/ChatListItemLastMessageAuthor.d.ts +3 -0
  42. package/dist/esm/types/ui/{ChatList → ChatGroup/List}/ChatListItemLastMessageContent.d.ts +1 -1
  43. package/dist/esm/types/ui/ChatGroup/List/ChatListItemLastMessageSentAt.d.ts +3 -0
  44. package/dist/esm/types/ui/ChatGroup/List/ChatListItemName.d.ts +3 -0
  45. package/dist/esm/types/ui/ChatGroup/List/ChatListItemUnreadCount.d.ts +3 -0
  46. package/dist/esm/types/ui/ChatGroup/List/index.d.ts +29 -0
  47. package/dist/esm/types/ui/ChatGroup/index.d.ts +5 -0
  48. package/dist/esm/types/ui/Chatify.d.ts +8 -72
  49. package/dist/esm/types/ui/Conversation/Conversation.d.ts +23 -0
  50. package/dist/esm/types/ui/Conversation/ConversationActions.d.ts +2 -0
  51. package/dist/esm/types/ui/Conversation/ConversationBody.d.ts +2 -0
  52. package/dist/esm/types/ui/Conversation/ConversationContext.d.ts +22 -0
  53. package/dist/esm/types/ui/Conversation/ConversationHeader.d.ts +2 -0
  54. package/dist/esm/types/ui/Conversation/ConversationName.d.ts +2 -0
  55. package/dist/esm/types/ui/Conversation/InputBox/InputBox.d.ts +2 -0
  56. package/dist/esm/types/ui/Conversation/InputBox/InputBoxFile.d.ts +8 -0
  57. package/dist/esm/types/ui/Conversation/InputBox/InputBoxFileList.d.ts +8 -0
  58. package/dist/esm/types/ui/Conversation/InputBox/InputFilesBox.d.ts +12 -0
  59. package/dist/esm/types/ui/Conversation/InputBox/InputSubmitButtonBox.d.ts +7 -0
  60. package/dist/esm/types/ui/Conversation/InputBox/InputTextBox.d.ts +9 -0
  61. package/dist/esm/types/ui/Conversation/InputBox/index.d.ts +21 -0
  62. package/dist/esm/types/ui/Conversation/Message/MessageAuthor.d.ts +3 -0
  63. package/dist/esm/types/ui/Conversation/Message/MessageBox.d.ts +6 -0
  64. package/dist/esm/types/ui/Conversation/Message/MessageContent.d.ts +3 -0
  65. package/dist/esm/types/ui/Conversation/Message/MessageFile.d.ts +6 -0
  66. package/dist/esm/types/ui/Conversation/Message/MessageFileList.d.ts +3 -0
  67. package/dist/esm/types/ui/Conversation/Message/MessageInfoBox.d.ts +3 -0
  68. package/dist/esm/types/ui/{Message → Conversation/Message}/MessageRow.d.ts +1 -1
  69. package/dist/esm/types/ui/Conversation/Message/MessageText.d.ts +3 -0
  70. package/dist/esm/types/ui/Conversation/Message/index.d.ts +26 -0
  71. package/dist/esm/types/ui/Conversation/NextObserver/NextMessagesObserver.d.ts +5 -0
  72. package/dist/esm/types/ui/Conversation/NextObserver/index.d.ts +1 -0
  73. package/dist/esm/types/ui/Conversation/ReadObserver/MessageReadObserver.d.ts +6 -0
  74. package/dist/esm/types/ui/Conversation/ReadObserver/index.d.ts +1 -0
  75. package/dist/esm/types/ui/Conversation/SendingMessage/SendingMessageBox.d.ts +7 -0
  76. package/dist/esm/types/ui/Conversation/SendingMessage/SendingMessageContent.d.ts +3 -0
  77. package/dist/esm/types/ui/Conversation/SendingMessage/SendingMessageInfoBox.d.ts +3 -0
  78. package/dist/esm/types/ui/{SendingMessage/SendingMessageInfoBox.d.ts → Conversation/SendingMessage/SendingMessageText.d.ts} +1 -1
  79. package/dist/esm/types/ui/Conversation/SendingMessage/index.d.ts +14 -0
  80. package/dist/esm/types/ui/Conversation/SystemMessage/SystemMessageBox.d.ts +6 -0
  81. package/dist/esm/types/ui/Conversation/SystemMessage/SystemMessageRow.d.ts +9 -0
  82. package/dist/esm/types/ui/Conversation/SystemMessage/index.d.ts +8 -0
  83. package/dist/esm/types/ui/Conversation/index.d.ts +12 -0
  84. package/dist/esm/types/ui/{InputBox/InputFilesBox.d.ts → Thread/ThreadActions.d.ts} +1 -1
  85. package/dist/esm/types/ui/Thread/ThreadContext.d.ts +8 -0
  86. package/dist/esm/types/ui/Thread/ThreadPanel.d.ts +14 -0
  87. package/dist/esm/types/ui/Thread/index.d.ts +3 -0
  88. package/dist/esm/types/ui/color.d.ts +6 -0
  89. package/dist/esm/types/ui/common/Avatar.d.ts +6 -0
  90. package/dist/esm/types/ui/common/Icon.d.ts +22 -0
  91. package/dist/esm/types/ui/common/MessageSkeleton.d.ts +5 -0
  92. package/dist/esm/types/ui/common/index.d.ts +11 -0
  93. package/dist/esm/types/ui/customize.d.ts +5 -7
  94. package/dist/esm/types/ui/index.d.ts +9 -9
  95. package/dist/esm/types/ui/localizer.d.ts +7 -6
  96. package/dist/esm/types/ui/useFormatter.d.ts +3 -0
  97. package/dist/index.d.ts +13150 -425
  98. package/package.json +94 -92
  99. package/src/core/api/api.ts +639 -0
  100. package/src/core/api/baseApi.ts +38 -0
  101. package/src/core/api/index.ts +1 -0
  102. package/src/core/client.ts +280 -143
  103. package/src/core/constants.ts +1 -0
  104. package/src/core/debounce.ts +90 -0
  105. package/src/core/index.ts +4 -17
  106. package/src/core/types.tsx +149 -0
  107. package/src/index.ts +2 -3
  108. package/src/styles/aside.scss +162 -132
  109. package/src/styles/chat.scss +209 -211
  110. package/src/styles/index.scss +159 -108
  111. package/src/styles/input.scss +147 -72
  112. package/src/styles/keyframes.scss +14 -14
  113. package/src/styles/members.scss +13 -0
  114. package/src/styles/mixins.scss +25 -20
  115. package/src/styles/variables.scss +13 -10
  116. package/src/ui/Chat/ChatContext.tsx +30 -0
  117. package/src/ui/{ChatPanel/ChatHeaderName.tsx → Chat/ChatEditableHeaderName.tsx} +63 -69
  118. package/src/ui/Chat/ChatHeaderActions.tsx +19 -0
  119. package/src/ui/Chat/ChatPanel.tsx +30 -0
  120. package/src/ui/Chat/ChatView.tsx +115 -0
  121. package/src/ui/Chat/Members/ChatMembersButton.tsx +9 -0
  122. package/src/ui/{ChatPanel → Chat/Members}/ChatMembersPanel.tsx +112 -121
  123. package/src/ui/Chat/Members/ChatMembersPreview.tsx +25 -0
  124. package/src/ui/Chat/Members/index.ts +13 -0
  125. package/src/ui/Chat/index.ts +6 -0
  126. package/src/ui/ChatGroup/ChatGroupContext.tsx +50 -0
  127. package/src/ui/ChatGroup/ChatGroupPanel.tsx +73 -0
  128. package/src/ui/ChatGroup/Create/CreateChatButton.tsx +15 -0
  129. package/src/ui/{CreateChatPanel → ChatGroup/Create}/CreateChatForm.tsx +36 -36
  130. package/src/ui/{CreateChatPanel → ChatGroup/Create}/CreateChatMemberInput.tsx +65 -66
  131. package/src/ui/{CreateChatPanel → ChatGroup/Create}/CreateChatNameInput.tsx +25 -25
  132. package/src/ui/{CreateChatPanel → ChatGroup/Create}/CreateChatPanel.tsx +45 -49
  133. package/src/ui/ChatGroup/Create/index.ts +19 -0
  134. package/src/ui/ChatGroup/Layout/ChatGroupAside.tsx +12 -0
  135. package/src/ui/ChatGroup/Layout/ChatGroupBody.tsx +10 -0
  136. package/src/ui/ChatGroup/Layout/ChatGroupFooter.tsx +3 -0
  137. package/src/ui/ChatGroup/Layout/ChatGroupHeader.tsx +5 -0
  138. package/src/ui/ChatGroup/Layout/ChatGroupMain.tsx +17 -0
  139. package/src/ui/ChatGroup/Layout/index.ts +19 -0
  140. package/src/ui/{ChatList → ChatGroup/List}/ChatList.tsx +41 -42
  141. package/src/ui/ChatGroup/List/ChatListItemAvatar.tsx +22 -0
  142. package/src/ui/{ChatList → ChatGroup/List}/ChatListItemBox.tsx +26 -22
  143. package/src/ui/{ChatList → ChatGroup/List}/ChatListItemLastMessage.tsx +15 -15
  144. package/src/ui/{ChatList → ChatGroup/List}/ChatListItemLastMessageAuthor.tsx +15 -20
  145. package/src/ui/{ChatList → ChatGroup/List}/ChatListItemLastMessageContent.tsx +21 -21
  146. package/src/ui/{ChatList → ChatGroup/List}/ChatListItemLastMessageSentAt.tsx +22 -22
  147. package/src/ui/ChatGroup/List/ChatListItemName.tsx +8 -0
  148. package/src/ui/{ChatList → ChatGroup/List}/ChatListItemUnreadCount.tsx +12 -12
  149. package/src/ui/ChatGroup/List/index.ts +31 -0
  150. package/src/ui/ChatGroup/index.ts +5 -0
  151. package/src/ui/Chatify.tsx +9 -154
  152. package/src/ui/Conversation/Conversation.tsx +78 -0
  153. package/src/ui/Conversation/ConversationActions.tsx +5 -0
  154. package/src/ui/Conversation/ConversationBody.tsx +28 -0
  155. package/src/ui/Conversation/ConversationContext.ts +29 -0
  156. package/src/ui/Conversation/ConversationHeader.tsx +23 -0
  157. package/src/ui/Conversation/ConversationName.tsx +7 -0
  158. package/src/ui/Conversation/InputBox/InputBox.tsx +122 -0
  159. package/src/ui/Conversation/InputBox/InputBoxFile.tsx +38 -0
  160. package/src/ui/Conversation/InputBox/InputBoxFileList.tsx +21 -0
  161. package/src/ui/Conversation/InputBox/InputFilesBox.tsx +78 -0
  162. package/src/ui/Conversation/InputBox/InputSubmitButtonBox.tsx +26 -0
  163. package/src/ui/{InputBox → Conversation/InputBox}/InputTextBox.tsx +61 -51
  164. package/src/ui/Conversation/InputBox/index.ts +23 -0
  165. package/src/ui/{Message → Conversation/Message}/MessageAuthor.tsx +13 -13
  166. package/src/ui/{Message → Conversation/Message}/MessageBox.tsx +20 -20
  167. package/src/ui/{Message → Conversation/Message}/MessageContent.tsx +15 -11
  168. package/src/ui/Conversation/Message/MessageFile.tsx +54 -0
  169. package/src/ui/Conversation/Message/MessageFileList.tsx +14 -0
  170. package/src/ui/{Message → Conversation/Message}/MessageInfoBox.tsx +28 -26
  171. package/src/ui/{Message → Conversation/Message}/MessageRow.tsx +28 -28
  172. package/src/ui/{Message → Conversation/Message}/MessageText.tsx +7 -7
  173. package/src/ui/Conversation/Message/index.ts +28 -0
  174. package/src/ui/{Next.tsx → Conversation/NextObserver/NextMessagesObserver.tsx} +47 -48
  175. package/src/ui/Conversation/NextObserver/index.ts +1 -0
  176. package/src/ui/{MessageReadObserver.tsx → Conversation/ReadObserver/MessageReadObserver.tsx} +49 -45
  177. package/src/ui/Conversation/ReadObserver/index.ts +1 -0
  178. package/src/ui/{SendingMessage → Conversation/SendingMessage}/SendingMessageBox.tsx +16 -16
  179. package/src/ui/{SendingMessage → Conversation/SendingMessage}/SendingMessageContent.tsx +13 -13
  180. package/src/ui/{SendingMessage → Conversation/SendingMessage}/SendingMessageInfoBox.tsx +13 -13
  181. package/src/ui/{SendingMessage → Conversation/SendingMessage}/SendingMessageText.tsx +7 -7
  182. package/src/ui/Conversation/SendingMessage/index.ts +16 -0
  183. package/src/ui/{SystemMessage → Conversation/SystemMessage}/SystemMessageBox.tsx +20 -20
  184. package/src/ui/Conversation/SystemMessage/SystemMessageRow.tsx +28 -0
  185. package/src/ui/Conversation/SystemMessage/index.ts +10 -0
  186. package/src/ui/Conversation/index.ts +13 -0
  187. package/src/ui/Thread/ThreadActions.tsx +22 -0
  188. package/src/ui/Thread/ThreadContext.ts +13 -0
  189. package/src/ui/Thread/ThreadPanel.tsx +127 -0
  190. package/src/ui/Thread/index.tsx +3 -0
  191. package/src/ui/color.ts +20 -0
  192. package/src/ui/common/Avatar.tsx +20 -0
  193. package/src/ui/{Icon.tsx → common/Icon.tsx} +44 -35
  194. package/src/ui/{MessageSkeleton.tsx → common/MessageSkeleton.tsx} +20 -19
  195. package/src/ui/common/index.ts +13 -0
  196. package/src/ui/customize.tsx +51 -45
  197. package/src/ui/index.ts +11 -11
  198. package/src/ui/localizer.tsx +96 -84
  199. package/src/ui/useFormatter.tsx +17 -0
  200. package/dist/esm/types/ChatifyContext.d.ts +0 -11
  201. package/dist/esm/types/core/action.d.ts +0 -151
  202. package/dist/esm/types/core/models.d.ts +0 -70
  203. package/dist/esm/types/core/reducer.d.ts +0 -11
  204. package/dist/esm/types/core/state.d.ts +0 -55
  205. package/dist/esm/types/core/useAddChatMutation.d.ts +0 -2
  206. package/dist/esm/types/core/useAddMemberMutation.d.ts +0 -2
  207. package/dist/esm/types/core/useFetchNextMutation.d.ts +0 -3
  208. package/dist/esm/types/core/useGetAccountsQuery.d.ts +0 -3
  209. package/dist/esm/types/core/useGetChatListQuery.d.ts +0 -3
  210. package/dist/esm/types/core/useGetChatQuery.d.ts +0 -5
  211. package/dist/esm/types/core/useGetMessagesQuery.d.ts +0 -4
  212. package/dist/esm/types/core/useReadMonitor.d.ts +0 -1
  213. package/dist/esm/types/core/useRemoveMemberMutation.d.ts +0 -2
  214. package/dist/esm/types/core/useSendMutation.d.ts +0 -2
  215. package/dist/esm/types/core/useSignalRMonitor.d.ts +0 -2
  216. package/dist/esm/types/core/useUpdateChatNameMutation.d.ts +0 -2
  217. package/dist/esm/types/ui/AddChatButton.d.ts +0 -2
  218. package/dist/esm/types/ui/Avatar.d.ts +0 -6
  219. package/dist/esm/types/ui/ChatList/ChatList.d.ts +0 -2
  220. package/dist/esm/types/ui/ChatList/ChatListItemBox.d.ts +0 -6
  221. package/dist/esm/types/ui/ChatList/ChatListItemLastMessage.d.ts +0 -3
  222. package/dist/esm/types/ui/ChatList/ChatListItemLastMessageAuthor.d.ts +0 -3
  223. package/dist/esm/types/ui/ChatList/ChatListItemLastMessageSentAt.d.ts +0 -3
  224. package/dist/esm/types/ui/ChatList/ChatListItemName.d.ts +0 -3
  225. package/dist/esm/types/ui/ChatList/ChatListItemUnreadCount.d.ts +0 -3
  226. package/dist/esm/types/ui/ChatList/index.d.ts +0 -8
  227. package/dist/esm/types/ui/ChatName.d.ts +0 -5
  228. package/dist/esm/types/ui/ChatPanel/ChatBody.d.ts +0 -5
  229. package/dist/esm/types/ui/ChatPanel/ChatHeader.d.ts +0 -5
  230. package/dist/esm/types/ui/ChatPanel/ChatHeaderMembers.d.ts +0 -5
  231. package/dist/esm/types/ui/ChatPanel/ChatHeaderName.d.ts +0 -5
  232. package/dist/esm/types/ui/ChatPanel/ChatMembersButton.d.ts +0 -5
  233. package/dist/esm/types/ui/ChatPanel/ChatMembersPanel.d.ts +0 -5
  234. package/dist/esm/types/ui/ChatPanel/ChatPanel.d.ts +0 -5
  235. package/dist/esm/types/ui/ChatPanel/index.d.ts +0 -6
  236. package/dist/esm/types/ui/CreateChatPanel/CreateChatMemberInput.d.ts +0 -5
  237. package/dist/esm/types/ui/CreateChatPanel/CreateChatNameInput.d.ts +0 -5
  238. package/dist/esm/types/ui/CreateChatPanel/CreateChatPanel.d.ts +0 -2
  239. package/dist/esm/types/ui/CreateChatPanel/index.d.ts +0 -4
  240. package/dist/esm/types/ui/Icon.d.ts +0 -17
  241. package/dist/esm/types/ui/InputBox/InputBox.d.ts +0 -2
  242. package/dist/esm/types/ui/InputBox/InputSubmitButtonBox.d.ts +0 -5
  243. package/dist/esm/types/ui/InputBox/InputTextBox.d.ts +0 -7
  244. package/dist/esm/types/ui/InputBox/index.d.ts +0 -4
  245. package/dist/esm/types/ui/Layout/Aside.d.ts +0 -2
  246. package/dist/esm/types/ui/Layout/Body.d.ts +0 -2
  247. package/dist/esm/types/ui/Layout/Footer.d.ts +0 -2
  248. package/dist/esm/types/ui/Layout/Header.d.ts +0 -2
  249. package/dist/esm/types/ui/Layout/Main.d.ts +0 -2
  250. package/dist/esm/types/ui/Layout/index.d.ts +0 -5
  251. package/dist/esm/types/ui/Message/MessageAuthor.d.ts +0 -3
  252. package/dist/esm/types/ui/Message/MessageBox.d.ts +0 -6
  253. package/dist/esm/types/ui/Message/MessageContent.d.ts +0 -3
  254. package/dist/esm/types/ui/Message/MessageInfoBox.d.ts +0 -3
  255. package/dist/esm/types/ui/Message/MessageText.d.ts +0 -3
  256. package/dist/esm/types/ui/Message/index.d.ts +0 -6
  257. package/dist/esm/types/ui/MessageReadObserver.d.ts +0 -6
  258. package/dist/esm/types/ui/MessageSkeleton.d.ts +0 -4
  259. package/dist/esm/types/ui/Next.d.ts +0 -4
  260. package/dist/esm/types/ui/SendingMessage/SendingMessageBox.d.ts +0 -7
  261. package/dist/esm/types/ui/SendingMessage/SendingMessageContent.d.ts +0 -3
  262. package/dist/esm/types/ui/SendingMessage/SendingMessageText.d.ts +0 -3
  263. package/dist/esm/types/ui/SendingMessage/index.d.ts +0 -4
  264. package/dist/esm/types/ui/SystemMessage/SystemMessageBox.d.ts +0 -6
  265. package/dist/esm/types/ui/SystemMessage/SystemMessageRow.d.ts +0 -9
  266. package/dist/esm/types/ui/SystemMessage/index.d.ts +0 -2
  267. package/dist/esm/types/util/index.d.ts +0 -2
  268. package/dist/esm/types/util/uniqBy.d.ts +0 -1
  269. package/dist/esm/types/util/uniqId.d.ts +0 -1
  270. package/src/ChatifyContext.tsx +0 -41
  271. package/src/core/action.tsx +0 -431
  272. package/src/core/models.tsx +0 -82
  273. package/src/core/reducer.tsx +0 -87
  274. package/src/core/state.ts +0 -93
  275. package/src/core/useAddChatMutation.tsx +0 -28
  276. package/src/core/useAddMemberMutation.tsx +0 -25
  277. package/src/core/useFetchNextMutation.tsx +0 -28
  278. package/src/core/useGetAccountsQuery.tsx +0 -30
  279. package/src/core/useGetChatListQuery.tsx +0 -30
  280. package/src/core/useGetChatQuery.tsx +0 -31
  281. package/src/core/useGetMessagesQuery.tsx +0 -35
  282. package/src/core/useReadMonitor.tsx +0 -32
  283. package/src/core/useRemoveMemberMutation.tsx +0 -23
  284. package/src/core/useSendMutation.tsx +0 -24
  285. package/src/core/useSignalRMonitor.tsx +0 -66
  286. package/src/core/useUpdateChatNameMutation.tsx +0 -23
  287. package/src/ui/AddChatButton.tsx +0 -17
  288. package/src/ui/Avatar.tsx +0 -18
  289. package/src/ui/ChatList/ChatListItemName.tsx +0 -13
  290. package/src/ui/ChatList/index.ts +0 -8
  291. package/src/ui/ChatName.tsx +0 -10
  292. package/src/ui/ChatPanel/ChatBody.tsx +0 -44
  293. package/src/ui/ChatPanel/ChatHeader.tsx +0 -31
  294. package/src/ui/ChatPanel/ChatHeaderMembers.tsx +0 -28
  295. package/src/ui/ChatPanel/ChatMembersButton.tsx +0 -21
  296. package/src/ui/ChatPanel/ChatPanel.tsx +0 -27
  297. package/src/ui/ChatPanel/index.ts +0 -6
  298. package/src/ui/CreateChatPanel/index.ts +0 -4
  299. package/src/ui/InputBox/InputBox.tsx +0 -38
  300. package/src/ui/InputBox/InputFilesBox.tsx +0 -9
  301. package/src/ui/InputBox/InputSubmitButtonBox.tsx +0 -17
  302. package/src/ui/InputBox/index.ts +0 -4
  303. package/src/ui/Layout/Aside.tsx +0 -12
  304. package/src/ui/Layout/Body.tsx +0 -10
  305. package/src/ui/Layout/Footer.tsx +0 -3
  306. package/src/ui/Layout/Header.tsx +0 -5
  307. package/src/ui/Layout/Main.tsx +0 -15
  308. package/src/ui/Layout/index.ts +0 -5
  309. package/src/ui/Message/index.ts +0 -6
  310. package/src/ui/SendingMessage/index.ts +0 -4
  311. package/src/ui/SystemMessage/SystemMessageRow.tsx +0 -43
  312. package/src/ui/SystemMessage/index.ts +0 -2
  313. package/src/util/index.ts +0 -2
  314. package/src/util/uniqBy.tsx +0 -17
  315. package/src/util/uniqId.tsx +0 -3
@@ -1,143 +1,280 @@
1
- import { AxiosInstance } from 'axios';
2
- import * as SignalR from '@microsoft/signalr';
3
- import {
4
- Account,
5
- AddChatRequest,
6
- AddMemberRequest,
7
- Chat,
8
- ChatListItem,
9
- Message,
10
- ReadRequest,
11
- RemoveMemberRequest,
12
- SendMessageRequest,
13
- UpdateChatNameRequest,
14
- } from './models';
15
-
16
- export interface ChatifySignalRConfig {
17
- hubUri?: string;
18
- accessTokenFactory?: () => Promise<string>;
19
- headersFactory?: () => Promise<Record<string, string>>;
20
- }
21
-
22
- const DEFAULT_SIGNALR_CONFIG: ChatifySignalRConfig = {
23
- hubUri: '/api/chatify/hub',
24
- headersFactory: () => Promise.resolve({}),
25
- };
26
-
27
- export interface ChatifyClientConfig {
28
- axios: AxiosInstance;
29
- signalR: ChatifySignalRConfig;
30
- }
31
-
32
- const METHODS = [
33
- 'chatify://new-message',
34
- 'chatify://chat-created',
35
- 'chatify://read',
36
- 'chatify://member-added',
37
- 'chatify://member-removed',
38
- 'chatify://chat-name-changed',
39
- ] as const;
40
-
41
- export class ChatifyClient {
42
- private _config: ChatifyClientConfig;
43
- private _connection: SignalR.HubConnection = null!;
44
- private _subscribers: Record<string, ((args: any[]) => void)[]> = {};
45
- private _reconnectSubscribers: Array<() => void> = [];
46
-
47
- constructor(config: ChatifyClientConfig) {
48
- this._config = {
49
- ...config,
50
- signalR: {
51
- ...DEFAULT_SIGNALR_CONFIG,
52
- ...config.signalR,
53
- },
54
- };
55
- }
56
-
57
- public connect = async () => {
58
- const headers = await this._config.signalR!.headersFactory!();
59
-
60
- this._connection = new SignalR.HubConnectionBuilder()
61
- .withUrl(this._config.signalR!.hubUri!, {
62
- accessTokenFactory: this._config.signalR!.accessTokenFactory
63
- ? this._config.signalR!.accessTokenFactory
64
- : undefined,
65
- headers,
66
- })
67
- .withAutomaticReconnect()
68
- .build();
69
-
70
- METHODS.forEach((x) => {
71
- this._connection.on(x, (...args) => {
72
- this._subscribers[x]?.forEach((s) => s(args));
73
- });
74
- });
75
-
76
- this._connection.onreconnected(() => this._reconnectSubscribers.forEach((subscriber) => subscriber()));
77
-
78
- await this._connection.start();
79
- };
80
-
81
- public subscribe = <T extends any[]>(method: string, subscriber: (args: T) => void) => {
82
- this._subscribers[method] = this._subscribers[method] ?? [];
83
- this._subscribers[method].push(subscriber as any);
84
- return () => this._subscribers[method].filter((x) => x !== subscriber);
85
- };
86
-
87
- public subscribeReconnect = (subscriber: () => any) => {
88
- this._reconnectSubscribers.push(subscriber);
89
- return () => this._reconnectSubscribers.filter((x) => x !== subscriber);
90
- };
91
-
92
- private get axios() {
93
- return this._config.axios;
94
- }
95
-
96
- public accounts = async () => {
97
- const { data } = await this.axios.get<Account[]>('account');
98
- return data;
99
- };
100
-
101
- public chats = async () => {
102
- const { data } = await this.axios.get<ChatListItem[]>('chat');
103
- return data;
104
- };
105
-
106
- public chat = async (id: string) => {
107
- const { data } = await this.axios.get<Chat>(`chat/${id}`);
108
- return data;
109
- };
110
-
111
- public addChat = async (args: AddChatRequest) => {
112
- const { data } = await this.axios.post<string>(`chat`, args);
113
- return data;
114
- };
115
-
116
- public messages = async (args: { chatId: string; skip?: number; take?: number }) => {
117
- const { chatId, skip = 0, take = 20 } = args;
118
- const pagingRule = encodeURIComponent(JSON.stringify({ skip, take }));
119
- const { data } = await this.axios.get<Message[]>(`chat/${chatId}/message?pagingRule=${pagingRule}`);
120
- return data;
121
- };
122
-
123
- public send = async (request: SendMessageRequest) => {
124
- const { chatId, ...rest } = request;
125
- await this.axios.post(`chat/${chatId}/message`, rest);
126
- };
127
-
128
- public read = async (request: ReadRequest) => {
129
- await this.axios.put(`chat/message/read`, request);
130
- };
131
-
132
- public removeMember = async (request: RemoveMemberRequest) => {
133
- await this.axios.delete(`chat/${request.chatId}/member`, { data: request });
134
- };
135
-
136
- public updateChatName = async (request: UpdateChatNameRequest) => {
137
- await this.axios.put(`chat/${request.id}/name`, request);
138
- };
139
-
140
- public addMember = async (request: AddMemberRequest) => {
141
- await this.axios.post(`chat/${request.chatId}/member`, request);
142
- };
143
- }
1
+ import { AxiosInstance } from 'axios';
2
+ import * as SignalR from '@microsoft/signalr';
3
+ import {
4
+ Account,
5
+ AddChatRequest,
6
+ AddChatMemberRequest,
7
+ Chat,
8
+ ChatListItem,
9
+ ChatMessage,
10
+ ReadChatMessageEvent,
11
+ ReadChatMessageRequest,
12
+ RemoveChatMemberRequest,
13
+ SendChatMessageRequest,
14
+ UpdateChatNameRequest,
15
+ SendThreadMessageRequest,
16
+ Thread,
17
+ ThreadMessage,
18
+ ThreadWatchListItem as ThreadListItem,
19
+ } from './types';
20
+
21
+ export interface ChatifySignalRConfig {
22
+ hubUri?: string;
23
+ accessTokenFactory?: () => Promise<string>;
24
+ headersFactory?: () => Promise<Record<string, string>>;
25
+ }
26
+
27
+ const DEFAULT_SIGNALR_CONFIG: ChatifySignalRConfig = {
28
+ hubUri: '/api/chatify/hub',
29
+ headersFactory: () => Promise.resolve({}),
30
+ };
31
+
32
+ export interface ChatifyClientConfig {
33
+ axios: AxiosInstance;
34
+ signalR: ChatifySignalRConfig;
35
+ }
36
+
37
+ export const CHATIFY_SIGNALR_METHODS = [
38
+ 'chatify://chat-new-message',
39
+ 'chatify://chat-created',
40
+ 'chatify://chat-message-read',
41
+ 'chatify://chat-member-added',
42
+ 'chatify://chat-member-removed',
43
+ 'chatify://chat-name-changed',
44
+
45
+ 'chatify://thread-created',
46
+ 'chatify://thread-message-new',
47
+ 'chatify://thread-message-read',
48
+ 'chatify://thread-watch-added',
49
+ 'chatify://thread-watch-removed',
50
+ ] as const;
51
+
52
+ export type ChatifySignalRMethod = (typeof CHATIFY_SIGNALR_METHODS)[number];
53
+
54
+ export type ChatifySignalRArgsByMethod = {
55
+ 'chatify://chat-new-message': [message: ChatMessage];
56
+ 'chatify://chat-created': [chat: ChatListItem];
57
+ 'chatify://chat-message-read': [events: ReadChatMessageEvent[]];
58
+ 'chatify://chat-member-added': [
59
+ chatId: string,
60
+ chatName: string,
61
+ account: Account,
62
+ message: ChatMessage,
63
+ withHistory: boolean,
64
+ read: boolean,
65
+ ];
66
+ 'chatify://chat-member-removed': [
67
+ chatId: string,
68
+ accountId: string,
69
+ deleteHistory: boolean,
70
+ message: ChatMessage,
71
+ read: boolean,
72
+ ];
73
+ 'chatify://chat-name-changed': [chatId: string, newName: string, message: ChatMessage, read: boolean];
74
+
75
+ 'chatify://thread-message-new': [threadId: string, message: ThreadMessage, readForId: string | null];
76
+ 'chatify://thread-message-read': [threadId: string, messageId: string];
77
+ 'chatify://thread-watch-added': [thread: ThreadListItem];
78
+ 'chatify://thread-watch-removed': [id: string];
79
+ 'chatify://thread-created': [thread: ThreadListItem, watch: boolean];
80
+ };
81
+
82
+ export class ChatifyClient {
83
+ private _config: ChatifyClientConfig;
84
+ private _connection: SignalR.HubConnection = null!;
85
+ private _connectionPromise: Promise<SignalR.HubConnection> | null = null!;
86
+ private _subscribers: Record<string, ((args: any[]) => void)[]> = {};
87
+ private _reconnectSubscribers: Array<() => void> = [];
88
+ private _threadConnectionByThreadId = new Map<string, number>();
89
+
90
+ constructor(config: ChatifyClientConfig) {
91
+ this._config = {
92
+ ...config,
93
+ signalR: {
94
+ ...DEFAULT_SIGNALR_CONFIG,
95
+ ...config.signalR,
96
+ },
97
+ };
98
+ }
99
+
100
+ public connect = async () => {
101
+ if (this._connection) {
102
+ return;
103
+ }
104
+
105
+ if (this._connectionPromise) {
106
+ return await this._connectionPromise;
107
+ }
108
+
109
+ this._connectionPromise = this.createAndStartConnection();
110
+ this._connection = await this._connectionPromise;
111
+ };
112
+
113
+ private createAndStartConnection = async () => {
114
+ const headers = await this._config.signalR!.headersFactory!();
115
+
116
+ const connection = new SignalR.HubConnectionBuilder()
117
+ .withUrl(this._config.signalR!.hubUri!, {
118
+ accessTokenFactory: this._config.signalR!.accessTokenFactory
119
+ ? this._config.signalR!.accessTokenFactory
120
+ : undefined,
121
+ headers,
122
+ })
123
+ .withAutomaticReconnect()
124
+ .build();
125
+
126
+ CHATIFY_SIGNALR_METHODS.forEach((x) => {
127
+ connection.on(x, (...args) => {
128
+ this._subscribers[x]?.forEach((s) => {
129
+ try {
130
+ s(args);
131
+ } catch (ex) {
132
+ console.error(`Failed to notify subscriber`, ex);
133
+ }
134
+ });
135
+ });
136
+ });
137
+
138
+ connection.onreconnected(() => this._reconnectSubscribers.forEach((subscriber) => subscriber()));
139
+
140
+ await connection.start();
141
+ return connection;
142
+ };
143
+
144
+ public subscribe = <TMethod extends ChatifySignalRMethod>(
145
+ method: TMethod,
146
+ subscriber: (args: ChatifySignalRArgsByMethod[TMethod]) => void,
147
+ ) => {
148
+ this.connect().then(() => {
149
+ this._subscribers[method] = this._subscribers[method] ?? [];
150
+ this._subscribers[method].push(subscriber as any);
151
+ });
152
+ return () => this._subscribers[method].filter((x) => x !== subscriber);
153
+ };
154
+
155
+ public subscribeReconnect = (subscriber: () => any) => {
156
+ this._reconnectSubscribers.push(subscriber);
157
+ return () => this._reconnectSubscribers.filter((x) => x !== subscriber);
158
+ };
159
+
160
+ private get axios() {
161
+ return this._config.axios;
162
+ }
163
+
164
+ public accounts = async () => {
165
+ const { data } = await this.axios.get<Account[]>('account');
166
+ return data;
167
+ };
168
+
169
+ public chats = async () => {
170
+ const { data } = await this.axios.get<ChatListItem[]>('chat');
171
+ return data;
172
+ };
173
+
174
+ public chat = async (id: string) => {
175
+ const { data } = await this.axios.get<Chat>(`chat/${encodeURIComponent(id)}`);
176
+ return data;
177
+ };
178
+
179
+ public addChat = async (args: AddChatRequest) => {
180
+ const { data } = await this.axios.post<string>(`chat`, args);
181
+ return data;
182
+ };
183
+
184
+ public chatMessages = async (args: { chatId: string; skip?: number; take?: number }) => {
185
+ const { chatId, skip = 0, take = 20 } = args;
186
+ const pagingRule = encodeURIComponent(JSON.stringify({ skip, take }));
187
+ const { data } = await this.axios.get<ChatMessage[]>(
188
+ `chat/${encodeURIComponent(chatId)}/message?pagingRule=${pagingRule}`,
189
+ );
190
+ return data;
191
+ };
192
+
193
+ public sendChatMessage = async (request: SendChatMessageRequest) => {
194
+ const { chatId, ...rest } = request;
195
+ await this.axios.post(`chat/${encodeURIComponent(chatId)}/message`, rest);
196
+ };
197
+
198
+ public readChatMessage = async (request: ReadChatMessageRequest) => {
199
+ await this.axios.put(`chat/message/read`, request);
200
+ };
201
+
202
+ public removeChatMember = async (request: RemoveChatMemberRequest) => {
203
+ await this.axios.delete(`chat/${encodeURIComponent(request.chatId)}/member`, { data: request });
204
+ };
205
+
206
+ public updateChatName = async (request: UpdateChatNameRequest) => {
207
+ await this.axios.put(`chat/${encodeURIComponent(request.id)}/name`, request);
208
+ };
209
+
210
+ public addChatMember = async (request: AddChatMemberRequest) => {
211
+ await this.axios.post(`chat/${encodeURIComponent(request.chatId)}/member`, request);
212
+ };
213
+
214
+ public sendThreadMessage = async ({ body, threadId }: SendThreadMessageRequest) => {
215
+ const { data: id } = await this.axios.post<string>(`thread/${encodeURIComponent(threadId)}/message`, {
216
+ body,
217
+ });
218
+ return id;
219
+ };
220
+
221
+ public readThreadMessage = async (id: string) => {
222
+ await this.axios.put(`thread/message/${encodeURIComponent(id)}/read`);
223
+ };
224
+
225
+ public watchThreads = async () => {
226
+ const { data } = await this.axios.get<ThreadListItem[]>(`thread/watch`);
227
+ return data;
228
+ };
229
+
230
+ public thread = async (id: string) => {
231
+ const { data } = await this.axios.get<Thread>(`thread/${encodeURIComponent(id)}`);
232
+ return data;
233
+ };
234
+
235
+ public threadMessages = async ({
236
+ threadId,
237
+ skip,
238
+ take,
239
+ }: {
240
+ threadId: string;
241
+ skip: number;
242
+ take: number;
243
+ }) => {
244
+ const searchParams = new URLSearchParams();
245
+ searchParams.append('skip', skip.toString());
246
+ searchParams.append('take', take.toString());
247
+ const { data } = await this.axios.get<ThreadMessage[]>(
248
+ `thread/${encodeURIComponent(threadId)}/message?${searchParams.toString()}`,
249
+ );
250
+ return data;
251
+ };
252
+
253
+ public watchThread = async (id: string, watch: boolean) => {
254
+ await this.axios.put(`thread/${encodeURIComponent(id)}/watch`, { watch });
255
+ };
256
+
257
+ public connectToThread = async (id: string) => {
258
+ const connectionCount = this._threadConnectionByThreadId.get(id) ?? 0;
259
+ this._threadConnectionByThreadId.set(id, connectionCount + 1);
260
+
261
+ if (connectionCount === 0) {
262
+ this.connect().then(() => this._connection.invoke('ConnectToThread', id));
263
+ }
264
+ };
265
+
266
+ public disconnectFromThread = async (id: string) => {
267
+ const connectionCount = this._threadConnectionByThreadId.get(id) ?? 0;
268
+ this._threadConnectionByThreadId.set(id, Math.max(0, connectionCount - 1));
269
+
270
+ if (connectionCount === 1) {
271
+ this.connect().then(() => this._connection.invoke('DisconnectFromThread', id));
272
+ }
273
+ };
274
+ }
275
+
276
+ export function unsubscribe(...subscribers: Array<() => void>) {
277
+ const result = () => subscribers.forEach((x) => x());
278
+ result.when = (promise: Promise<any>) => promise.then(result);
279
+ return result;
280
+ }
@@ -0,0 +1 @@
1
+ export const SYSTEM_ID = 'chatify::system';
@@ -0,0 +1,90 @@
1
+ interface DebounceInternalValue<T> {
2
+ value: T;
3
+ enqueueTime: number;
4
+ }
5
+
6
+ export interface DebounceValue<T> extends DebounceInternalValue<T> {
7
+ state: 'enqueued' | 'processing';
8
+ }
9
+
10
+ export interface DebounceConfig<T> {
11
+ timeout: number;
12
+ callback: (value: T) => Promise<any>;
13
+ groupBy: (value: T) => string;
14
+ compare: (a: T, b: T) => number;
15
+ }
16
+
17
+ export class Debounce<T> {
18
+ private _enqueued: DebounceInternalValue<T>[] = [];
19
+ private _processing: DebounceInternalValue<T>[] = [];
20
+ private _timeoutByGroup: Record<string, NodeJS.Timeout> = {};
21
+ private _subscribers: ((value: Debounce<T>) => any)[] = [];
22
+
23
+ constructor(public config: DebounceConfig<T>) {}
24
+
25
+ public get units(): DebounceValue<T>[] {
26
+ return [
27
+ ...this._enqueued.map((x) => ({ ...x, state: 'enqueued' as const })),
28
+ ...this._processing.map((x) => ({ ...x, state: 'processing' as const })),
29
+ ];
30
+ }
31
+
32
+ public subscribe = (callback: (value: Debounce<T>) => any) => {
33
+ this._subscribers.push(callback);
34
+ return () => {
35
+ this._subscribers = this._subscribers.filter((x) => x !== callback);
36
+ };
37
+ };
38
+
39
+ public notify = () => {
40
+ this._subscribers.forEach((subscriber) => subscriber(this));
41
+ };
42
+
43
+ public push(value: T) {
44
+ const group = this.config.groupBy(value);
45
+ const unit = this._enqueued.find((unit) => this.config.groupBy(unit.value) === group);
46
+
47
+ if (!unit) {
48
+ this._enqueued.push({ value, enqueueTime: Date.now() });
49
+ } else if (this.config.compare(unit.value, value) >= 0) {
50
+ unit.value = value;
51
+ unit.enqueueTime = Date.now();
52
+ }
53
+
54
+ this._process(group);
55
+ }
56
+
57
+ private _process(group: string) {
58
+ if (!this._enqueued.some((unit) => this.config.groupBy(unit.value) === group)) {
59
+ return;
60
+ }
61
+
62
+ let timeout = this._timeoutByGroup[group];
63
+ timeout && clearTimeout(timeout);
64
+
65
+ if (this._processing.some((unit) => this.config.groupBy(unit.value) === group)) {
66
+ return;
67
+ }
68
+
69
+ timeout = setTimeout(() => {
70
+ const processing = this._enqueued.find((unit) => this.config.groupBy(unit.value) === group)!;
71
+ this._processing.push(processing);
72
+ this._enqueued.splice(this._enqueued.indexOf(processing), 1);
73
+ this.notify();
74
+
75
+ this.config
76
+ .callback(processing.value)
77
+ .then(() => {
78
+ this._processing.splice(this._processing.indexOf(processing), 1);
79
+ this.notify();
80
+ this._process(group);
81
+ })
82
+ .catch(() => {
83
+ this._processing.splice(this._processing.indexOf(processing), 1);
84
+ this.push(processing.value);
85
+ });
86
+ }, this.config.timeout);
87
+
88
+ this._timeoutByGroup[group] = timeout;
89
+ }
90
+ }
package/src/core/index.ts CHANGED
@@ -1,17 +1,4 @@
1
- export * from './models';
2
- export * from './client';
3
- export * from './action';
4
- export * from './reducer';
5
- export * from './state';
6
- export * from './useGetChatQuery';
7
- export * from './useGetChatListQuery';
8
- export * from './useFetchNextMutation';
9
- export * from './useGetMessagesQuery';
10
- export * from './useSignalRMonitor';
11
- export * from './useGetAccountsQuery';
12
- export * from './useAddChatMutation';
13
- export * from './useReadMonitor';
14
- export * from './useAddMemberMutation';
15
- export * from './useRemoveMemberMutation';
16
- export * from './useSendMutation';
17
- export * from './useUpdateChatNameMutation';
1
+ export * from './constants';
2
+ export * from './types';
3
+ export * from './api';
4
+ export * from './client';
@@ -0,0 +1,149 @@
1
+ export interface File {
2
+ name: string;
3
+ bytes: number;
4
+ ref: string;
5
+ }
6
+
7
+ export interface Account {
8
+ id: string;
9
+ name: string;
10
+ avatar: string;
11
+ }
12
+
13
+ export interface MessageBase {
14
+ id: string;
15
+ text: string | null;
16
+ files: File[];
17
+ sentAt: string;
18
+ sentBy: Account;
19
+ }
20
+
21
+ export interface ChatMessage extends MessageBase {
22
+ chatId: string;
23
+ }
24
+
25
+ export interface Chat {
26
+ id: string;
27
+ name: string;
28
+ members: Account[];
29
+ active: boolean;
30
+ lastReadMessageId: string | null;
31
+ }
32
+
33
+ export interface ChatListItem {
34
+ id: string;
35
+ name: string;
36
+ message: ChatMessage;
37
+ totalUnreadCount: number;
38
+ active: boolean;
39
+ lastReadMessageId: string | null;
40
+ }
41
+
42
+ export interface SendChatMessageRequest {
43
+ chatId: string;
44
+ text: string | null;
45
+ files: File[];
46
+ }
47
+
48
+ export interface MessageBody {
49
+ text: string | null;
50
+ files: File[];
51
+ }
52
+
53
+ export interface AddChatRequest {
54
+ name: string;
55
+ message?: MessageBody;
56
+ members: string[];
57
+ }
58
+
59
+ export interface ReadChatMessageRequest {
60
+ id: string;
61
+ }
62
+
63
+ export interface ReadChatMessageEvent {
64
+ chatId: string;
65
+ newLastReadMessageId: string;
66
+ readCount: number;
67
+ }
68
+
69
+ export interface RemoveChatMemberRequest {
70
+ chatId: string;
71
+ accountId: string;
72
+ deleteHistory: boolean;
73
+ }
74
+
75
+ export interface AddChatMemberRequest {
76
+ chatId: string;
77
+ accountId: string;
78
+ withHistory: boolean;
79
+ }
80
+
81
+ export interface UpdateChatNameRequest {
82
+ id: string;
83
+ name: string;
84
+ }
85
+
86
+ export function chatId(messageId: string) {
87
+ return messageId.slice(0, 36);
88
+ }
89
+
90
+ export interface ThreadWatchListItem {
91
+ id: string;
92
+ name: string;
93
+ createdById: string;
94
+ createdAt: string;
95
+ archive: boolean;
96
+ lastMessage: ThreadMessage | null;
97
+ lastReadMessageId: string | null;
98
+ }
99
+
100
+ export interface Thread {
101
+ id: string;
102
+ name: string;
103
+ createdBy: Account;
104
+ createdAt: string;
105
+ archive: boolean;
106
+ lastMessageId: string | null;
107
+ lastReadMessageId: string | null;
108
+ watch: boolean;
109
+ }
110
+
111
+ export interface ThreadMessage extends MessageBase {
112
+ threadId: string;
113
+ }
114
+
115
+ export interface SendThreadMessageRequest {
116
+ threadId: string;
117
+ body: MessageBody;
118
+ }
119
+
120
+ export type SystemMessageText =
121
+ | 'chatify://chat-created'
122
+ | 'chatify://member-added'
123
+ | 'chatify://member-removed'
124
+ | `chatify://chat-name-changed`;
125
+
126
+ export function parseThreadMessageId(messageId: string) {
127
+ const [threadId, index] = messageId.split('::', 2);
128
+ return [threadId, parseInt(index, 10)] as const;
129
+ }
130
+
131
+ export function calcThreadUnreadCount(
132
+ thread: Pick<ThreadWatchListItem, 'lastMessage' | 'lastReadMessageId'>,
133
+ ) {
134
+ const lastReadMessageIndex =
135
+ thread.lastReadMessageId != null ? parseThreadMessageId(thread.lastReadMessageId)[1] : -1;
136
+
137
+ const lastThreadMessageIndex =
138
+ thread.lastMessage?.id != null ? parseThreadMessageId(thread.lastMessage?.id)[1] : -1;
139
+
140
+ return lastThreadMessageIndex - lastReadMessageIndex;
141
+ }
142
+
143
+ export function calcThreadListUnreadCount(
144
+ threads: Pick<ThreadWatchListItem, 'lastMessage' | 'lastReadMessageId'>[],
145
+ ) {
146
+ return threads.reduce((prev, thread) => {
147
+ return prev + calcThreadUnreadCount(thread);
148
+ }, 0);
149
+ }