stream-chat-react-native-core 5.8.1-beta.3 → 5.9.0-beta.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 (43) hide show
  1. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerItem.js +38 -65
  2. package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerItem.js.map +1 -1
  3. package/lib/commonjs/components/ChannelList/ChannelList.js +6 -2
  4. package/lib/commonjs/components/ChannelList/ChannelList.js.map +1 -1
  5. package/lib/commonjs/components/ChannelList/hooks/listeners/useNewMessage.js +22 -17
  6. package/lib/commonjs/components/ChannelList/hooks/listeners/useNewMessage.js.map +1 -1
  7. package/lib/commonjs/components/ChannelList/hooks/listeners/useNewMessageNotification.js +17 -7
  8. package/lib/commonjs/components/ChannelList/hooks/listeners/useNewMessageNotification.js.map +1 -1
  9. package/lib/commonjs/components/MessageInput/FileUploadPreview.js +22 -21
  10. package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
  11. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +82 -112
  12. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  13. package/lib/commonjs/types/types.js.map +1 -1
  14. package/lib/commonjs/version.json +1 -1
  15. package/lib/module/components/AttachmentPicker/components/AttachmentPickerItem.js +38 -65
  16. package/lib/module/components/AttachmentPicker/components/AttachmentPickerItem.js.map +1 -1
  17. package/lib/module/components/ChannelList/ChannelList.js +6 -2
  18. package/lib/module/components/ChannelList/ChannelList.js.map +1 -1
  19. package/lib/module/components/ChannelList/hooks/listeners/useNewMessage.js +22 -17
  20. package/lib/module/components/ChannelList/hooks/listeners/useNewMessage.js.map +1 -1
  21. package/lib/module/components/ChannelList/hooks/listeners/useNewMessageNotification.js +17 -7
  22. package/lib/module/components/ChannelList/hooks/listeners/useNewMessageNotification.js.map +1 -1
  23. package/lib/module/components/MessageInput/FileUploadPreview.js +22 -21
  24. package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
  25. package/lib/module/contexts/messageInputContext/MessageInputContext.js +82 -112
  26. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  27. package/lib/module/types/types.js.map +1 -1
  28. package/lib/module/version.json +1 -1
  29. package/lib/typescript/components/ChannelList/ChannelList.d.ts +23 -0
  30. package/lib/typescript/components/ChannelList/hooks/listeners/useNewMessage.d.ts +3 -2
  31. package/lib/typescript/components/ChannelList/hooks/listeners/useNewMessageNotification.d.ts +2 -1
  32. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +1 -6
  33. package/lib/typescript/types/types.d.ts +1 -0
  34. package/package.json +1 -1
  35. package/src/components/AttachmentPicker/components/AttachmentPickerItem.tsx +3 -5
  36. package/src/components/ChannelList/ChannelList.tsx +34 -0
  37. package/src/components/ChannelList/__tests__/ChannelList.test.js +37 -0
  38. package/src/components/ChannelList/hooks/listeners/useNewMessage.ts +29 -19
  39. package/src/components/ChannelList/hooks/listeners/useNewMessageNotification.ts +10 -0
  40. package/src/components/MessageInput/FileUploadPreview.tsx +1 -0
  41. package/src/contexts/messageInputContext/MessageInputContext.tsx +10 -32
  42. package/src/types/types.ts +1 -0
  43. package/src/version.json +1 -1
@@ -297,6 +297,24 @@ describe('ChannelList', () => {
297
297
  expect(within(items[2]).getByText(newMessage.text)).toBeTruthy();
298
298
  });
299
299
  });
300
+ it('should call the `onNewMessage` function prop, if provided', async () => {
301
+ const onNewMessage = jest.fn();
302
+ const { getByTestId } = render(
303
+ <Chat client={chatClient}>
304
+ <ChannelList {...props} onNewMessage={onNewMessage} />
305
+ </Chat>,
306
+ );
307
+
308
+ await waitFor(() => {
309
+ expect(getByTestId('channel-list')).toBeTruthy();
310
+ });
311
+
312
+ act(() => dispatchMessageNewEvent(chatClient, testChannel2.channel));
313
+
314
+ await waitFor(() => {
315
+ expect(onNewMessage).toHaveBeenCalledTimes(1);
316
+ });
317
+ });
300
318
  });
301
319
 
302
320
  describe('notification.message_new', () => {
@@ -346,6 +364,25 @@ describe('ChannelList', () => {
346
364
  expect(onMessageNew).toHaveBeenCalledTimes(1);
347
365
  });
348
366
  });
367
+
368
+ it('should call the `onNewMessageNotification` function prop, if provided', async () => {
369
+ const onNewMessageNotification = jest.fn();
370
+ const { getByTestId } = render(
371
+ <Chat client={chatClient}>
372
+ <ChannelList {...props} onNewMessageNotification={onNewMessageNotification} />
373
+ </Chat>,
374
+ );
375
+
376
+ await waitFor(() => {
377
+ expect(getByTestId('channel-list')).toBeTruthy();
378
+ });
379
+
380
+ act(() => dispatchNotificationMessageNewEvent(chatClient, testChannel2.channel));
381
+
382
+ await waitFor(() => {
383
+ expect(onNewMessageNotification).toHaveBeenCalledTimes(1);
384
+ });
385
+ });
349
386
  });
350
387
 
351
388
  describe('notification.added_to_channel', () => {
@@ -11,43 +11,53 @@ type Parameters<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultSt
11
11
  {
12
12
  lockChannelOrder: boolean;
13
13
  setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[] | null>>;
14
+ onNewMessage?: (
15
+ lockChannelOrder: boolean,
16
+ setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[] | null>>,
17
+ event: Event<StreamChatGenerics>,
18
+ ) => void;
14
19
  };
15
20
 
16
21
  export const useNewMessage = <
17
22
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
18
23
  >({
19
24
  lockChannelOrder,
25
+ onNewMessage,
20
26
  setChannels,
21
27
  }: Parameters<StreamChatGenerics>) => {
22
28
  const { client } = useChatContext<StreamChatGenerics>();
23
29
 
24
30
  useEffect(() => {
25
31
  const handleEvent = (event: Event<StreamChatGenerics>) => {
26
- setChannels((channels) => {
27
- if (!channels) return channels;
32
+ if (typeof onNewMessage === 'function') {
33
+ onNewMessage(lockChannelOrder, setChannels, event);
34
+ } else {
35
+ setChannels((channels) => {
36
+ if (!channels) return channels;
28
37
 
29
- if (!lockChannelOrder && event.cid && event.channel_type && event.channel_id) {
30
- const targetChannelIndex = channels.findIndex((c) => c.cid === event.cid);
38
+ if (!lockChannelOrder && event.cid && event.channel_type && event.channel_id) {
39
+ const targetChannelIndex = channels.findIndex((c) => c.cid === event.cid);
31
40
 
32
- if (targetChannelIndex >= 0) {
33
- return moveChannelUp<StreamChatGenerics>({
34
- channels,
35
- cid: event.cid,
36
- });
37
- }
41
+ if (targetChannelIndex >= 0) {
42
+ return moveChannelUp<StreamChatGenerics>({
43
+ channels,
44
+ cid: event.cid,
45
+ });
46
+ }
38
47
 
39
- // If channel doesn't exist in existing list, check in activeChannels as well.
40
- // It may happen that channel was hidden using channel.hide(). In that case
41
- // We remove it from `channels` state, but its still being watched and exists in client.activeChannels.
42
- const channel = client.channel(event.channel_type, event.channel_id);
48
+ // If channel doesn't exist in existing list, check in activeChannels as well.
49
+ // It may happen that channel was hidden using channel.hide(). In that case
50
+ // We remove it from `channels` state, but its still being watched and exists in client.activeChannels.
51
+ const channel = client.channel(event.channel_type, event.channel_id);
43
52
 
44
- if (channel.initialized) {
45
- return [channel, ...channels];
53
+ if (channel.initialized) {
54
+ return [channel, ...channels];
55
+ }
46
56
  }
47
- }
48
57
 
49
- return [...channels];
50
- });
58
+ return [...channels];
59
+ });
60
+ }
51
61
  };
52
62
 
53
63
  const listener = client?.on('message.new', handleEvent);
@@ -16,12 +16,17 @@ type Parameters<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultSt
16
16
  setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[] | null>>,
17
17
  event: Event<StreamChatGenerics>,
18
18
  ) => void;
19
+ onNewMessageNotification?: (
20
+ setChannels: React.Dispatch<React.SetStateAction<Channel<StreamChatGenerics>[] | null>>,
21
+ event: Event<StreamChatGenerics>,
22
+ ) => void;
19
23
  };
20
24
 
21
25
  export const useNewMessageNotification = <
22
26
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
23
27
  >({
24
28
  onMessageNew,
29
+ onNewMessageNotification,
25
30
  setChannels,
26
31
  }: Parameters<StreamChatGenerics>) => {
27
32
  const { client } = useChatContext<StreamChatGenerics>();
@@ -30,6 +35,11 @@ export const useNewMessageNotification = <
30
35
  const handleEvent = async (event: Event<StreamChatGenerics>) => {
31
36
  if (typeof onMessageNew === 'function') {
32
37
  onMessageNew(setChannels, event);
38
+ console.warn(
39
+ 'onMessageNew is deprecated and will be removed in future release. Please use onNewMessageNotification to establish the same behaviour',
40
+ );
41
+ } else if (typeof onNewMessageNotification === 'function') {
42
+ onNewMessageNotification(setChannels, event);
33
43
  } else {
34
44
  if (event.channel?.id && event.channel?.type) {
35
45
  const channel = await getChannel({
@@ -69,6 +69,7 @@ const styles = StyleSheet.create({
69
69
  borderRadius: 12,
70
70
  marginLeft: 8,
71
71
  marginRight: 8,
72
+ marginTop: 2,
72
73
  },
73
74
  unsupportedFile: {
74
75
  flexDirection: 'row',
@@ -1,6 +1,6 @@
1
1
  import React, { PropsWithChildren, useContext, useEffect, useRef, useState } from 'react';
2
2
 
3
- import { Alert, Keyboard } from 'react-native';
3
+ import { Alert, Keyboard, Platform } from 'react-native';
4
4
 
5
5
  import type { TextInput, TextInputProps } from 'react-native';
6
6
 
@@ -327,12 +327,7 @@ export type InputMessageInputContextValue<
327
327
  * @overrideType Function
328
328
  */
329
329
  doDocUploadRequest?: (
330
- file: {
331
- name: string;
332
- size?: string | number;
333
- type?: string;
334
- uri?: string;
335
- },
330
+ file: File,
336
331
  channel: ChannelContextValue<StreamChatGenerics>['channel'],
337
332
  ) => Promise<SendFileAPIResponse>;
338
333
  /**
@@ -972,7 +967,9 @@ export const MessageInputProvider = <
972
967
  if (value.doDocUploadRequest) {
973
968
  response = await value.doDocUploadRequest(file, channel);
974
969
  } else if (channel && file.uri) {
975
- response = await channel.sendFile(file.uri, file.name, file.type);
970
+ // For the case of expo messaging app where you need to fetch the file uri from file id. Here it is only done for iOS since for android the file.uri is fine.
971
+ const localAssetURI = Platform.OS === 'ios' && file.id && (await getLocalAssetUri(file.id));
972
+ response = await channel.sendFile(localAssetURI || file.uri, file.name, file.type);
976
973
  }
977
974
  const extraData: Partial<FileUpload> = { thumb_url: response.thumb_url, url: response.file };
978
975
  setFileUploads(getUploadSetStateAction(id, FileState.UPLOADED, extraData));
@@ -991,23 +988,9 @@ export const MessageInputProvider = <
991
988
  let response = {} as SendFileAPIResponse;
992
989
 
993
990
  try {
994
- /**
995
- * Expo now uses the assets-library which is also how remote
996
- * native files are presented. We now return a file id from Expo
997
- * only, if that file id exits we call getLocalAssetUri to download
998
- * the asset for expo before uploading it. We do the same for native
999
- * if the uri includes assets-library, this uses the CameraRoll.save
1000
- * function to also create a local uri.
1001
- */
1002
- const getLocalUri = async () => {
1003
- if (file.id) {
1004
- return await getLocalAssetUri(file.id);
1005
- } else if (file.uri?.match(/assets-library/)) {
1006
- return await getLocalAssetUri(file.uri);
1007
- }
1008
- return file.uri;
1009
- };
1010
- const uri = file.name || (await getLocalUri()) || '';
991
+ // For the case of expo messaging app where you need to fetch the file uri from file id. Here it is only done for iOS since for android the file.uri is fine.
992
+ const localAssetURI = Platform.OS === 'ios' && file.id && (await getLocalAssetUri(file.id));
993
+ const uri = localAssetURI || file.uri || '';
1011
994
  /**
1012
995
  * We skip compression if:
1013
996
  * - the file is from the camera as that should already be compressed
@@ -1068,12 +1051,7 @@ export const MessageInputProvider = <
1068
1051
  }
1069
1052
  };
1070
1053
 
1071
- const uploadNewFile = async (file: {
1072
- name: string;
1073
- size?: number | string;
1074
- type?: string;
1075
- uri?: string;
1076
- }) => {
1054
+ const uploadNewFile = async (file: File) => {
1077
1055
  const id: string = generateRandomId();
1078
1056
  const mimeType: string | boolean = lookup(file.name);
1079
1057
 
@@ -1092,7 +1070,7 @@ export const MessageInputProvider = <
1092
1070
  const newFile: FileUpload = {
1093
1071
  duration: 0,
1094
1072
  file: { ...file, type: mimeType || file?.type },
1095
- id,
1073
+ id: file.id || id,
1096
1074
  paused: true,
1097
1075
  progress: 0,
1098
1076
  state: fileState,
@@ -17,6 +17,7 @@ export type Asset = {
17
17
  export type File = {
18
18
  name: string;
19
19
  duration?: string | null;
20
+ id?: string;
20
21
  size?: number | string;
21
22
  type?: string;
22
23
  uri?: string;
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "5.8.1-beta.3"
2
+ "version": "5.9.0-beta.1"
3
3
  }