@webinex/chatify 1.0.0-rc2 → 1.0.1-rc3

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 (273) hide show
  1. package/dist/css/chatify.css +183 -141
  2. package/dist/esm/index.js +1 -1
  3. package/dist/esm/index.js.map +1 -1
  4. package/dist/esm/types/core/action.d.ts +110 -42
  5. package/dist/esm/types/core/client.d.ts +2 -1
  6. package/dist/esm/types/core/index.d.ts +11 -8
  7. package/dist/esm/types/core/models.d.ts +10 -4
  8. package/dist/esm/types/core/state.d.ts +36 -7
  9. package/dist/esm/types/core/useAddChatMutation.d.ts +2 -0
  10. package/dist/esm/types/core/useAddMemberMutation.d.ts +2 -0
  11. package/dist/esm/types/core/useFetchNextMutation.d.ts +3 -0
  12. package/dist/esm/types/core/useGetAccountsQuery.d.ts +1 -0
  13. package/dist/esm/types/core/useGetChatListQuery.d.ts +1 -0
  14. package/dist/{cjs/types/core/useChat.d.ts → esm/types/core/useGetChatQuery.d.ts} +1 -1
  15. package/dist/esm/types/core/useGetMessagesQuery.d.ts +4 -0
  16. package/dist/esm/types/core/useRemoveMemberMutation.d.ts +2 -0
  17. package/dist/esm/types/core/useSendMutation.d.ts +2 -0
  18. package/dist/esm/types/core/useUpdateChatNameMutation.d.ts +2 -0
  19. package/dist/esm/types/ui/AddChatButton.d.ts +2 -2
  20. package/dist/esm/types/ui/Avatar.d.ts +2 -2
  21. package/dist/esm/types/ui/ChatList/ChatList.d.ts +2 -0
  22. package/dist/esm/types/ui/ChatList/ChatListItemBox.d.ts +6 -0
  23. package/dist/esm/types/ui/ChatList/ChatListItemLastMessage.d.ts +3 -0
  24. package/dist/esm/types/ui/ChatList/ChatListItemLastMessageAuthor.d.ts +3 -0
  25. package/dist/esm/types/ui/ChatList/ChatListItemLastMessageContent.d.ts +3 -0
  26. package/dist/esm/types/ui/ChatList/ChatListItemName.d.ts +3 -0
  27. package/dist/esm/types/ui/ChatList/ChatListItemUnreadCount.d.ts +3 -0
  28. package/dist/esm/types/ui/ChatList/index.d.ts +7 -0
  29. package/dist/esm/types/ui/ChatName.d.ts +2 -2
  30. package/dist/esm/types/ui/ChatPanel/ChatBody.d.ts +5 -0
  31. package/dist/esm/types/ui/ChatPanel/ChatHeader.d.ts +5 -0
  32. package/dist/esm/types/ui/ChatPanel/ChatHeaderMembers.d.ts +5 -0
  33. package/dist/esm/types/ui/ChatPanel/ChatHeaderName.d.ts +5 -0
  34. package/dist/esm/types/ui/ChatPanel/ChatMembersButton.d.ts +5 -0
  35. package/dist/esm/types/ui/ChatPanel/ChatMembersPanel.d.ts +5 -0
  36. package/dist/esm/types/ui/ChatPanel/ChatPanel.d.ts +5 -0
  37. package/dist/esm/types/ui/ChatPanel/index.d.ts +6 -0
  38. package/dist/esm/types/ui/Chatify.d.ts +45 -23
  39. package/dist/esm/types/ui/CreateChatPanel/CreateChatForm.d.ts +11 -0
  40. package/dist/esm/types/ui/CreateChatPanel/CreateChatMemberInput.d.ts +5 -0
  41. package/dist/esm/types/ui/CreateChatPanel/CreateChatNameInput.d.ts +5 -0
  42. package/dist/esm/types/ui/CreateChatPanel/CreateChatPanel.d.ts +2 -0
  43. package/dist/esm/types/ui/CreateChatPanel/index.d.ts +4 -0
  44. package/dist/esm/types/ui/Icon.d.ts +13 -4
  45. package/dist/esm/types/ui/InputBox/InputBox.d.ts +2 -0
  46. package/dist/esm/types/ui/InputBox/InputFilesBox.d.ts +2 -0
  47. package/dist/esm/types/ui/InputBox/InputSubmitButtonBox.d.ts +5 -0
  48. package/dist/esm/types/ui/InputBox/InputTextBox.d.ts +7 -0
  49. package/dist/esm/types/ui/InputBox/index.d.ts +4 -0
  50. package/dist/esm/types/ui/Layout/Aside.d.ts +2 -0
  51. package/dist/esm/types/ui/Layout/Body.d.ts +2 -0
  52. package/dist/esm/types/ui/Layout/Footer.d.ts +2 -0
  53. package/dist/esm/types/ui/Layout/Header.d.ts +2 -0
  54. package/dist/esm/types/ui/Layout/Main.d.ts +2 -0
  55. package/dist/esm/types/ui/Layout/index.d.ts +5 -0
  56. package/dist/esm/types/ui/Message/MessageAuthor.d.ts +3 -0
  57. package/dist/esm/types/ui/Message/MessageBox.d.ts +6 -0
  58. package/dist/esm/types/ui/Message/MessageContent.d.ts +3 -0
  59. package/dist/esm/types/ui/Message/MessageInfoBox.d.ts +3 -0
  60. package/dist/esm/types/ui/Message/MessageRow.d.ts +6 -0
  61. package/dist/esm/types/ui/Message/MessageText.d.ts +3 -0
  62. package/dist/esm/types/ui/Message/index.d.ts +6 -0
  63. package/dist/esm/types/ui/MessageReadObserver.d.ts +6 -0
  64. package/dist/esm/types/ui/Next.d.ts +4 -0
  65. package/dist/esm/types/ui/SendingMessage/SendingMessageBox.d.ts +7 -0
  66. package/dist/esm/types/ui/SendingMessage/SendingMessageContent.d.ts +3 -0
  67. package/dist/esm/types/ui/SendingMessage/SendingMessageInfoBox.d.ts +3 -0
  68. package/dist/esm/types/ui/SendingMessage/SendingMessageText.d.ts +3 -0
  69. package/dist/esm/types/ui/SendingMessage/index.d.ts +4 -0
  70. package/dist/esm/types/ui/SystemMessage/SystemMessageBox.d.ts +6 -0
  71. package/dist/esm/types/ui/SystemMessage/SystemMessageRow.d.ts +9 -0
  72. package/dist/esm/types/ui/SystemMessage/index.d.ts +2 -0
  73. package/dist/esm/types/{util → ui}/customize.d.ts +2 -3
  74. package/dist/esm/types/ui/index.d.ts +6 -6
  75. package/dist/esm/types/ui/localizer.d.ts +5 -0
  76. package/dist/esm/types/util/index.d.ts +0 -1
  77. package/dist/index.d.ts +353 -142
  78. package/package.json +92 -90
  79. package/src/ChatifyContext.tsx +41 -41
  80. package/src/core/action.tsx +405 -319
  81. package/src/core/client.ts +143 -137
  82. package/src/core/index.ts +17 -14
  83. package/src/core/models.tsx +82 -75
  84. package/src/core/reducer.tsx +87 -86
  85. package/src/core/state.ts +92 -38
  86. package/src/core/useAddChatMutation.tsx +22 -0
  87. package/src/core/useAddMemberMutation.tsx +25 -0
  88. package/src/core/useFetchNextMutation.tsx +28 -0
  89. package/src/core/useGetAccountsQuery.tsx +33 -0
  90. package/src/core/useGetChatListQuery.tsx +33 -0
  91. package/src/core/useGetChatQuery.tsx +34 -0
  92. package/src/core/useGetMessagesQuery.tsx +35 -0
  93. package/src/core/useReadMonitor.tsx +32 -31
  94. package/src/core/useRemoveMemberMutation.tsx +23 -0
  95. package/src/core/useSendMutation.tsx +24 -0
  96. package/src/core/useSignalRMonitor.tsx +66 -52
  97. package/src/core/useUpdateChatNameMutation.tsx +23 -0
  98. package/src/index.ts +3 -3
  99. package/src/{ui/styles → styles}/aside.scss +94 -94
  100. package/src/styles/chat.scss +222 -0
  101. package/src/styles/index.scss +79 -0
  102. package/src/{ui/styles → styles}/keyframes.scss +14 -14
  103. package/src/{ui/styles → styles}/mixins.scss +20 -20
  104. package/src/styles/settings.scss +5 -0
  105. package/src/{ui/styles → styles}/variables.scss +10 -10
  106. package/src/ui/AddChatButton.tsx +15 -19
  107. package/src/ui/Avatar.tsx +18 -18
  108. package/src/ui/ChatList/ChatList.tsx +42 -0
  109. package/src/ui/ChatList/ChatListItemBox.tsx +22 -0
  110. package/src/ui/ChatList/ChatListItemLastMessage.tsx +13 -0
  111. package/src/ui/ChatList/ChatListItemLastMessageAuthor.tsx +20 -0
  112. package/src/ui/ChatList/ChatListItemLastMessageContent.tsx +21 -0
  113. package/src/ui/ChatList/ChatListItemName.tsx +13 -0
  114. package/src/ui/ChatList/ChatListItemUnreadCount.tsx +12 -0
  115. package/src/ui/ChatList/index.ts +7 -0
  116. package/src/ui/ChatName.tsx +10 -15
  117. package/src/ui/ChatPanel/ChatBody.tsx +44 -0
  118. package/src/ui/ChatPanel/ChatHeader.tsx +33 -0
  119. package/src/ui/{ChatHeaderMembers.tsx → ChatPanel/ChatHeaderMembers.tsx} +26 -30
  120. package/src/ui/ChatPanel/ChatHeaderName.tsx +67 -0
  121. package/src/ui/ChatPanel/ChatMembersButton.tsx +21 -0
  122. package/src/ui/ChatPanel/ChatMembersPanel.tsx +117 -0
  123. package/src/ui/ChatPanel/ChatPanel.tsx +27 -0
  124. package/src/ui/ChatPanel/index.ts +6 -0
  125. package/src/ui/Chatify.tsx +148 -106
  126. package/src/ui/CreateChatPanel/CreateChatForm.tsx +36 -0
  127. package/src/ui/CreateChatPanel/CreateChatMemberInput.tsx +66 -0
  128. package/src/ui/CreateChatPanel/CreateChatNameInput.tsx +25 -0
  129. package/src/ui/CreateChatPanel/CreateChatPanel.tsx +33 -0
  130. package/src/ui/CreateChatPanel/index.ts +4 -0
  131. package/src/ui/Icon.tsx +33 -21
  132. package/src/ui/InputBox/InputBox.tsx +38 -0
  133. package/src/ui/InputBox/InputFilesBox.tsx +9 -0
  134. package/src/ui/InputBox/InputSubmitButtonBox.tsx +17 -0
  135. package/src/ui/InputBox/InputTextBox.tsx +50 -0
  136. package/src/ui/InputBox/index.ts +4 -0
  137. package/src/ui/Layout/Aside.tsx +10 -0
  138. package/src/ui/Layout/Body.tsx +10 -0
  139. package/src/ui/Layout/Footer.tsx +3 -0
  140. package/src/ui/Layout/Header.tsx +10 -0
  141. package/src/ui/Layout/Main.tsx +15 -0
  142. package/src/ui/Layout/index.ts +5 -0
  143. package/src/ui/Message/MessageAuthor.tsx +13 -0
  144. package/src/ui/Message/MessageBox.tsx +20 -0
  145. package/src/ui/Message/MessageContent.tsx +13 -0
  146. package/src/ui/Message/MessageInfoBox.tsx +25 -0
  147. package/src/ui/Message/MessageRow.tsx +24 -0
  148. package/src/ui/Message/MessageText.tsx +7 -0
  149. package/src/ui/Message/index.ts +6 -0
  150. package/src/ui/MessageReadObserver.tsx +45 -0
  151. package/src/ui/MessageSkeleton.tsx +19 -19
  152. package/src/ui/Next.tsx +48 -0
  153. package/src/ui/SendingMessage/SendingMessageBox.tsx +16 -0
  154. package/src/ui/SendingMessage/SendingMessageContent.tsx +13 -0
  155. package/src/ui/SendingMessage/SendingMessageInfoBox.tsx +13 -0
  156. package/src/ui/SendingMessage/SendingMessageText.tsx +7 -0
  157. package/src/ui/SendingMessage/index.ts +4 -0
  158. package/src/ui/SystemMessage/SystemMessageBox.tsx +20 -0
  159. package/src/ui/SystemMessage/SystemMessageRow.tsx +43 -0
  160. package/src/ui/SystemMessage/index.ts +2 -0
  161. package/src/{util → ui}/customize.tsx +45 -45
  162. package/src/ui/index.ts +11 -11
  163. package/src/ui/localizer.tsx +80 -68
  164. package/src/util/index.ts +2 -3
  165. package/src/util/uniqBy.tsx +17 -17
  166. package/src/util/uniqId.tsx +3 -3
  167. package/dist/cjs/index.js +0 -2
  168. package/dist/cjs/index.js.map +0 -1
  169. package/dist/cjs/types/ChatifyContext.d.ts +0 -11
  170. package/dist/cjs/types/core/action.d.ts +0 -76
  171. package/dist/cjs/types/core/client.d.ts +0 -35
  172. package/dist/cjs/types/core/index.d.ts +0 -14
  173. package/dist/cjs/types/core/models.d.ts +0 -64
  174. package/dist/cjs/types/core/reducer.d.ts +0 -11
  175. package/dist/cjs/types/core/state.d.ts +0 -25
  176. package/dist/cjs/types/core/useAccounts.d.ts +0 -1
  177. package/dist/cjs/types/core/useAddChat.d.ts +0 -2
  178. package/dist/cjs/types/core/useAddMember.d.ts +0 -2
  179. package/dist/cjs/types/core/useAddMessage.d.ts +0 -5
  180. package/dist/cjs/types/core/useChatList.d.ts +0 -1
  181. package/dist/cjs/types/core/useLoadMore.d.ts +0 -3
  182. package/dist/cjs/types/core/useMessages.d.ts +0 -15
  183. package/dist/cjs/types/core/useMutation.d.ts +0 -12
  184. package/dist/cjs/types/core/useQuery.d.ts +0 -7
  185. package/dist/cjs/types/core/useReadMonitor.d.ts +0 -1
  186. package/dist/cjs/types/core/useRemoveMember.d.ts +0 -2
  187. package/dist/cjs/types/core/useSignalRMonitor.d.ts +0 -2
  188. package/dist/cjs/types/index.d.ts +0 -3
  189. package/dist/cjs/types/ui/AddChat.d.ts +0 -1
  190. package/dist/cjs/types/ui/AddChatButton.d.ts +0 -2
  191. package/dist/cjs/types/ui/Aside.d.ts +0 -1
  192. package/dist/cjs/types/ui/Avatar.d.ts +0 -6
  193. package/dist/cjs/types/ui/Chat.d.ts +0 -4
  194. package/dist/cjs/types/ui/ChatBody.d.ts +0 -4
  195. package/dist/cjs/types/ui/ChatHeader.d.ts +0 -4
  196. package/dist/cjs/types/ui/ChatHeaderMembers.d.ts +0 -5
  197. package/dist/cjs/types/ui/ChatHeaderSettingsButton.d.ts +0 -5
  198. package/dist/cjs/types/ui/ChatListItem.d.ts +0 -11
  199. package/dist/cjs/types/ui/ChatName.d.ts +0 -5
  200. package/dist/cjs/types/ui/ChatSettings.d.ts +0 -1
  201. package/dist/cjs/types/ui/Chatify.d.ts +0 -49
  202. package/dist/cjs/types/ui/Footer.d.ts +0 -2
  203. package/dist/cjs/types/ui/Header.d.ts +0 -2
  204. package/dist/cjs/types/ui/Icon.d.ts +0 -7
  205. package/dist/cjs/types/ui/InputForm.d.ts +0 -1
  206. package/dist/cjs/types/ui/LoadMore.d.ts +0 -4
  207. package/dist/cjs/types/ui/Main.d.ts +0 -1
  208. package/dist/cjs/types/ui/Message.d.ts +0 -18
  209. package/dist/cjs/types/ui/MessageSkeleton.d.ts +0 -4
  210. package/dist/cjs/types/ui/SendingMessage.d.ts +0 -10
  211. package/dist/cjs/types/ui/SystemMessage.d.ts +0 -8
  212. package/dist/cjs/types/ui/index.d.ts +0 -11
  213. package/dist/cjs/types/ui/localizer.d.ts +0 -32
  214. package/dist/cjs/types/util/customize.d.ts +0 -12
  215. package/dist/cjs/types/util/index.d.ts +0 -3
  216. package/dist/cjs/types/util/uniqBy.d.ts +0 -1
  217. package/dist/cjs/types/util/uniqId.d.ts +0 -1
  218. package/dist/esm/types/core/useAccounts.d.ts +0 -1
  219. package/dist/esm/types/core/useAddChat.d.ts +0 -2
  220. package/dist/esm/types/core/useAddMember.d.ts +0 -2
  221. package/dist/esm/types/core/useAddMessage.d.ts +0 -5
  222. package/dist/esm/types/core/useChat.d.ts +0 -3
  223. package/dist/esm/types/core/useChatList.d.ts +0 -1
  224. package/dist/esm/types/core/useLoadMore.d.ts +0 -3
  225. package/dist/esm/types/core/useMessages.d.ts +0 -15
  226. package/dist/esm/types/core/useMutation.d.ts +0 -12
  227. package/dist/esm/types/core/useQuery.d.ts +0 -7
  228. package/dist/esm/types/core/useRemoveMember.d.ts +0 -2
  229. package/dist/esm/types/ui/AddChat.d.ts +0 -1
  230. package/dist/esm/types/ui/Aside.d.ts +0 -1
  231. package/dist/esm/types/ui/Chat.d.ts +0 -4
  232. package/dist/esm/types/ui/ChatBody.d.ts +0 -4
  233. package/dist/esm/types/ui/ChatHeader.d.ts +0 -4
  234. package/dist/esm/types/ui/ChatHeaderMembers.d.ts +0 -5
  235. package/dist/esm/types/ui/ChatHeaderSettingsButton.d.ts +0 -5
  236. package/dist/esm/types/ui/ChatListItem.d.ts +0 -11
  237. package/dist/esm/types/ui/ChatSettings.d.ts +0 -1
  238. package/dist/esm/types/ui/Footer.d.ts +0 -2
  239. package/dist/esm/types/ui/Header.d.ts +0 -2
  240. package/dist/esm/types/ui/InputForm.d.ts +0 -1
  241. package/dist/esm/types/ui/LoadMore.d.ts +0 -4
  242. package/dist/esm/types/ui/Main.d.ts +0 -1
  243. package/dist/esm/types/ui/Message.d.ts +0 -18
  244. package/dist/esm/types/ui/SendingMessage.d.ts +0 -10
  245. package/dist/esm/types/ui/SystemMessage.d.ts +0 -8
  246. package/src/core/useAccounts.tsx +0 -11
  247. package/src/core/useAddChat.tsx +0 -12
  248. package/src/core/useAddMember.tsx +0 -12
  249. package/src/core/useAddMessage.tsx +0 -40
  250. package/src/core/useChat.tsx +0 -12
  251. package/src/core/useChatList.tsx +0 -10
  252. package/src/core/useLoadMore.tsx +0 -42
  253. package/src/core/useMessages.tsx +0 -23
  254. package/src/core/useMutation.tsx +0 -48
  255. package/src/core/useQuery.tsx +0 -45
  256. package/src/core/useRemoveMember.tsx +0 -12
  257. package/src/ui/AddChat.tsx +0 -55
  258. package/src/ui/Aside.tsx +0 -41
  259. package/src/ui/Chat.tsx +0 -26
  260. package/src/ui/ChatBody.tsx +0 -43
  261. package/src/ui/ChatHeader.tsx +0 -33
  262. package/src/ui/ChatHeaderSettingsButton.tsx +0 -26
  263. package/src/ui/ChatListItem.tsx +0 -101
  264. package/src/ui/ChatSettings.tsx +0 -59
  265. package/src/ui/Footer.tsx +0 -7
  266. package/src/ui/Header.tsx +0 -14
  267. package/src/ui/InputForm.tsx +0 -51
  268. package/src/ui/LoadMore.tsx +0 -40
  269. package/src/ui/Main.tsx +0 -16
  270. package/src/ui/Message.tsx +0 -118
  271. package/src/ui/SendingMessage.tsx +0 -50
  272. package/src/ui/SystemMessage.tsx +0 -32
  273. package/src/ui/styles/index.scss +0 -248
@@ -1,319 +1,405 @@
1
- import type { MutationState, QueryState, State } from './state';
2
- import { Account, ChatListItem, Message, ReadEvent } from './models';
3
- import { MessageState } from './useMessages';
4
-
5
- function updateQuery<TData>(
6
- state: State,
7
- key: string,
8
- mutation: (queryState: QueryState<TData> | undefined) => QueryState<TData> | undefined,
9
- ) {
10
- state = {
11
- ...state,
12
- query: {
13
- ...state.query,
14
- },
15
- };
16
-
17
- const result = mutation(state.query[key]);
18
- if (result) {
19
- state.query[key] = result;
20
- }
21
- return state;
22
- }
23
-
24
- function updateMutation(
25
- state: State,
26
- key: string,
27
- mutation: (mutationState: MutationState | undefined) => MutationState | undefined,
28
- ) {
29
- state = {
30
- ...state,
31
- mutation: {
32
- ...state.mutation,
33
- },
34
- };
35
-
36
- const result = mutation(state.mutation[key]);
37
- if (result) {
38
- state.mutation[key] = result;
39
- }
40
- return state;
41
- }
42
-
43
- export const ACTIONS = {
44
- query_fetch: (state: State, { key }: { key: string }): State => {
45
- return updateQuery(state, key, (x) => ({ ...x, isFetching: true, uninitialized: false }));
46
- },
47
-
48
- query_resolve: (state: State, { key, data }: { key: string; data: any[] }): State => {
49
- return updateQuery(state, key, (x) => ({ ...x!, isFetching: false, error: undefined, data }));
50
- },
51
-
52
- query_reject: (state: State, { key, error }: { key: string; error: any }): State => {
53
- return updateQuery(state, key, (x) => ({ ...x!, isFetching: false, error }));
54
- },
55
-
56
- mutation_fetch: (state: State, { key }: { key: string }): State => {
57
- return updateMutation(state, key, (x) => ({ ...x, isFetching: true }));
58
- },
59
-
60
- mutation_resolve: (state: State, { key }: { key: string }): State => {
61
- return updateMutation(state, key, (x) => ({ ...x, isFetching: false, error: undefined }));
62
- },
63
-
64
- mutation_reject: (state: State, { key, error }: { key: string; error: any }): State => {
65
- return updateMutation(state, key, (x) => ({ ...x, isFetching: false, error }));
66
- },
67
-
68
- update: (state: State, { mutation }: { mutation: (state: State) => State }): State => {
69
- return mutation(state);
70
- },
71
-
72
- chat_open: (state: State, { chatId }: { chatId: string }): State => {
73
- return { ...state, ui: { ...state.ui, view: 'chat', chatId } };
74
- },
75
-
76
- new_chat_open: (state: State): State => {
77
- return { ...state, ui: { ...state.ui, view: 'new-chat', chatId: undefined } };
78
- },
79
-
80
- chat_settings_open: (state: State, { chatId }: { chatId: string }): State => {
81
- return { ...state, ui: { ...state.ui, view: 'chat-settings', chatId } };
82
- },
83
-
84
- message_received: (
85
- state: State,
86
- { message, requestId }: { message: Message; requestId: string },
87
- ): State => {
88
- if (state.query['messages.' + message.chatId]?.data !== undefined) {
89
- state = {
90
- ...state,
91
- query: {
92
- ...state.query,
93
- ['messages.' + message.chatId]: {
94
- ...state.query['messages.' + message.chatId],
95
- data: [{ type: 'message', ...message }, ...state.query['messages.' + message.chatId].data].filter(
96
- (x: MessageState) => x.type !== 'sending' || x.requestId !== requestId,
97
- ),
98
- },
99
- },
100
- };
101
- }
102
-
103
- if (state.query['chat-list'].data !== undefined) {
104
- state = {
105
- ...state,
106
- query: {
107
- ...state.query,
108
- 'chat-list': {
109
- ...state.query['chat-list'],
110
- data: state.query['chat-list'].data.map((x: ChatListItem) =>
111
- x.id === message.chatId
112
- ? { ...x, message, unreadCount: message.read ? x.unreadCount : x.unreadCount + 1 }
113
- : x,
114
- ),
115
- },
116
- },
117
- };
118
- }
119
-
120
- return state;
121
- },
122
-
123
- chat_created: (state: State, { chat }: { chat: ChatListItem; requestId?: string }): State => {
124
- if (state.query['chat-list']?.data === undefined) {
125
- return state;
126
- }
127
-
128
- return {
129
- ...state,
130
- query: {
131
- ...state.query,
132
- 'chat-list': {
133
- ...state.query['chat-list'],
134
- data: [chat, ...state.query['chat-list'].data!],
135
- },
136
- },
137
- };
138
- },
139
-
140
- read: (state: State, { id, timestamp }: { id: string; timestamp: number }): State => {
141
- return {
142
- ...state,
143
- read: {
144
- ...state.read,
145
- queued: [...state.read.queued, id],
146
- timestamp,
147
- },
148
- };
149
- },
150
-
151
- read_send: (state: State, { ids }: { ids: string[] }): State => {
152
- return {
153
- ...state,
154
- read: {
155
- ...state.read,
156
- queued: state.read.queued.filter((x) => !ids.includes(x)),
157
- sent: [...state.read.sent, ...ids],
158
- },
159
- };
160
- },
161
-
162
- read_reject: (state: State, { ids, timestamp }: { ids: string[]; timestamp: number }): State => {
163
- return {
164
- ...state,
165
- read: {
166
- ...state.read,
167
- queued: [...state.read.queued, ...ids],
168
- sent: state.read.sent.filter((x) => !ids.includes(x)),
169
- timestamp,
170
- },
171
- };
172
- },
173
-
174
- read_received: (state: State, { events }: { events: ReadEvent[] }): State => {
175
- const ids = events.map((x) => x.messageId);
176
-
177
- state = {
178
- ...state,
179
- query: {
180
- ...state.query,
181
- },
182
- read: {
183
- ...state.read,
184
- sent: state.read.sent.filter((x) => !ids.includes(x)),
185
- },
186
- };
187
-
188
- Object.keys(state.query)
189
- .filter((x) => x.startsWith('messages.'))
190
- .forEach((key) => {
191
- state.query[key] = { ...state.query[key] };
192
- const queryState: QueryState<MessageState[]> = state.query[key];
193
-
194
- queryState.data = queryState.data?.map((x) => {
195
- if (x.type === 'message' && ids.includes(x.id)) {
196
- return { ...x, read: true };
197
- }
198
-
199
- return x;
200
- });
201
- });
202
-
203
- state.query['chat-list'] = { ...state.query['chat-list'] };
204
- const chatListState: QueryState<ChatListItem[]> = state.query['chat-list'];
205
- chatListState.data = chatListState.data?.map((x) =>
206
- ids.includes(x.message.id) ? { ...x, message: { ...x.message, read: true } } : x,
207
- );
208
-
209
- chatListState.data = chatListState.data?.map((chat) => ({
210
- ...chat,
211
- unreadCount: chat.unreadCount - events.filter((x) => x.chatId === chat.id).length,
212
- }));
213
-
214
- return state;
215
- },
216
-
217
- member_added: (
218
- state: State,
219
- {
220
- chatId,
221
- chatName,
222
- account,
223
- me,
224
- message,
225
- }: { chatId: string; chatName: string; account: Account; me: string; message: Message },
226
- ): State => {
227
- state = {
228
- ...state,
229
- query: {
230
- ...state.query,
231
- },
232
- };
233
-
234
- if (state.query['chat.' + chatId]?.data !== undefined) {
235
- state.query['chat.' + chatId] = {
236
- ...state.query['chat.' + chatId],
237
- data: { ...state.query['chat.' + chatId].data },
238
- };
239
- state.query['chat.' + chatId].data.members = [...state.query['chat.' + chatId].data.members, account];
240
- }
241
-
242
- if (state.query['messages.' + chatId]?.data !== undefined) {
243
- state.query['messages.' + chatId] = {
244
- ...state.query['messages.' + chatId],
245
- data: [{ type: 'message', ...message }, ...state.query['messages.' + chatId].data],
246
- };
247
- }
248
-
249
- if (account.id !== me && state.query['chat-list'].data !== undefined) {
250
- state.query['chat-list'] = { ...state.query['chat-list'] };
251
- state.query['chat-list'].data = state.query['chat-list'].data.map((x: ChatListItem) =>
252
- x.id === chatId ? { ...x, message: { ...message } } : x,
253
- );
254
- }
255
-
256
- if (account.id === me && state.query['chat-list'].data !== undefined) {
257
- const listItem: ChatListItem = {
258
- id: chatId,
259
- name: chatName,
260
- message: { ...message },
261
- unreadCount: 0,
262
- };
263
-
264
- state.query['chat-list'] = {
265
- ...state.query['chat-list'],
266
- data: [...state.query['chat-list'].data, listItem],
267
- };
268
- }
269
-
270
- return state;
271
- },
272
-
273
- member_removed: (
274
- state: State,
275
- {
276
- chatId,
277
- accountId,
278
- deleteHistory,
279
- me,
280
- }: { chatId: string; accountId: string; deleteHistory: boolean; me: string },
281
- ): State => {
282
- state = {
283
- ...state,
284
- query: {
285
- ...state.query,
286
- },
287
- };
288
-
289
- if (state.query['chat.' + chatId]?.data !== undefined) {
290
- state.query['chat.' + chatId] = {
291
- ...state.query['chat.' + chatId],
292
- data: { ...state.query['chat.' + chatId].data },
293
- };
294
- state.query['chat.' + chatId].data.members = state.query['chat.' + chatId].data.members.filter(
295
- (x: Account) => x.id !== accountId,
296
- );
297
- }
298
-
299
- if (accountId === me && deleteHistory && state.query['chat-list']?.data) {
300
- state.query['chat-list'] = { ...state.query['chat-list'] };
301
- state.query['chat-list'].data = state.query['chat-list'].data.filter(
302
- (x: ChatListItem) => x.id !== chatId,
303
- );
304
- }
305
-
306
- if (accountId === me && deleteHistory && state.query['chat-list']?.data && state.ui.chatId === chatId) {
307
- state.ui = { ...state.ui, chatId: state.query['chat-list']?.data.at(0)?.id };
308
- }
309
-
310
- return state;
311
- },
312
- };
313
-
314
- export type Action = {
315
- [K in keyof typeof ACTIONS]: {
316
- type: K;
317
- data: Parameters<(typeof ACTIONS)[K]>[1];
318
- };
319
- }[keyof typeof ACTIONS];
1
+ import type { State } from './state';
2
+ import { Account, Chat, ChatListItem, Message, ReadEvent, File } from './models';
3
+
4
+ export const ACTIONS = {
5
+ update: (state: State, { mutation }: { mutation: (state: State) => State }) => {
6
+ mutation(state);
7
+ },
8
+
9
+ messages_fetch: (state: State, { chatId }: { chatId: string }) => {
10
+ state.query.messages[chatId] = {
11
+ ...state.query.messages[chatId],
12
+ uninitialized: false,
13
+ isFetching: true,
14
+ };
15
+ },
16
+
17
+ messages_fulfilled: (
18
+ state: State,
19
+ { chatId, messages, hasMore }: { chatId: string; messages: Message[]; hasMore: boolean },
20
+ ) => {
21
+ const qState = state.query.messages[chatId];
22
+
23
+ qState.error = undefined;
24
+ qState.isFetching = false;
25
+ qState.data = messages.map((x) => ({ type: 'message', ...x }));
26
+
27
+ if (hasMore) {
28
+ qState.data!.push({ type: 'next' });
29
+ }
30
+ },
31
+
32
+ messages_rejected: (state: State, { chatId, error }: { chatId: string; error: any }) => {
33
+ const qState = state.query.messages[chatId];
34
+ qState.error = error;
35
+ qState.isFetching = false;
36
+ },
37
+
38
+ fetchNext_fetch: (state: State, { chatId }: { chatId: string }) => {
39
+ state.mutation.fetchNext = { isFetching: true };
40
+ },
41
+
42
+ fetchNext_fulfilled: (
43
+ state: State,
44
+ { chatId, messages, hasMore }: { chatId: string; messages: Message[]; hasMore: boolean },
45
+ ) => {
46
+ state.mutation.fetchNext = { isFetching: false, error: undefined };
47
+ state.query.messages[chatId].data = state.query.messages[chatId].data!.filter((x) => x.type !== 'next');
48
+ state.query.messages[chatId].data!.push(...messages.map((x) => ({ type: 'message' as const, ...x })));
49
+
50
+ if (hasMore) state.query.messages[chatId].data!.push({ type: 'next' });
51
+ },
52
+
53
+ fetchNext_rejected: (state: State, { chatId, error }: { chatId: string; error: any }) => {
54
+ state.mutation.fetchNext = { isFetching: false, error };
55
+ },
56
+
57
+ chatList_fetch: (state: State) => {
58
+ state.query.chatList.isFetching = true;
59
+ state.query.chatList.uninitialized = false;
60
+ },
61
+
62
+ chatList_fulfilled: (state: State, { chats }: { chats: ChatListItem[] }) => {
63
+ chats = chats.sort((a, b) => -a.message.id.substring(47).localeCompare(b.message.id.substring(47)));
64
+
65
+ state.query.chatList.isFetching = false;
66
+ state.query.chatList.error = undefined;
67
+ state.query.chatList.data = chats;
68
+
69
+ if (state.ui.chatId === undefined && chats.length > 0) {
70
+ state.ui.view = 'chat';
71
+ state.ui.chatId = chats[0].id;
72
+ }
73
+ },
74
+
75
+ chatList_rejected: (state: State, { error }: { error: any }) => {
76
+ state.query.chatList.isFetching = false;
77
+ state.query.chatList.error = error;
78
+ },
79
+
80
+ removeMember_fetch: (state: State) => {
81
+ state.mutation.removeMember = { isFetching: true };
82
+ },
83
+
84
+ removeMember_fulfilled: (state: State) => {
85
+ state.mutation.removeMember = { isFetching: false, error: undefined };
86
+ },
87
+
88
+ removeMember_rejected: (state: State, { error }: { error: any }) => {
89
+ state.mutation.removeMember = { isFetching: false, error };
90
+ },
91
+
92
+ addMember_fetch: (state: State) => {
93
+ state.mutation.addMember = { isFetching: true };
94
+ },
95
+
96
+ addMember_fulfilled: (state: State) => {
97
+ state.mutation.addMember = { isFetching: false, error: undefined };
98
+ },
99
+
100
+ addMember_rejected: (state: State, { error }: { error: any }) => {
101
+ state.mutation.addMember = { isFetching: false, error };
102
+ },
103
+
104
+ updateChatName_fetch: (state: State) => {
105
+ state.mutation.updateChatName = { isFetching: true };
106
+ },
107
+
108
+ updateChatName_fulfilled: (state: State) => {
109
+ state.mutation.updateChatName = { isFetching: false, error: undefined };
110
+ },
111
+
112
+ updateChatName_rejected: (state: State, { error }: { error: any }) => {
113
+ state.mutation.updateChatName = { isFetching: false, error };
114
+ },
115
+
116
+ addChat_fetch: (state: State) => {
117
+ state.mutation.addChat = { isFetching: true };
118
+ },
119
+
120
+ addChat_fulfilled: (state: State) => {
121
+ state.mutation.addChat = { isFetching: false, error: undefined };
122
+ },
123
+
124
+ addChat_rejected: (state: State, { error }: { error: any }) => {
125
+ state.mutation.addChat = { isFetching: false, error };
126
+ },
127
+
128
+ accounts_fetch: (state: State) => {
129
+ state.query.accounts = { isFetching: true, uninitialized: false };
130
+ },
131
+
132
+ accounts_fulfilled: (state: State, { accounts }: { accounts: Account[] }) => {
133
+ state.query.accounts.data = accounts;
134
+ state.query.accounts.isFetching = false;
135
+ state.query.accounts.error = undefined;
136
+ },
137
+
138
+ accounts_rejected: (state: State, { error }: { error: any }) => {
139
+ state.query.accounts.isFetching = false;
140
+ state.query.accounts.error = error;
141
+ },
142
+
143
+ chat_open: (state: State, { chatId }: { chatId: string }) => {
144
+ state.ui.chatId = chatId;
145
+ state.ui.view = 'chat';
146
+ },
147
+
148
+ new_chat_open: (state: State) => {
149
+ state.ui.chatId = undefined;
150
+ state.ui.view = 'new-chat';
151
+ },
152
+
153
+ toggle_members_view: (state: State) => {
154
+ state.ui.showMembers = !state.ui.showMembers;
155
+ },
156
+
157
+ message_received: (
158
+ state: State,
159
+ { message, requestId, me }: { message: Message; requestId: string; me: string },
160
+ ) => {
161
+ const messagesState = state.query.messages[message.chatId];
162
+
163
+ if (messagesState?.data) {
164
+ messagesState.data.unshift({ type: 'message', ...message });
165
+ messagesState.data = messagesState.data.filter(
166
+ (x) => x.type !== 'sending' || x.requestId !== requestId,
167
+ );
168
+ }
169
+
170
+ const chatListItemState = state.query.chatList?.data?.find((x) => x.id === message.chatId);
171
+
172
+ if (chatListItemState) {
173
+ chatListItemState.message = message;
174
+ }
175
+
176
+ if (chatListItemState && message.sentBy.id !== me) {
177
+ chatListItemState.totalUnreadCount++;
178
+ }
179
+
180
+ if (chatListItemState && message.sentBy.id === me) {
181
+ chatListItemState.lastReadMessageId = message.id;
182
+ chatListItemState.totalUnreadCount = 0;
183
+ }
184
+ },
185
+
186
+ chat_created: (state: State, { chat }: { chat: ChatListItem; requestId?: string }) => {
187
+ state.query.chatList?.data?.unshift(chat);
188
+ },
189
+
190
+ read: (state: State, { id, timestamp }: { id: string; timestamp: number }) => {
191
+ const queuedSameChat = state.queue.read.queued.filter((x) => x.substring(0, 36) === id.substring(0, 36));
192
+
193
+ if (queuedSameChat.some((x) => x.localeCompare(id) >= 0)) {
194
+ return;
195
+ }
196
+
197
+ state.queue.read.queued.filter((x) => queuedSameChat.includes(x));
198
+ state.queue.read.queued.push(id);
199
+ state.queue.read.timestamp = timestamp;
200
+ },
201
+
202
+ read_send: (state: State, { id }: { id: string }) => {
203
+ state.queue.read.queued = state.queue.read.queued.filter((x) => x !== id);
204
+ state.queue.read.processing.push(id);
205
+ },
206
+
207
+ read_reject: (state: State, { id, timestamp }: { id: string; timestamp: number }) => {
208
+ state.queue.read.queued.push(id);
209
+ state.queue.read.processing = state.queue.read.processing.filter((x) => x !== id);
210
+ state.queue.read.timestamp = timestamp;
211
+ },
212
+
213
+ read_received: (state: State, { events }: { events: ReadEvent[] }) => {
214
+ state.queue.read.processing = state.queue.read.processing.filter((item) => {
215
+ const event = events.find((x) => x.chatId === item.substring(0, 36));
216
+ return !event || event.newLastReadMessageId.localeCompare(item) >= 0;
217
+ });
218
+
219
+ for (const event of events) {
220
+ state.queue.read.processing = state.queue.read.processing.filter(
221
+ (x) => x.substring(0, 36) !== event.chatId || x.localeCompare(event.newLastReadMessageId) > 0,
222
+ );
223
+ const chatListItem = state.query.chatList.data?.find((x) => x.id === event.chatId);
224
+
225
+ if (chatListItem) {
226
+ chatListItem.lastReadMessageId = event.newLastReadMessageId;
227
+ chatListItem.totalUnreadCount = chatListItem.totalUnreadCount - event.readCount;
228
+ }
229
+ }
230
+ },
231
+
232
+ member_added: (
233
+ state: State,
234
+ {
235
+ chatId,
236
+ chatName,
237
+ account,
238
+ me,
239
+ message,
240
+ withHistory,
241
+ }: {
242
+ chatId: string;
243
+ chatName: string;
244
+ account: Account;
245
+ me: string;
246
+ message: Message;
247
+ withHistory: boolean;
248
+ },
249
+ ) => {
250
+ const { chats, messages, chatList } = state.query;
251
+ chats[chatId]?.data?.members.push(account);
252
+ const chatListItem = chatList?.data?.find((x) => x.id === chatId);
253
+
254
+ if (account.id !== me && chatListItem != null) {
255
+ chatListItem.message = message;
256
+ chatListItem.totalUnreadCount++;
257
+ }
258
+
259
+ messages[chatId]?.data?.unshift({ type: 'message', ...message });
260
+
261
+ if (account.id === me && chatList.data !== undefined && !chatListItem) {
262
+ chatList.data.unshift({
263
+ id: chatId,
264
+ name: chatName,
265
+ message,
266
+ totalUnreadCount: 1,
267
+ active: true,
268
+ lastReadMessageId: null,
269
+ });
270
+ }
271
+
272
+ if (account.id === me && chatListItem) {
273
+ chatListItem.active = true;
274
+ chatListItem.message = message;
275
+ chatListItem.totalUnreadCount++;
276
+ }
277
+
278
+ return state;
279
+ },
280
+
281
+ member_removed: (
282
+ state: State,
283
+ {
284
+ chatId,
285
+ accountId,
286
+ deleteHistory,
287
+ me,
288
+ message,
289
+ }: { chatId: string; accountId: string; deleteHistory: boolean; me: string; message: Message },
290
+ ) => {
291
+ const { chats, chatList } = state.query;
292
+ const chat = chats[chatId];
293
+
294
+ if (chat?.data) {
295
+ chat.data.members = chat.data.members.filter((x) => x.id !== accountId);
296
+ }
297
+
298
+ if (accountId === me && state.query.chats[chatId].data) {
299
+ delete state.query.chats[chatId];
300
+ }
301
+
302
+ if (accountId === me && deleteHistory && chatList?.data) {
303
+ chatList.data = chatList.data.filter((x) => x.id !== chatId);
304
+
305
+ if (state.ui.chatId === chatId) {
306
+ state.ui.chatId = chatList.data.at(0)?.id;
307
+ }
308
+ }
309
+
310
+ if (accountId === me && !deleteHistory && chatList?.data) {
311
+ const listItem = chatList.data.find((x) => x.id === chatId)!;
312
+ listItem.active = false;
313
+ }
314
+
315
+ if ((accountId !== me || !deleteHistory) && state.query.messages[chatId].data) {
316
+ state.query.messages[chatId].data!.unshift({ ...message, type: 'message' });
317
+ }
318
+
319
+ if ((accountId !== me || !deleteHistory) && state.query.chatList.data) {
320
+ const listItem = state.query.chatList.data.find((x) => x.id === chatId)!;
321
+ listItem.message = message;
322
+ listItem.totalUnreadCount++;
323
+ }
324
+
325
+ if (accountId === me && deleteHistory && state.query.messages[chatId].data) {
326
+ delete state.query.messages[chatId];
327
+ }
328
+ },
329
+
330
+ chat_fetch: (state: State, { chatId }: { chatId: string }) => {
331
+ state.query.chats[chatId] = { isFetching: true, uninitialized: false, data: undefined, error: undefined };
332
+ },
333
+
334
+ chat_fulfilled: (state: State, { chat }: { chat: Chat }) => {
335
+ const chatState = state.query.chats[chat.id];
336
+ chatState.isFetching = false;
337
+ chatState.error = undefined;
338
+ chatState.data = chat;
339
+ },
340
+
341
+ chat_rejected: (state: State, { chatId, error }: { chatId: string; error: any }) => {
342
+ const chatState = state.query.chats[chatId];
343
+ chatState.isFetching = false;
344
+ chatState.error = error;
345
+ },
346
+
347
+ send_fetch: (
348
+ state: State,
349
+ {
350
+ chatId,
351
+ text,
352
+ files,
353
+ requestId,
354
+ }: {
355
+ chatId: string;
356
+ text: string;
357
+ files: File[];
358
+ requestId: string;
359
+ },
360
+ ) => {
361
+ state.mutation.send = { isFetching: true, error: undefined };
362
+ state.query.messages[chatId].data?.push({ type: 'sending', text, files, requestId });
363
+ },
364
+
365
+ send_fulfilled: (state: State, { chatId, requestId }: { chatId: string; requestId: string }) => {
366
+ state.mutation.send = { isFetching: false, error: undefined };
367
+ },
368
+
369
+ send_rejected: (
370
+ state: State,
371
+ { chatId, requestId, error }: { chatId: string; requestId: string; error: any },
372
+ ) => {
373
+ state.mutation.send = { isFetching: false, error };
374
+ state.query.messages[chatId].data = state.query.messages[chatId].data?.filter(
375
+ (x) => x.type !== 'sending' || x.requestId !== requestId,
376
+ );
377
+ },
378
+
379
+ chatNameChanged_received: (
380
+ state: State,
381
+ { chatId, newName, message }: { chatId: string; newName: string; message: Message },
382
+ ) => {
383
+ if (state.query.chatList.data) {
384
+ const chatListItem = state.query.chatList.data.find((x) => x.id === chatId);
385
+ chatListItem!.name = newName;
386
+ chatListItem!.message = message;
387
+ chatListItem!.totalUnreadCount++;
388
+ }
389
+
390
+ if (state.query.chats[chatId].data) {
391
+ state.query.chats[chatId].data!.name = newName;
392
+ }
393
+
394
+ if (state.query.messages[chatId].data) {
395
+ state.query.messages[chatId].data!.unshift({ type: 'message', ...message });
396
+ }
397
+ },
398
+ };
399
+
400
+ export type Action = {
401
+ [K in keyof typeof ACTIONS]: {
402
+ type: K;
403
+ data: Parameters<(typeof ACTIONS)[K]>[1];
404
+ };
405
+ }[keyof typeof ACTIONS];