@ermis-network/ermis-chat-react 2.0.0 → 2.0.1

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 (72) hide show
  1. package/README.md +144 -0
  2. package/dist/index.cjs +5087 -11279
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +632 -152
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.mts +273 -9
  7. package/dist/index.d.ts +273 -9
  8. package/dist/index.mjs +5085 -11295
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +2 -2
  11. package/src/components/Channel.tsx +0 -3
  12. package/src/components/ChannelActions.tsx +6 -1
  13. package/src/components/ChannelHeader.tsx +8 -32
  14. package/src/components/ChannelInfo/AddMemberModal.tsx +7 -1
  15. package/src/components/ChannelInfo/ChannelInfo.tsx +82 -2
  16. package/src/components/ChannelInfo/EditChannelModal.tsx +2 -2
  17. package/src/components/ChannelInfo/MediaGridItem.tsx +215 -78
  18. package/src/components/ChannelInfo/useChannelInfoTabs.tsx +170 -129
  19. package/src/components/ChannelList.tsx +72 -13
  20. package/src/components/CreateChannelModal.tsx +131 -12
  21. package/src/components/FilesPreview.tsx +8 -12
  22. package/src/components/FlatTopicGroupItem.tsx +27 -16
  23. package/src/components/ForwardMessageModal.tsx +11 -3
  24. package/src/components/MediaLightbox.tsx +444 -304
  25. package/src/components/MessageActionsBox.tsx +2 -0
  26. package/src/components/MessageInput.tsx +41 -12
  27. package/src/components/MessageItem.tsx +70 -25
  28. package/src/components/MessageQuickReactions.tsx +131 -128
  29. package/src/components/MessageReactions.tsx +47 -2
  30. package/src/components/MessageRenderers.tsx +1030 -433
  31. package/src/components/PinnedMessages.tsx +40 -12
  32. package/src/components/QuotedMessagePreview.tsx +99 -8
  33. package/src/components/RecoveryPin/RecoveryPin.tsx +279 -0
  34. package/src/components/RecoveryPin/index.ts +19 -0
  35. package/src/components/TopicList.tsx +20 -5
  36. package/src/components/TypingIndicator.tsx +3 -3
  37. package/src/components/UserPicker.tsx +26 -25
  38. package/src/components/VirtualMessageList.tsx +345 -125
  39. package/src/context/ChatProvider.tsx +27 -1
  40. package/src/hooks/useChannelListUpdates.ts +22 -1
  41. package/src/hooks/useChannelMessages.ts +338 -51
  42. package/src/hooks/useChannelRowUpdates.ts +18 -6
  43. package/src/hooks/useChatUser.ts +9 -1
  44. package/src/hooks/useE2eeAttachmentRenderer.ts +204 -0
  45. package/src/hooks/useE2eeFileUpload.ts +38 -0
  46. package/src/hooks/useFileUpload.ts +25 -5
  47. package/src/hooks/useForwardMessage.ts +210 -13
  48. package/src/hooks/useLoadMessages.ts +16 -4
  49. package/src/hooks/useMentions.ts +60 -6
  50. package/src/hooks/useMessageActions.ts +14 -8
  51. package/src/hooks/useMessageSend.ts +64 -12
  52. package/src/hooks/usePendingE2eeSends.ts +29 -0
  53. package/src/hooks/useRecoveryPin.ts +287 -0
  54. package/src/hooks/useScrollToMessage.ts +29 -4
  55. package/src/hooks/useTopicGroupUpdates.ts +49 -11
  56. package/src/index.ts +23 -0
  57. package/src/messageTypeUtils.ts +14 -0
  58. package/src/styles/_channel-info.css +9 -0
  59. package/src/styles/_channel-list.css +37 -14
  60. package/src/styles/_media-lightbox.css +36 -3
  61. package/src/styles/_message-bubble.css +381 -41
  62. package/src/styles/_message-input.css +8 -0
  63. package/src/styles/_message-list.css +67 -10
  64. package/src/styles/_message-quick-reactions.css +101 -59
  65. package/src/styles/_message-reactions.css +18 -32
  66. package/src/styles/_recovery-pin.css +97 -0
  67. package/src/styles/_tokens.css +5 -5
  68. package/src/styles/_typing-indicator.css +23 -13
  69. package/src/styles/index.css +1 -0
  70. package/src/types.ts +115 -1
  71. package/src/utils/avatarColors.ts +1 -1
  72. package/src/utils.ts +38 -18
@@ -184,19 +184,10 @@ export const UserPicker: React.FC<UserPickerProps> = ({
184
184
  const fetchUsers = async () => {
185
185
  if (!client) return;
186
186
 
187
- const cacheKey = friendsOnly
188
- ? `${client.userID || 'anon'}-friends`
189
- : `${client.userID || 'anon'}-${pageSize}`;
190
-
191
- if (globalUsersCache[cacheKey] && globalUsersCache[cacheKey].users.length > 0) {
192
- const cached = globalUsersCache[cacheKey];
193
- setAllUsers(cached.users);
194
- setHasMore(cached.hasMore);
195
- setPage(cached.page);
196
- setLoading(false);
197
- return;
198
- }
199
-
187
+ // For friendsOnly mode, always read fresh data from activeChannels.
188
+ // Do NOT use globalUsersCache here — the friend list can change at any
189
+ // time (e.g. a new friend request was accepted) and caching would
190
+ // return stale results, hiding the newly added friend.
200
191
  if (friendsOnly) {
201
192
  const friends: UserPickerUser[] = [];
202
193
  const seenIds = new Set<string>();
@@ -222,19 +213,24 @@ export const UserPicker: React.FC<UserPickerProps> = ({
222
213
  setHasMore(false);
223
214
  setPage(1);
224
215
  setLoading(false);
225
-
226
- globalUsersCache[cacheKey] = {
227
- users: friends,
228
- page: 1,
229
- hasMore: false,
230
- };
231
216
  }
232
217
  return;
233
218
  }
234
219
 
220
+ const cacheKey = `${client.userID || 'anon'}-${pageSize}`;
221
+
222
+ if (globalUsersCache[cacheKey] && globalUsersCache[cacheKey].users.length > 0) {
223
+ const cached = globalUsersCache[cacheKey];
224
+ setAllUsers(cached.users);
225
+ setHasMore(cached.hasMore);
226
+ setPage(cached.page);
227
+ setLoading(false);
228
+ return;
229
+ }
230
+
235
231
  try {
236
232
  setLoading(true);
237
- const response = await client.queryUsers(String(pageSize), 1);
233
+ const response = await client.queryUsers(pageSize, 1);
238
234
  if (active && response.data) {
239
235
  setAllUsers(response.data);
240
236
  setHasMore(response.data.length >= pageSize);
@@ -254,7 +250,7 @@ export const UserPicker: React.FC<UserPickerProps> = ({
254
250
  };
255
251
  fetchUsers();
256
252
  return () => { active = false; };
257
- }, [client, pageSize]);
253
+ }, [client, pageSize, friendsOnly]);
258
254
 
259
255
  /* ---------- 2. Load more (infinite scroll) ---------- */
260
256
  const loadMore = useCallback(async () => {
@@ -262,7 +258,7 @@ export const UserPicker: React.FC<UserPickerProps> = ({
262
258
  const nextPage = page + 1;
263
259
  setLoadingMore(true);
264
260
  try {
265
- const response = await client.queryUsers(String(pageSize), nextPage);
261
+ const response = await client.queryUsers(pageSize, nextPage);
266
262
  if (response.data) {
267
263
  setAllUsers(prev => {
268
264
  const existingIds = new Set(prev.map(u => u.id));
@@ -294,12 +290,17 @@ export const UserPicker: React.FC<UserPickerProps> = ({
294
290
  const localFilteredUsers = useMemo(() => {
295
291
  const term = removeAccents(search.toLowerCase().trim());
296
292
  if (!term) return allUsers;
297
- return allUsers.filter(u => {
293
+ const result: UserPickerUser[] = [];
294
+ for (const u of allUsers) {
298
295
  const name = removeAccents((u.name || '').toLowerCase());
299
296
  const email = removeAccents((u.email || '').toLowerCase());
300
297
  const phone = removeAccents((u.phone || '').toLowerCase());
301
- return name.includes(term) || email.includes(term) || phone.includes(term);
302
- });
298
+ if (name.startsWith(term) || email.startsWith(term) || phone.startsWith(term)) {
299
+ result.push(u);
300
+ if (result.length >= 100) break; // optimize for large room
301
+ }
302
+ }
303
+ return result;
303
304
  }, [search, allUsers]);
304
305
 
305
306
  /* ---------- 4. Remote search fallback ---------- */