@webinex/chatify 2.0.0-alpha13 → 2.0.0-alpha14

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 (143) hide show
  1. package/dist/{Chatify-CwAfN1wu.js → Chatify-CP2jgo8d.js} +191 -118
  2. package/dist/Chatify-CP2jgo8d.js.map +1 -0
  3. package/dist/Chatify.css +28 -0
  4. package/dist/audit.js +3 -2
  5. package/dist/audit.js.map +1 -1
  6. package/dist/index.js +1 -1
  7. package/dist/types/audit/index.d.ts +17 -15
  8. package/dist/types/ui/Chat/ChatContext.d.ts +2 -0
  9. package/dist/types/ui/Chat/ChatPanel.d.ts +7 -0
  10. package/dist/types/ui/Chat/ChatView.d.ts +4 -2
  11. package/dist/types/ui/ChatGroup/ChatGroupContext.d.ts +4 -1
  12. package/dist/types/ui/ChatGroup/ChatGroupPanel.d.ts +21 -2
  13. package/dist/types/ui/Conversation/Conversation.d.ts +1 -0
  14. package/dist/types/ui/Conversation/ConversationContext.d.ts +1 -0
  15. package/dist/types/ui/Conversation/ConversationHeader.d.ts +4 -1
  16. package/dist/types/ui/localizer.d.ts +4 -1
  17. package/dist/types/ui/useCompact.d.ts +4 -0
  18. package/package.json +81 -81
  19. package/src/audit/AuditChatList.tsx +25 -25
  20. package/src/audit/AuditConversationPanel.tsx +49 -48
  21. package/src/audit/AuditPanel.tsx +76 -76
  22. package/src/audit/AuditPanelCustomizeValue.ts +11 -11
  23. package/src/audit/AuditSearch.tsx +89 -89
  24. package/src/audit/AuditSearchValue.tsx +42 -42
  25. package/src/audit/auditApi.tsx +113 -113
  26. package/src/audit/index.d.ts +18 -18
  27. package/src/audit/index.tsx +28 -28
  28. package/src/audit/styles.scss +72 -72
  29. package/src/core/api/api.ts +675 -675
  30. package/src/core/api/baseApi.ts +38 -38
  31. package/src/core/api/index.ts +1 -1
  32. package/src/core/client.ts +298 -298
  33. package/src/core/constants.ts +1 -1
  34. package/src/core/debounce.ts +90 -90
  35. package/src/core/index.ts +4 -4
  36. package/src/core/types.tsx +182 -182
  37. package/src/index.ts +2 -2
  38. package/src/styles/aside.scss +34 -26
  39. package/src/styles/chat-list.scss +138 -138
  40. package/src/styles/chat.scss +11 -11
  41. package/src/styles/conversation.scss +199 -200
  42. package/src/styles/index.scss +227 -220
  43. package/src/styles/input.scss +148 -148
  44. package/src/styles/keyframes.scss +14 -14
  45. package/src/styles/members.scss +30 -13
  46. package/src/styles/mixins.scss +38 -25
  47. package/src/styles/variables.scss +13 -13
  48. package/src/ui/Chat/ChatContext.tsx +32 -30
  49. package/src/ui/Chat/ChatEditableHeaderName.tsx +63 -63
  50. package/src/ui/Chat/ChatHeaderActions.tsx +19 -19
  51. package/src/ui/Chat/ChatPanel.tsx +46 -30
  52. package/src/ui/Chat/ChatView.tsx +122 -115
  53. package/src/ui/Chat/Members/ChatMembersButton.tsx +9 -9
  54. package/src/ui/Chat/Members/ChatMembersPanel.tsx +128 -112
  55. package/src/ui/Chat/Members/ChatMembersPreview.tsx +25 -25
  56. package/src/ui/Chat/Members/index.ts +13 -13
  57. package/src/ui/Chat/index.ts +6 -6
  58. package/src/ui/ChatGroup/AutoReply/AutoReplyButton.tsx +21 -21
  59. package/src/ui/ChatGroup/AutoReply/AutoReplyForm.tsx +50 -50
  60. package/src/ui/ChatGroup/AutoReply/AutoReplyPanel.tsx +94 -94
  61. package/src/ui/ChatGroup/AutoReply/AutoReplyPeriodInput.tsx +22 -22
  62. package/src/ui/ChatGroup/AutoReply/AutoReplyTextInput.tsx +22 -22
  63. package/src/ui/ChatGroup/AutoReply/index.ts +19 -19
  64. package/src/ui/ChatGroup/ChatGroupContext.tsx +63 -61
  65. package/src/ui/ChatGroup/ChatGroupPanel.tsx +110 -75
  66. package/src/ui/ChatGroup/Create/CreateChatButton.tsx +15 -15
  67. package/src/ui/ChatGroup/Create/CreateChatForm.tsx +36 -36
  68. package/src/ui/ChatGroup/Create/CreateChatMemberInput.tsx +65 -65
  69. package/src/ui/ChatGroup/Create/CreateChatNameInput.tsx +25 -25
  70. package/src/ui/ChatGroup/Create/CreateChatPanel.tsx +45 -45
  71. package/src/ui/ChatGroup/Create/index.ts +19 -19
  72. package/src/ui/ChatGroup/Layout/ChatGroupActions.tsx +15 -15
  73. package/src/ui/ChatGroup/Layout/ChatGroupAside.tsx +12 -12
  74. package/src/ui/ChatGroup/Layout/ChatGroupBody.tsx +17 -10
  75. package/src/ui/ChatGroup/Layout/ChatGroupFooter.tsx +3 -3
  76. package/src/ui/ChatGroup/Layout/ChatGroupHeader.tsx +5 -5
  77. package/src/ui/ChatGroup/Layout/ChatGroupMain.tsx +21 -19
  78. package/src/ui/ChatGroup/Layout/index.ts +22 -22
  79. package/src/ui/ChatGroup/List/ChatListPanel.tsx +28 -28
  80. package/src/ui/ChatGroup/List/index.ts +8 -8
  81. package/src/ui/ChatGroup/index.ts +6 -6
  82. package/src/ui/Chatify.tsx +15 -15
  83. package/src/ui/Conversation/Conversation.tsx +96 -92
  84. package/src/ui/Conversation/ConversationActions.tsx +12 -12
  85. package/src/ui/Conversation/ConversationBody.tsx +28 -28
  86. package/src/ui/Conversation/ConversationContext.ts +31 -30
  87. package/src/ui/Conversation/ConversationHeader.tsx +35 -19
  88. package/src/ui/Conversation/ConversationName.tsx +7 -7
  89. package/src/ui/Conversation/InputBox/InputBox.tsx +126 -126
  90. package/src/ui/Conversation/InputBox/InputBoxFile.tsx +38 -38
  91. package/src/ui/Conversation/InputBox/InputBoxFileList.tsx +21 -21
  92. package/src/ui/Conversation/InputBox/InputFilesBox.tsx +78 -78
  93. package/src/ui/Conversation/InputBox/InputSubmitButtonBox.tsx +26 -26
  94. package/src/ui/Conversation/InputBox/InputTextBox.tsx +63 -61
  95. package/src/ui/Conversation/InputBox/index.ts +23 -23
  96. package/src/ui/Conversation/Message/MessageAuthor.tsx +13 -13
  97. package/src/ui/Conversation/Message/MessageBox.tsx +20 -20
  98. package/src/ui/Conversation/Message/MessageContent.tsx +15 -15
  99. package/src/ui/Conversation/Message/MessageFile.tsx +54 -54
  100. package/src/ui/Conversation/Message/MessageFileList.tsx +14 -14
  101. package/src/ui/Conversation/Message/MessageInfoBox.tsx +28 -28
  102. package/src/ui/Conversation/Message/MessageRow.tsx +28 -28
  103. package/src/ui/Conversation/Message/MessageText.tsx +7 -7
  104. package/src/ui/Conversation/Message/index.ts +28 -28
  105. package/src/ui/Conversation/NextObserver/NextMessagesObserver.tsx +47 -47
  106. package/src/ui/Conversation/NextObserver/index.ts +1 -1
  107. package/src/ui/Conversation/ReadObserver/MessageReadObserver.tsx +49 -49
  108. package/src/ui/Conversation/ReadObserver/index.ts +1 -1
  109. package/src/ui/Conversation/SendingMessage/SendingMessageBox.tsx +16 -16
  110. package/src/ui/Conversation/SendingMessage/SendingMessageContent.tsx +13 -13
  111. package/src/ui/Conversation/SendingMessage/SendingMessageInfoBox.tsx +13 -13
  112. package/src/ui/Conversation/SendingMessage/SendingMessageText.tsx +7 -7
  113. package/src/ui/Conversation/SendingMessage/index.ts +16 -16
  114. package/src/ui/Conversation/SystemMessage/SystemMessageBox.tsx +20 -20
  115. package/src/ui/Conversation/SystemMessage/SystemMessageRow.tsx +28 -28
  116. package/src/ui/Conversation/SystemMessage/index.ts +10 -10
  117. package/src/ui/Conversation/index.ts +13 -13
  118. package/src/ui/Thread/ThreadActions.tsx +22 -22
  119. package/src/ui/Thread/ThreadContext.ts +13 -13
  120. package/src/ui/Thread/ThreadPanel.tsx +128 -127
  121. package/src/ui/Thread/index.tsx +3 -3
  122. package/src/ui/color.ts +20 -20
  123. package/src/ui/common/Avatar.tsx +20 -20
  124. package/src/ui/common/ChatList/ChatList.tsx +83 -84
  125. package/src/ui/common/ChatList/ChatListItemAvatar.tsx +22 -22
  126. package/src/ui/common/ChatList/ChatListItemBox.tsx +32 -32
  127. package/src/ui/common/ChatList/ChatListItemLastMessage.tsx +15 -15
  128. package/src/ui/common/ChatList/ChatListItemLastMessageAuthor.tsx +15 -15
  129. package/src/ui/common/ChatList/ChatListItemLastMessageContent.tsx +21 -21
  130. package/src/ui/common/ChatList/ChatListItemLastMessageSentAt.tsx +22 -22
  131. package/src/ui/common/ChatList/ChatListItemName.tsx +8 -8
  132. package/src/ui/common/ChatList/ChatListItemUnreadCount.tsx +12 -12
  133. package/src/ui/common/ChatList/ChatListValue.ts +9 -9
  134. package/src/ui/common/ChatList/index.ts +32 -32
  135. package/src/ui/common/Icon.tsx +48 -48
  136. package/src/ui/common/MessageSkeleton.tsx +20 -20
  137. package/src/ui/common/index.ts +14 -14
  138. package/src/ui/customize.tsx +51 -51
  139. package/src/ui/index.ts +11 -11
  140. package/src/ui/localizer.tsx +148 -137
  141. package/src/ui/useCompact.tsx +32 -0
  142. package/src/ui/useFormatter.tsx +17 -17
  143. package/dist/Chatify-CwAfN1wu.js.map +0 -1
@@ -1,675 +1,675 @@
1
- import { ChatifyApiSettings, DEFAULT_MESSAGE_LIST_TAKE, __baseApi, __settings } from './baseApi';
2
- import { useSelector } from 'react-redux';
3
- import {
4
- Account,
5
- AddChatMemberRequest,
6
- Chat,
7
- ChatListItem,
8
- ChatMessage,
9
- RemoveChatMemberRequest,
10
- SendChatMessageRequest,
11
- SendThreadMessageRequest,
12
- Thread,
13
- ThreadMessage,
14
- ThreadWatchListItem,
15
- UpdateAccountRequest,
16
- calcThreadListUnreadCount,
17
- chatId,
18
- parseThreadMessageId,
19
- } from '../types';
20
- import { unsubscribe } from '../client';
21
- import { Debounce, DebounceValue } from '../debounce';
22
- import { useMemo } from 'react';
23
-
24
- export interface ChatMessageListResult {
25
- messages: ChatMessage[];
26
- hasMore: boolean;
27
- }
28
-
29
- export interface ThreadMessageList {
30
- messages: ThreadMessage[];
31
- hasMore: boolean;
32
- }
33
-
34
- const THREAD_MESSAGE_READ_QUEUE = new Debounce<string>({
35
- callback: (id) => __settings.client.readThreadMessage(id),
36
- compare: (a, b) => -a.localeCompare(b),
37
- groupBy: (id) => parseThreadMessageId(id)[0],
38
- timeout: 500,
39
- });
40
-
41
- const CHAT_MESSAGE_READ_QUEUE = new Debounce<string>({
42
- callback: (id) => __settings.client.readChatMessage({ id }),
43
- compare: (a, b) => -a.localeCompare(b),
44
- groupBy: (id) => chatId(id),
45
- timeout: 500,
46
- });
47
-
48
- const __chatifyApi = __baseApi.injectEndpoints({
49
- endpoints: (builder) => ({
50
- // ====================================================
51
- // ============== ACCOUNT ======================
52
- // ====================================================
53
-
54
- getAccountList: builder.query<Account[], { ids?: string[] }>({
55
- queryFn: async (args) => ({ data: await __settings.client.accounts(args) }),
56
- providesTags: ['account'],
57
- }),
58
-
59
- geCurrentUserAccount: builder.query<Account | null, void>({
60
- queryFn: async () => ({ data: await __settings.client.currentUserAccount() }),
61
- providesTags: ['account'],
62
- }),
63
-
64
- updateAccount: builder.mutation<void, UpdateAccountRequest>({
65
- queryFn: async (request) => {
66
- await __settings.client.updateAccount(request);
67
- return { data: null! };
68
- },
69
- invalidatesTags: ['account'],
70
- }),
71
-
72
- // ====================================================
73
- // ================ CHAT =======================
74
- // ====================================================
75
-
76
- getChat: builder.query<Chat, { id: string }>({
77
- queryFn: async ({ id }) => ({ data: await __settings.client.chat(id) }),
78
- providesTags: ['chat', 'account'],
79
- onCacheEntryAdded: async ({ id }, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
80
- await cacheDataLoaded;
81
-
82
- unsubscribe(
83
- __settings.client.subscribe(
84
- 'chatify://chat-member-added',
85
- ([chatId, _, account, message, , read]) =>
86
- chatId === id &&
87
- updateCachedData((chat) => {
88
- chat.members.push(account);
89
- chat.lastReadMessageId = read ? message.id : chat.lastReadMessageId;
90
- }),
91
- ),
92
- __settings.client.subscribe(
93
- 'chatify://chat-member-removed',
94
- ([chatId, accountId, , message, read]) =>
95
- id === chatId &&
96
- updateCachedData((chat) => {
97
- chat.members = chat.members.filter((x) => x.id !== accountId);
98
- chat.lastReadMessageId = read ? message.id : chat.lastReadMessageId;
99
- }),
100
- ),
101
- __settings.client.subscribe(
102
- 'chatify://chat-name-changed',
103
- ([chatId, newName, message, read]) =>
104
- id === chatId &&
105
- updateCachedData((chat) => {
106
- chat.name = newName;
107
- chat.lastReadMessageId = read ? message.id : chat.lastReadMessageId;
108
- }),
109
- ),
110
- __settings.client.subscribe(
111
- 'chatify://chat-new-message',
112
- ([message]) =>
113
- id === message.chatId &&
114
- updateCachedData((chat) => {
115
- chat.lastReadMessageId =
116
- message.sentBy.id === __settings.me() ? message.id : chat.lastReadMessageId;
117
- }),
118
- ),
119
- __settings.client.subscribe(
120
- 'chatify://chat-message-read',
121
- ([events]) =>
122
- events.find((x) => x.chatId === id) &&
123
- updateCachedData((chat) => {
124
- const event = events.find((x) => x.chatId === id)!;
125
- chat.lastReadMessageId = event.newLastReadMessageId;
126
- }),
127
- ),
128
- ).when(cacheEntryRemoved);
129
- },
130
- }),
131
-
132
- addChat: builder.mutation<string, { name: string; members: string[] }>({
133
- queryFn: async ({ name, members }) => {
134
- const chatId = await __settings.client.addChat({
135
- name,
136
- members,
137
- });
138
- return { data: chatId };
139
- },
140
- }),
141
-
142
- updateChatName: builder.mutation<void, { id: string; name: string }>({
143
- queryFn: async ({ id, name }) => {
144
- await __settings.client.updateChatName({ id, name });
145
- return { data: null! };
146
- },
147
- }),
148
-
149
- // ====================================================
150
- // ============= CHAT LIST =====================
151
- // ====================================================
152
-
153
- getChatList: builder.query<ChatListItem[], void>({
154
- queryFn: async () => ({ data: await __settings.client.chats() }),
155
- providesTags: ['chat', 'account'],
156
- onCacheEntryAdded: async (_, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
157
- await cacheDataLoaded;
158
-
159
- unsubscribe(
160
- __settings.client.subscribe('chatify://chat-created', ([chat]) =>
161
- updateCachedData((chatList) => {
162
- chatList.push(chat);
163
- }),
164
- ),
165
-
166
- __settings.client.subscribe('chatify://chat-new-message', ([message]) =>
167
- updateCachedData((chatList) => {
168
- const chat = chatList.find((x) => x.id === message.chatId);
169
-
170
- if (!chat) {
171
- return;
172
- }
173
-
174
- chat.message = message;
175
-
176
- if (message.sentBy.id === __settings.me()) {
177
- chat.lastReadMessageId = message.id;
178
- chat.totalUnreadCount = 0;
179
- }
180
-
181
- if (message.sentBy.id !== __settings.me()) {
182
- chat.totalUnreadCount++;
183
- }
184
- }),
185
- ),
186
- __settings.client.subscribe('chatify://chat-message-read', ([events]) =>
187
- updateCachedData((chatList) => {
188
- for (const event of events) {
189
- const chat = chatList.find((x) => x.id === event.chatId);
190
-
191
- if (!chat) {
192
- return;
193
- }
194
-
195
- chat.lastReadMessageId = event.newLastReadMessageId;
196
- chat.totalUnreadCount = chat.totalUnreadCount - event.readCount;
197
- }
198
- }),
199
- ),
200
- __settings.client.subscribe(
201
- 'chatify://chat-member-added',
202
- ([chatId, chatName, account, message, , read]) =>
203
- updateCachedData((chatList) => {
204
- const chat = chatList.find((x) => x.id === chatId);
205
-
206
- if (account.id === __settings.me() && !chat) {
207
- chatList.push({
208
- id: chatId,
209
- name: chatName,
210
- message,
211
- totalUnreadCount: read ? 0 : 1,
212
- active: true,
213
- lastReadMessageId: read ? message.id : null,
214
- });
215
- }
216
-
217
- if (!chat) {
218
- return;
219
- }
220
-
221
- chat.message = message;
222
- chat.active = true;
223
-
224
- if (read) {
225
- chat.totalUnreadCount = 0;
226
- chat.lastReadMessageId = message.id;
227
- } else {
228
- chat.totalUnreadCount++;
229
- }
230
- }),
231
- ),
232
- __settings.client.subscribe(
233
- 'chatify://chat-member-removed',
234
- ([chatId, accountId, deleteHistory, message, read]) =>
235
- updateCachedData((chatList) => {
236
- if (accountId === __settings.me() && deleteHistory) {
237
- return chatList.filter((x) => x.id !== chatId);
238
- }
239
-
240
- const chat = chatList.find((x) => x.id === chatId);
241
-
242
- if (!chat) {
243
- return;
244
- }
245
-
246
- chat.message = message;
247
-
248
- if (accountId === __settings.me()) {
249
- chat.active = false;
250
- }
251
-
252
- if (!read) {
253
- chat.totalUnreadCount++;
254
- } else {
255
- chat.totalUnreadCount = 0;
256
- chat.lastReadMessageId = message.id;
257
- }
258
- }),
259
- ),
260
- __settings.client.subscribe('chatify://chat-name-changed', ([chatId, newName, message, read]) =>
261
- updateCachedData((chatList) => {
262
- const chat = chatList.find((x) => x.id === chatId);
263
- if (!chat) return;
264
-
265
- chat.name = newName;
266
- chat.message = message;
267
-
268
- if (!read) {
269
- chat.totalUnreadCount++;
270
- } else {
271
- chat.totalUnreadCount = 0;
272
- chat.lastReadMessageId = message.id;
273
- }
274
- }),
275
- ),
276
- ).when(cacheEntryRemoved);
277
- },
278
- }),
279
-
280
- // ====================================================
281
- // ============ CHAT MEMBER ====================
282
- // ====================================================
283
-
284
- removeChatMember: builder.mutation<void, RemoveChatMemberRequest>({
285
- queryFn: async (args) => {
286
- await __settings.client.removeChatMember(args);
287
- return { data: null! };
288
- },
289
- }),
290
-
291
- addChatMember: builder.mutation<void, AddChatMemberRequest>({
292
- queryFn: async (args) => {
293
- await __settings.client.addChatMember(args);
294
- return { data: null! };
295
- },
296
- }),
297
-
298
- // ====================================================
299
- // ============ CHAT MESSAGE ===================
300
- // ====================================================
301
-
302
- getChatMessageList: builder.query<ChatMessageListResult, { chatId: string }>({
303
- queryFn: async ({ chatId }) => {
304
- const messages = await __settings.client.chatMessages({
305
- chatId,
306
- skip: 0,
307
- take: DEFAULT_MESSAGE_LIST_TAKE + 1,
308
- });
309
- return {
310
- data: {
311
- messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
312
- hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
313
- },
314
- };
315
- },
316
- providesTags: ['message', 'chat', 'account'],
317
- onCacheEntryAdded: async ({ chatId }, { dispatch, cacheEntryRemoved, cacheDataLoaded }) => {
318
- await cacheDataLoaded;
319
-
320
- unsubscribe(
321
- __settings.client.subscribe('chatify://chat-new-message', ([message]) => {
322
- message.chatId === chatId &&
323
- dispatch(
324
- chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
325
- draft.messages.unshift(message);
326
- }),
327
- );
328
- }),
329
-
330
- __settings.client.subscribe('chatify://chat-member-added', ([eventChatId, , , message]) => {
331
- eventChatId === chatId &&
332
- dispatch(
333
- chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
334
- draft.messages.unshift(message);
335
- }),
336
- );
337
- }),
338
-
339
- __settings.client.subscribe('chatify://chat-member-removed', ([eventChatId, , , message]) => {
340
- eventChatId === chatId &&
341
- dispatch(
342
- chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
343
- draft.messages.unshift(message);
344
- }),
345
- );
346
- }),
347
-
348
- __settings.client.subscribe('chatify://chat-name-changed', ([eventChatId, , message]) => {
349
- eventChatId === chatId &&
350
- dispatch(
351
- chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
352
- draft.messages.unshift(message);
353
- }),
354
- );
355
- }),
356
- ).when(cacheEntryRemoved);
357
- },
358
- }),
359
-
360
- fetchNextChatMessageList: builder.mutation<void, { chatId: string }>({
361
- queryFn: async ({ chatId }, { getState }) => {
362
- const current = chatifyApi.endpoints.getChatMessageList.select({ chatId })(getState() as any);
363
- const messages = await __settings.client.chatMessages({
364
- chatId,
365
- skip: current.data!.messages.length,
366
- take: DEFAULT_MESSAGE_LIST_TAKE + 1,
367
- });
368
- return {
369
- data: null!,
370
- meta: {
371
- messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
372
- hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
373
- },
374
- };
375
- },
376
- onQueryStarted: async ({ chatId }, { dispatch, queryFulfilled }) => {
377
- const result = await queryFulfilled;
378
- const meta: ChatMessageListResult = result.meta! as any;
379
-
380
- dispatch(
381
- chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
382
- draft.hasMore = meta.hasMore;
383
- draft.messages.push(...meta!.messages);
384
- }),
385
- );
386
- },
387
- }),
388
-
389
- sendChatMessage: builder.mutation<void, SendChatMessageRequest>({
390
- queryFn: async ({ chatId, text, files }) => {
391
- await __settings.client.sendChatMessage({
392
- chatId,
393
- text,
394
- files,
395
- });
396
-
397
- return { data: null! };
398
- },
399
- }),
400
-
401
- readChatMessage: builder.mutation<void, { id: string }>({
402
- queryFn: async () => {
403
- return { data: null! };
404
- },
405
- onQueryStarted: async ({ id }, { dispatch }) => {
406
- CHAT_MESSAGE_READ_QUEUE.push(id);
407
- dispatch(chatifyApi.endpoints.getChatMessageReadQueue.initiate(undefined, { forceRefetch: true }));
408
- },
409
- }),
410
-
411
- getChatMessageReadQueue: builder.query<DebounceValue<string>[], void>({
412
- queryFn: async () => ({ data: CHAT_MESSAGE_READ_QUEUE.units }),
413
- onCacheEntryAdded: async (_, { dispatch, cacheEntryRemoved }) => {
414
- unsubscribe(
415
- CHAT_MESSAGE_READ_QUEUE.subscribe((value) => {
416
- dispatch(
417
- chatifyApi.util.updateQueryData('getChatMessageReadQueue', undefined, () => value.units),
418
- );
419
- }),
420
- ).when(cacheEntryRemoved);
421
- },
422
- }),
423
-
424
- // ====================================================
425
- // =============== THREAD ======================s
426
- // ====================================================
427
- getWatchThreadList: builder.query<ThreadWatchListItem[], void>({
428
- queryFn: async () => {
429
- const threads = await __settings.client.watchThreads();
430
- return { data: threads };
431
- },
432
- providesTags: ['account', 'thread'],
433
- onCacheEntryAdded: async (_, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
434
- await cacheDataLoaded;
435
-
436
- unsubscribe(
437
- __settings.client.subscribe(
438
- 'chatify://thread-created',
439
- ([thread, watch]) =>
440
- watch &&
441
- updateCachedData((threads) => {
442
- threads.push(thread);
443
- }),
444
- ),
445
- __settings.client.subscribe('chatify://thread-message-new', ([threadId, message, readForId]) =>
446
- updateCachedData((threads) => {
447
- const thread = threads.find((x) => x.id === threadId);
448
- if (!thread) return;
449
-
450
- thread.lastMessage = message;
451
-
452
- if (readForId === __settings.me()) {
453
- thread.lastReadMessageId = message.id;
454
- }
455
- }),
456
- ),
457
- __settings.client.subscribe('chatify://thread-message-read', ([threadId, messageId]) =>
458
- updateCachedData((threads) => {
459
- const thread = threads.find((x) => x.id === threadId);
460
- if (!thread) return;
461
-
462
- thread.lastReadMessageId = messageId;
463
- }),
464
- ),
465
- __settings.client.subscribe('chatify://thread-watch-added', ([thread]) =>
466
- updateCachedData((threads) => {
467
- threads.push(thread);
468
- }),
469
- ),
470
- __settings.client.subscribe('chatify://thread-watch-removed', ([id]) =>
471
- updateCachedData((threads) => {
472
- const index = threads.findIndex((x) => x.id === id);
473
- if (index !== -1) threads.splice(index, 1);
474
- }),
475
- ),
476
- __settings.client.subscribe('chatify://thread-updated', ([threadId, threadName]) =>
477
- updateCachedData((threads) => {
478
- const thread = threads.find((x) => x.id === threadId);
479
- if (!thread) return;
480
-
481
- thread.name = threadName;
482
- }),
483
- ),
484
- ).when(cacheEntryRemoved);
485
- },
486
- }),
487
-
488
- getThread: builder.query<Thread, { id: string }>({
489
- queryFn: async ({ id }) => {
490
- const threads = await __settings.client.thread(id);
491
- return { data: threads };
492
- },
493
- providesTags: ['account', 'thread'],
494
- onCacheEntryAdded: async ({ id }, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
495
- await cacheDataLoaded;
496
-
497
- unsubscribe(
498
- __settings.client.subscribe(
499
- 'chatify://thread-message-read',
500
- ([threadId, messageId]) =>
501
- id === threadId &&
502
- updateCachedData((t) => {
503
- t.lastReadMessageId = messageId;
504
- }),
505
- ),
506
- __settings.client.subscribe(
507
- 'chatify://thread-message-new',
508
- ([threadId, message, readForId]) =>
509
- id === threadId &&
510
- updateCachedData((thread) => {
511
- thread.lastMessageId = message.id;
512
- thread.lastReadMessageId =
513
- readForId === __settings.me() ? message.id : thread.lastReadMessageId;
514
- }),
515
- ),
516
- __settings.client.subscribe(
517
- 'chatify://thread-watch-added',
518
- ([threadListItem]) =>
519
- id === threadListItem.id &&
520
- updateCachedData((thread) => {
521
- thread.watch = true;
522
- thread.lastMessageId = threadListItem.lastMessage?.id ?? null;
523
- thread.lastReadMessageId = threadListItem.lastReadMessageId ?? null;
524
- }),
525
- ),
526
- __settings.client.subscribe(
527
- 'chatify://thread-watch-removed',
528
- ([threadId]) =>
529
- id === threadId &&
530
- updateCachedData((thread) => {
531
- thread.watch = false;
532
- }),
533
- ),
534
- __settings.client.subscribe(
535
- 'chatify://thread-updated',
536
- ([threadId, threadName]) =>
537
- id === threadId &&
538
- updateCachedData((thread) => {
539
- thread.name = threadName;
540
- }),
541
- ),
542
- ).when(cacheEntryRemoved);
543
- },
544
- }),
545
-
546
- watchThread: builder.mutation<void, { id: string; watch: boolean }>({
547
- queryFn: async ({ id, watch }) => {
548
- await __settings.client.watchThread(id, watch);
549
- return { data: null! };
550
- },
551
- }),
552
-
553
- // ====================================================
554
- // ============ THREAD MESSAGE =================
555
- // ====================================================
556
-
557
- getThreadMessageList: builder.query<ThreadMessageList, { threadId: string }>({
558
- queryFn: async (args) => {
559
- const requestArgs = {
560
- skip: 0,
561
- take: DEFAULT_MESSAGE_LIST_TAKE + 1,
562
- ...args,
563
- };
564
- const messages = await __settings.client.threadMessages(requestArgs);
565
- return {
566
- data: {
567
- messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
568
- hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
569
- },
570
- };
571
- },
572
- providesTags: ['account', 'thread', 'thread-message'],
573
- onCacheEntryAdded: async ({ threadId }, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
574
- await cacheDataLoaded;
575
-
576
- unsubscribe(
577
- __settings.client.subscribe('chatify://thread-message-new', ([_threadId, message]) => {
578
- threadId === _threadId &&
579
- updateCachedData((messageList) => {
580
- !messageList.messages.some((x) => x.id === message.id) &&
581
- messageList.messages.unshift(message);
582
- });
583
- }),
584
- ).when(cacheEntryRemoved);
585
- },
586
- }),
587
-
588
- fetchNextThreadMessageList: builder.mutation<void, { threadId: string }>({
589
- queryFn: async ({ threadId }, { getState }) => {
590
- const current = chatifyApi.endpoints.getThreadMessageList.select({ threadId })(getState() as any);
591
- const messages = await __settings.client.threadMessages({
592
- threadId,
593
- skip: current.data!.messages.length,
594
- take: DEFAULT_MESSAGE_LIST_TAKE + 1,
595
- });
596
- return {
597
- data: null!,
598
- meta: {
599
- messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
600
- hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
601
- },
602
- };
603
- },
604
- onQueryStarted: async ({ threadId }, { dispatch, queryFulfilled }) => {
605
- const result = await queryFulfilled;
606
- const meta: ThreadMessageList = result.meta! as any;
607
-
608
- dispatch(
609
- chatifyApi.util.updateQueryData('getThreadMessageList', { threadId }, (draft) => {
610
- draft.hasMore = meta.hasMore;
611
- draft.messages.push(...meta!.messages);
612
- }),
613
- );
614
- },
615
- }),
616
-
617
- sendThreadMessage: builder.mutation<string, SendThreadMessageRequest>({
618
- queryFn: async (args) => {
619
- const id = await __settings.client.sendThreadMessage(args);
620
- return { data: id };
621
- },
622
- }),
623
-
624
- readThreadMessage: builder.mutation<void, { id: string }>({
625
- queryFn: async () => {
626
- return { data: null! };
627
- },
628
- onQueryStarted: async ({ id }, { dispatch }) => {
629
- THREAD_MESSAGE_READ_QUEUE.push(id);
630
- dispatch(chatifyApi.endpoints.getThreadMessageReadQueue.initiate(undefined, { forceRefetch: true }));
631
- },
632
- }),
633
-
634
- getThreadMessageReadQueue: builder.query<DebounceValue<string>[], void>({
635
- queryFn: async () => ({ data: THREAD_MESSAGE_READ_QUEUE.units }),
636
- onCacheEntryAdded: async (_, { dispatch, cacheEntryRemoved }) => {
637
- unsubscribe(
638
- THREAD_MESSAGE_READ_QUEUE.subscribe((value) => {
639
- dispatch(
640
- chatifyApi.util.updateQueryData('getThreadMessageReadQueue', undefined, () => value.units),
641
- );
642
- }),
643
- ).when(cacheEntryRemoved);
644
- },
645
- }),
646
- }),
647
- });
648
-
649
- export function useChatListItem(id: string | null) {
650
- return useSelector((state: any) =>
651
- id != null
652
- ? __chatifyApi.endpoints.getChatList
653
- .select()(state)
654
- .data?.find((x) => x.id === id)
655
- : null,
656
- );
657
- }
658
-
659
- export function useUnreadThreadMessageCount() {
660
- const { data: threads, ...state } = chatifyApi.useGetWatchThreadListQuery();
661
- const count = useMemo(() => (threads != null ? calcThreadListUnreadCount(threads) : null), [threads]);
662
- return [count, state] as const;
663
- }
664
-
665
- type ChatifyApi = typeof __chatifyApi & {
666
- settings: ChatifyApiSettings;
667
- useChatListItem: typeof useChatListItem;
668
- useUnreadThreadMessageCount: typeof useUnreadThreadMessageCount;
669
- };
670
-
671
- export const chatifyApi: ChatifyApi = Object.assign(__chatifyApi, {
672
- settings: __settings,
673
- useChatListItem,
674
- useUnreadThreadMessageCount,
675
- });
1
+ import { ChatifyApiSettings, DEFAULT_MESSAGE_LIST_TAKE, __baseApi, __settings } from './baseApi';
2
+ import { useSelector } from 'react-redux';
3
+ import {
4
+ Account,
5
+ AddChatMemberRequest,
6
+ Chat,
7
+ ChatListItem,
8
+ ChatMessage,
9
+ RemoveChatMemberRequest,
10
+ SendChatMessageRequest,
11
+ SendThreadMessageRequest,
12
+ Thread,
13
+ ThreadMessage,
14
+ ThreadWatchListItem,
15
+ UpdateAccountRequest,
16
+ calcThreadListUnreadCount,
17
+ chatId,
18
+ parseThreadMessageId,
19
+ } from '../types';
20
+ import { unsubscribe } from '../client';
21
+ import { Debounce, DebounceValue } from '../debounce';
22
+ import { useMemo } from 'react';
23
+
24
+ export interface ChatMessageListResult {
25
+ messages: ChatMessage[];
26
+ hasMore: boolean;
27
+ }
28
+
29
+ export interface ThreadMessageList {
30
+ messages: ThreadMessage[];
31
+ hasMore: boolean;
32
+ }
33
+
34
+ const THREAD_MESSAGE_READ_QUEUE = new Debounce<string>({
35
+ callback: (id) => __settings.client.readThreadMessage(id),
36
+ compare: (a, b) => -a.localeCompare(b),
37
+ groupBy: (id) => parseThreadMessageId(id)[0],
38
+ timeout: 500,
39
+ });
40
+
41
+ const CHAT_MESSAGE_READ_QUEUE = new Debounce<string>({
42
+ callback: (id) => __settings.client.readChatMessage({ id }),
43
+ compare: (a, b) => -a.localeCompare(b),
44
+ groupBy: (id) => chatId(id),
45
+ timeout: 500,
46
+ });
47
+
48
+ const __chatifyApi = __baseApi.injectEndpoints({
49
+ endpoints: (builder) => ({
50
+ // ====================================================
51
+ // ============== ACCOUNT ======================
52
+ // ====================================================
53
+
54
+ getAccountList: builder.query<Account[], { ids?: string[] }>({
55
+ queryFn: async (args) => ({ data: await __settings.client.accounts(args) }),
56
+ providesTags: ['account'],
57
+ }),
58
+
59
+ geCurrentUserAccount: builder.query<Account | null, void>({
60
+ queryFn: async () => ({ data: await __settings.client.currentUserAccount() }),
61
+ providesTags: ['account'],
62
+ }),
63
+
64
+ updateAccount: builder.mutation<void, UpdateAccountRequest>({
65
+ queryFn: async (request) => {
66
+ await __settings.client.updateAccount(request);
67
+ return { data: null! };
68
+ },
69
+ invalidatesTags: ['account'],
70
+ }),
71
+
72
+ // ====================================================
73
+ // ================ CHAT =======================
74
+ // ====================================================
75
+
76
+ getChat: builder.query<Chat, { id: string }>({
77
+ queryFn: async ({ id }) => ({ data: await __settings.client.chat(id) }),
78
+ providesTags: ['chat', 'account'],
79
+ onCacheEntryAdded: async ({ id }, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
80
+ await cacheDataLoaded;
81
+
82
+ unsubscribe(
83
+ __settings.client.subscribe(
84
+ 'chatify://chat-member-added',
85
+ ([chatId, _, account, message, , read]) =>
86
+ chatId === id &&
87
+ updateCachedData((chat) => {
88
+ chat.members.push(account);
89
+ chat.lastReadMessageId = read ? message.id : chat.lastReadMessageId;
90
+ }),
91
+ ),
92
+ __settings.client.subscribe(
93
+ 'chatify://chat-member-removed',
94
+ ([chatId, accountId, , message, read]) =>
95
+ id === chatId &&
96
+ updateCachedData((chat) => {
97
+ chat.members = chat.members.filter((x) => x.id !== accountId);
98
+ chat.lastReadMessageId = read ? message.id : chat.lastReadMessageId;
99
+ }),
100
+ ),
101
+ __settings.client.subscribe(
102
+ 'chatify://chat-name-changed',
103
+ ([chatId, newName, message, read]) =>
104
+ id === chatId &&
105
+ updateCachedData((chat) => {
106
+ chat.name = newName;
107
+ chat.lastReadMessageId = read ? message.id : chat.lastReadMessageId;
108
+ }),
109
+ ),
110
+ __settings.client.subscribe(
111
+ 'chatify://chat-new-message',
112
+ ([message]) =>
113
+ id === message.chatId &&
114
+ updateCachedData((chat) => {
115
+ chat.lastReadMessageId =
116
+ message.sentBy.id === __settings.me() ? message.id : chat.lastReadMessageId;
117
+ }),
118
+ ),
119
+ __settings.client.subscribe(
120
+ 'chatify://chat-message-read',
121
+ ([events]) =>
122
+ events.find((x) => x.chatId === id) &&
123
+ updateCachedData((chat) => {
124
+ const event = events.find((x) => x.chatId === id)!;
125
+ chat.lastReadMessageId = event.newLastReadMessageId;
126
+ }),
127
+ ),
128
+ ).when(cacheEntryRemoved);
129
+ },
130
+ }),
131
+
132
+ addChat: builder.mutation<string, { name: string; members: string[] }>({
133
+ queryFn: async ({ name, members }) => {
134
+ const chatId = await __settings.client.addChat({
135
+ name,
136
+ members,
137
+ });
138
+ return { data: chatId };
139
+ },
140
+ }),
141
+
142
+ updateChatName: builder.mutation<void, { id: string; name: string }>({
143
+ queryFn: async ({ id, name }) => {
144
+ await __settings.client.updateChatName({ id, name });
145
+ return { data: null! };
146
+ },
147
+ }),
148
+
149
+ // ====================================================
150
+ // ============= CHAT LIST =====================
151
+ // ====================================================
152
+
153
+ getChatList: builder.query<ChatListItem[], void>({
154
+ queryFn: async () => ({ data: await __settings.client.chats() }),
155
+ providesTags: ['chat', 'account'],
156
+ onCacheEntryAdded: async (_, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
157
+ await cacheDataLoaded;
158
+
159
+ unsubscribe(
160
+ __settings.client.subscribe('chatify://chat-created', ([chat]) =>
161
+ updateCachedData((chatList) => {
162
+ chatList.push(chat);
163
+ }),
164
+ ),
165
+
166
+ __settings.client.subscribe('chatify://chat-new-message', ([message]) =>
167
+ updateCachedData((chatList) => {
168
+ const chat = chatList.find((x) => x.id === message.chatId);
169
+
170
+ if (!chat) {
171
+ return;
172
+ }
173
+
174
+ chat.message = message;
175
+
176
+ if (message.sentBy.id === __settings.me()) {
177
+ chat.lastReadMessageId = message.id;
178
+ chat.totalUnreadCount = 0;
179
+ }
180
+
181
+ if (message.sentBy.id !== __settings.me()) {
182
+ chat.totalUnreadCount++;
183
+ }
184
+ }),
185
+ ),
186
+ __settings.client.subscribe('chatify://chat-message-read', ([events]) =>
187
+ updateCachedData((chatList) => {
188
+ for (const event of events) {
189
+ const chat = chatList.find((x) => x.id === event.chatId);
190
+
191
+ if (!chat) {
192
+ return;
193
+ }
194
+
195
+ chat.lastReadMessageId = event.newLastReadMessageId;
196
+ chat.totalUnreadCount = chat.totalUnreadCount - event.readCount;
197
+ }
198
+ }),
199
+ ),
200
+ __settings.client.subscribe(
201
+ 'chatify://chat-member-added',
202
+ ([chatId, chatName, account, message, , read]) =>
203
+ updateCachedData((chatList) => {
204
+ const chat = chatList.find((x) => x.id === chatId);
205
+
206
+ if (account.id === __settings.me() && !chat) {
207
+ chatList.push({
208
+ id: chatId,
209
+ name: chatName,
210
+ message,
211
+ totalUnreadCount: read ? 0 : 1,
212
+ active: true,
213
+ lastReadMessageId: read ? message.id : null,
214
+ });
215
+ }
216
+
217
+ if (!chat) {
218
+ return;
219
+ }
220
+
221
+ chat.message = message;
222
+ chat.active = true;
223
+
224
+ if (read) {
225
+ chat.totalUnreadCount = 0;
226
+ chat.lastReadMessageId = message.id;
227
+ } else {
228
+ chat.totalUnreadCount++;
229
+ }
230
+ }),
231
+ ),
232
+ __settings.client.subscribe(
233
+ 'chatify://chat-member-removed',
234
+ ([chatId, accountId, deleteHistory, message, read]) =>
235
+ updateCachedData((chatList) => {
236
+ if (accountId === __settings.me() && deleteHistory) {
237
+ return chatList.filter((x) => x.id !== chatId);
238
+ }
239
+
240
+ const chat = chatList.find((x) => x.id === chatId);
241
+
242
+ if (!chat) {
243
+ return;
244
+ }
245
+
246
+ chat.message = message;
247
+
248
+ if (accountId === __settings.me()) {
249
+ chat.active = false;
250
+ }
251
+
252
+ if (!read) {
253
+ chat.totalUnreadCount++;
254
+ } else {
255
+ chat.totalUnreadCount = 0;
256
+ chat.lastReadMessageId = message.id;
257
+ }
258
+ }),
259
+ ),
260
+ __settings.client.subscribe('chatify://chat-name-changed', ([chatId, newName, message, read]) =>
261
+ updateCachedData((chatList) => {
262
+ const chat = chatList.find((x) => x.id === chatId);
263
+ if (!chat) return;
264
+
265
+ chat.name = newName;
266
+ chat.message = message;
267
+
268
+ if (!read) {
269
+ chat.totalUnreadCount++;
270
+ } else {
271
+ chat.totalUnreadCount = 0;
272
+ chat.lastReadMessageId = message.id;
273
+ }
274
+ }),
275
+ ),
276
+ ).when(cacheEntryRemoved);
277
+ },
278
+ }),
279
+
280
+ // ====================================================
281
+ // ============ CHAT MEMBER ====================
282
+ // ====================================================
283
+
284
+ removeChatMember: builder.mutation<void, RemoveChatMemberRequest>({
285
+ queryFn: async (args) => {
286
+ await __settings.client.removeChatMember(args);
287
+ return { data: null! };
288
+ },
289
+ }),
290
+
291
+ addChatMember: builder.mutation<void, AddChatMemberRequest>({
292
+ queryFn: async (args) => {
293
+ await __settings.client.addChatMember(args);
294
+ return { data: null! };
295
+ },
296
+ }),
297
+
298
+ // ====================================================
299
+ // ============ CHAT MESSAGE ===================
300
+ // ====================================================
301
+
302
+ getChatMessageList: builder.query<ChatMessageListResult, { chatId: string }>({
303
+ queryFn: async ({ chatId }) => {
304
+ const messages = await __settings.client.chatMessages({
305
+ chatId,
306
+ skip: 0,
307
+ take: DEFAULT_MESSAGE_LIST_TAKE + 1,
308
+ });
309
+ return {
310
+ data: {
311
+ messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
312
+ hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
313
+ },
314
+ };
315
+ },
316
+ providesTags: ['message', 'chat', 'account'],
317
+ onCacheEntryAdded: async ({ chatId }, { dispatch, cacheEntryRemoved, cacheDataLoaded }) => {
318
+ await cacheDataLoaded;
319
+
320
+ unsubscribe(
321
+ __settings.client.subscribe('chatify://chat-new-message', ([message]) => {
322
+ message.chatId === chatId &&
323
+ dispatch(
324
+ chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
325
+ draft.messages.unshift(message);
326
+ }),
327
+ );
328
+ }),
329
+
330
+ __settings.client.subscribe('chatify://chat-member-added', ([eventChatId, , , message]) => {
331
+ eventChatId === chatId &&
332
+ dispatch(
333
+ chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
334
+ draft.messages.unshift(message);
335
+ }),
336
+ );
337
+ }),
338
+
339
+ __settings.client.subscribe('chatify://chat-member-removed', ([eventChatId, , , message]) => {
340
+ eventChatId === chatId &&
341
+ dispatch(
342
+ chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
343
+ draft.messages.unshift(message);
344
+ }),
345
+ );
346
+ }),
347
+
348
+ __settings.client.subscribe('chatify://chat-name-changed', ([eventChatId, , message]) => {
349
+ eventChatId === chatId &&
350
+ dispatch(
351
+ chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
352
+ draft.messages.unshift(message);
353
+ }),
354
+ );
355
+ }),
356
+ ).when(cacheEntryRemoved);
357
+ },
358
+ }),
359
+
360
+ fetchNextChatMessageList: builder.mutation<void, { chatId: string }>({
361
+ queryFn: async ({ chatId }, { getState }) => {
362
+ const current = chatifyApi.endpoints.getChatMessageList.select({ chatId })(getState() as any);
363
+ const messages = await __settings.client.chatMessages({
364
+ chatId,
365
+ skip: current.data!.messages.length,
366
+ take: DEFAULT_MESSAGE_LIST_TAKE + 1,
367
+ });
368
+ return {
369
+ data: null!,
370
+ meta: {
371
+ messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
372
+ hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
373
+ },
374
+ };
375
+ },
376
+ onQueryStarted: async ({ chatId }, { dispatch, queryFulfilled }) => {
377
+ const result = await queryFulfilled;
378
+ const meta: ChatMessageListResult = result.meta! as any;
379
+
380
+ dispatch(
381
+ chatifyApi.util.updateQueryData('getChatMessageList', { chatId }, (draft) => {
382
+ draft.hasMore = meta.hasMore;
383
+ draft.messages.push(...meta!.messages);
384
+ }),
385
+ );
386
+ },
387
+ }),
388
+
389
+ sendChatMessage: builder.mutation<void, SendChatMessageRequest>({
390
+ queryFn: async ({ chatId, text, files }) => {
391
+ await __settings.client.sendChatMessage({
392
+ chatId,
393
+ text,
394
+ files,
395
+ });
396
+
397
+ return { data: null! };
398
+ },
399
+ }),
400
+
401
+ readChatMessage: builder.mutation<void, { id: string }>({
402
+ queryFn: async () => {
403
+ return { data: null! };
404
+ },
405
+ onQueryStarted: async ({ id }, { dispatch }) => {
406
+ CHAT_MESSAGE_READ_QUEUE.push(id);
407
+ dispatch(chatifyApi.endpoints.getChatMessageReadQueue.initiate(undefined, { forceRefetch: true }));
408
+ },
409
+ }),
410
+
411
+ getChatMessageReadQueue: builder.query<DebounceValue<string>[], void>({
412
+ queryFn: async () => ({ data: CHAT_MESSAGE_READ_QUEUE.units }),
413
+ onCacheEntryAdded: async (_, { dispatch, cacheEntryRemoved }) => {
414
+ unsubscribe(
415
+ CHAT_MESSAGE_READ_QUEUE.subscribe((value) => {
416
+ dispatch(
417
+ chatifyApi.util.updateQueryData('getChatMessageReadQueue', undefined, () => value.units),
418
+ );
419
+ }),
420
+ ).when(cacheEntryRemoved);
421
+ },
422
+ }),
423
+
424
+ // ====================================================
425
+ // =============== THREAD ======================s
426
+ // ====================================================
427
+ getWatchThreadList: builder.query<ThreadWatchListItem[], void>({
428
+ queryFn: async () => {
429
+ const threads = await __settings.client.watchThreads();
430
+ return { data: threads };
431
+ },
432
+ providesTags: ['account', 'thread'],
433
+ onCacheEntryAdded: async (_, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
434
+ await cacheDataLoaded;
435
+
436
+ unsubscribe(
437
+ __settings.client.subscribe(
438
+ 'chatify://thread-created',
439
+ ([thread, watch]) =>
440
+ watch &&
441
+ updateCachedData((threads) => {
442
+ threads.push(thread);
443
+ }),
444
+ ),
445
+ __settings.client.subscribe('chatify://thread-message-new', ([threadId, message, readForId]) =>
446
+ updateCachedData((threads) => {
447
+ const thread = threads.find((x) => x.id === threadId);
448
+ if (!thread) return;
449
+
450
+ thread.lastMessage = message;
451
+
452
+ if (readForId === __settings.me()) {
453
+ thread.lastReadMessageId = message.id;
454
+ }
455
+ }),
456
+ ),
457
+ __settings.client.subscribe('chatify://thread-message-read', ([threadId, messageId]) =>
458
+ updateCachedData((threads) => {
459
+ const thread = threads.find((x) => x.id === threadId);
460
+ if (!thread) return;
461
+
462
+ thread.lastReadMessageId = messageId;
463
+ }),
464
+ ),
465
+ __settings.client.subscribe('chatify://thread-watch-added', ([thread]) =>
466
+ updateCachedData((threads) => {
467
+ threads.push(thread);
468
+ }),
469
+ ),
470
+ __settings.client.subscribe('chatify://thread-watch-removed', ([id]) =>
471
+ updateCachedData((threads) => {
472
+ const index = threads.findIndex((x) => x.id === id);
473
+ if (index !== -1) threads.splice(index, 1);
474
+ }),
475
+ ),
476
+ __settings.client.subscribe('chatify://thread-updated', ([threadId, threadName]) =>
477
+ updateCachedData((threads) => {
478
+ const thread = threads.find((x) => x.id === threadId);
479
+ if (!thread) return;
480
+
481
+ thread.name = threadName;
482
+ }),
483
+ ),
484
+ ).when(cacheEntryRemoved);
485
+ },
486
+ }),
487
+
488
+ getThread: builder.query<Thread, { id: string }>({
489
+ queryFn: async ({ id }) => {
490
+ const threads = await __settings.client.thread(id);
491
+ return { data: threads };
492
+ },
493
+ providesTags: ['account', 'thread'],
494
+ onCacheEntryAdded: async ({ id }, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
495
+ await cacheDataLoaded;
496
+
497
+ unsubscribe(
498
+ __settings.client.subscribe(
499
+ 'chatify://thread-message-read',
500
+ ([threadId, messageId]) =>
501
+ id === threadId &&
502
+ updateCachedData((t) => {
503
+ t.lastReadMessageId = messageId;
504
+ }),
505
+ ),
506
+ __settings.client.subscribe(
507
+ 'chatify://thread-message-new',
508
+ ([threadId, message, readForId]) =>
509
+ id === threadId &&
510
+ updateCachedData((thread) => {
511
+ thread.lastMessageId = message.id;
512
+ thread.lastReadMessageId =
513
+ readForId === __settings.me() ? message.id : thread.lastReadMessageId;
514
+ }),
515
+ ),
516
+ __settings.client.subscribe(
517
+ 'chatify://thread-watch-added',
518
+ ([threadListItem]) =>
519
+ id === threadListItem.id &&
520
+ updateCachedData((thread) => {
521
+ thread.watch = true;
522
+ thread.lastMessageId = threadListItem.lastMessage?.id ?? null;
523
+ thread.lastReadMessageId = threadListItem.lastReadMessageId ?? null;
524
+ }),
525
+ ),
526
+ __settings.client.subscribe(
527
+ 'chatify://thread-watch-removed',
528
+ ([threadId]) =>
529
+ id === threadId &&
530
+ updateCachedData((thread) => {
531
+ thread.watch = false;
532
+ }),
533
+ ),
534
+ __settings.client.subscribe(
535
+ 'chatify://thread-updated',
536
+ ([threadId, threadName]) =>
537
+ id === threadId &&
538
+ updateCachedData((thread) => {
539
+ thread.name = threadName;
540
+ }),
541
+ ),
542
+ ).when(cacheEntryRemoved);
543
+ },
544
+ }),
545
+
546
+ watchThread: builder.mutation<void, { id: string; watch: boolean }>({
547
+ queryFn: async ({ id, watch }) => {
548
+ await __settings.client.watchThread(id, watch);
549
+ return { data: null! };
550
+ },
551
+ }),
552
+
553
+ // ====================================================
554
+ // ============ THREAD MESSAGE =================
555
+ // ====================================================
556
+
557
+ getThreadMessageList: builder.query<ThreadMessageList, { threadId: string }>({
558
+ queryFn: async (args) => {
559
+ const requestArgs = {
560
+ skip: 0,
561
+ take: DEFAULT_MESSAGE_LIST_TAKE + 1,
562
+ ...args,
563
+ };
564
+ const messages = await __settings.client.threadMessages(requestArgs);
565
+ return {
566
+ data: {
567
+ messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
568
+ hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
569
+ },
570
+ };
571
+ },
572
+ providesTags: ['account', 'thread', 'thread-message'],
573
+ onCacheEntryAdded: async ({ threadId }, { cacheEntryRemoved, cacheDataLoaded, updateCachedData }) => {
574
+ await cacheDataLoaded;
575
+
576
+ unsubscribe(
577
+ __settings.client.subscribe('chatify://thread-message-new', ([_threadId, message]) => {
578
+ threadId === _threadId &&
579
+ updateCachedData((messageList) => {
580
+ !messageList.messages.some((x) => x.id === message.id) &&
581
+ messageList.messages.unshift(message);
582
+ });
583
+ }),
584
+ ).when(cacheEntryRemoved);
585
+ },
586
+ }),
587
+
588
+ fetchNextThreadMessageList: builder.mutation<void, { threadId: string }>({
589
+ queryFn: async ({ threadId }, { getState }) => {
590
+ const current = chatifyApi.endpoints.getThreadMessageList.select({ threadId })(getState() as any);
591
+ const messages = await __settings.client.threadMessages({
592
+ threadId,
593
+ skip: current.data!.messages.length,
594
+ take: DEFAULT_MESSAGE_LIST_TAKE + 1,
595
+ });
596
+ return {
597
+ data: null!,
598
+ meta: {
599
+ messages: messages.slice(0, DEFAULT_MESSAGE_LIST_TAKE),
600
+ hasMore: messages.length === DEFAULT_MESSAGE_LIST_TAKE + 1,
601
+ },
602
+ };
603
+ },
604
+ onQueryStarted: async ({ threadId }, { dispatch, queryFulfilled }) => {
605
+ const result = await queryFulfilled;
606
+ const meta: ThreadMessageList = result.meta! as any;
607
+
608
+ dispatch(
609
+ chatifyApi.util.updateQueryData('getThreadMessageList', { threadId }, (draft) => {
610
+ draft.hasMore = meta.hasMore;
611
+ draft.messages.push(...meta!.messages);
612
+ }),
613
+ );
614
+ },
615
+ }),
616
+
617
+ sendThreadMessage: builder.mutation<string, SendThreadMessageRequest>({
618
+ queryFn: async (args) => {
619
+ const id = await __settings.client.sendThreadMessage(args);
620
+ return { data: id };
621
+ },
622
+ }),
623
+
624
+ readThreadMessage: builder.mutation<void, { id: string }>({
625
+ queryFn: async () => {
626
+ return { data: null! };
627
+ },
628
+ onQueryStarted: async ({ id }, { dispatch }) => {
629
+ THREAD_MESSAGE_READ_QUEUE.push(id);
630
+ dispatch(chatifyApi.endpoints.getThreadMessageReadQueue.initiate(undefined, { forceRefetch: true }));
631
+ },
632
+ }),
633
+
634
+ getThreadMessageReadQueue: builder.query<DebounceValue<string>[], void>({
635
+ queryFn: async () => ({ data: THREAD_MESSAGE_READ_QUEUE.units }),
636
+ onCacheEntryAdded: async (_, { dispatch, cacheEntryRemoved }) => {
637
+ unsubscribe(
638
+ THREAD_MESSAGE_READ_QUEUE.subscribe((value) => {
639
+ dispatch(
640
+ chatifyApi.util.updateQueryData('getThreadMessageReadQueue', undefined, () => value.units),
641
+ );
642
+ }),
643
+ ).when(cacheEntryRemoved);
644
+ },
645
+ }),
646
+ }),
647
+ });
648
+
649
+ export function useChatListItem(id: string | null) {
650
+ return useSelector((state: any) =>
651
+ id != null
652
+ ? __chatifyApi.endpoints.getChatList
653
+ .select()(state)
654
+ .data?.find((x) => x.id === id)
655
+ : null,
656
+ );
657
+ }
658
+
659
+ export function useUnreadThreadMessageCount() {
660
+ const { data: threads, ...state } = chatifyApi.useGetWatchThreadListQuery();
661
+ const count = useMemo(() => (threads != null ? calcThreadListUnreadCount(threads) : null), [threads]);
662
+ return [count, state] as const;
663
+ }
664
+
665
+ type ChatifyApi = typeof __chatifyApi & {
666
+ settings: ChatifyApiSettings;
667
+ useChatListItem: typeof useChatListItem;
668
+ useUnreadThreadMessageCount: typeof useUnreadThreadMessageCount;
669
+ };
670
+
671
+ export const chatifyApi: ChatifyApi = Object.assign(__chatifyApi, {
672
+ settings: __settings,
673
+ useChatListItem,
674
+ useUnreadThreadMessageCount,
675
+ });