stream-chat-react-native-core 4.3.1 → 4.4.0-beta.3

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 (186) hide show
  1. package/README.md +3 -3
  2. package/lib/commonjs/components/Attachment/Card.js +25 -28
  3. package/lib/commonjs/components/Attachment/Card.js.map +1 -1
  4. package/lib/commonjs/components/Attachment/FileAttachment.js +19 -24
  5. package/lib/commonjs/components/Attachment/FileAttachment.js.map +1 -1
  6. package/lib/commonjs/components/Attachment/Giphy.js +27 -25
  7. package/lib/commonjs/components/Attachment/Giphy.js.map +1 -1
  8. package/lib/commonjs/components/Attachment/hooks/useGoToURL.js +42 -0
  9. package/lib/commonjs/components/Attachment/hooks/useGoToURL.js.map +1 -0
  10. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +11 -7
  11. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  12. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  13. package/lib/commonjs/components/Channel/hooks/useCreatePaginatedMessageListContext.js +4 -12
  14. package/lib/commonjs/components/Channel/hooks/useCreatePaginatedMessageListContext.js.map +1 -1
  15. package/lib/commonjs/components/Channel/hooks/useCreateThreadContext.js +4 -12
  16. package/lib/commonjs/components/Channel/hooks/useCreateThreadContext.js.map +1 -1
  17. package/lib/commonjs/components/Chat/Chat.js +8 -4
  18. package/lib/commonjs/components/Chat/Chat.js.map +1 -1
  19. package/lib/commonjs/components/Chat/hooks/useAppSettings.js +80 -0
  20. package/lib/commonjs/components/Chat/hooks/useAppSettings.js.map +1 -0
  21. package/lib/commonjs/components/Chat/hooks/useCreateChatContext.js +3 -1
  22. package/lib/commonjs/components/Chat/hooks/useCreateChatContext.js.map +1 -1
  23. package/lib/commonjs/components/Message/Message.js +27 -22
  24. package/lib/commonjs/components/Message/Message.js.map +1 -1
  25. package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js +28 -14
  26. package/lib/commonjs/components/Message/MessageSimple/utils/renderText.js.map +1 -1
  27. package/lib/commonjs/components/MessageInput/FileUploadPreview.js +108 -40
  28. package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
  29. package/lib/commonjs/components/MessageInput/ImageUploadPreview.js +117 -24
  30. package/lib/commonjs/components/MessageInput/ImageUploadPreview.js.map +1 -1
  31. package/lib/commonjs/components/MessageInput/UploadProgressIndicator.js +52 -20
  32. package/lib/commonjs/components/MessageInput/UploadProgressIndicator.js.map +1 -1
  33. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js +8 -6
  34. package/lib/commonjs/components/MessageList/ScrollToBottomButton.js.map +1 -1
  35. package/lib/commonjs/contexts/chatContext/ChatContext.js +2 -2
  36. package/lib/commonjs/contexts/chatContext/ChatContext.js.map +1 -1
  37. package/lib/commonjs/contexts/messageContext/MessageContext.js +2 -2
  38. package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
  39. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +145 -119
  40. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  41. package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
  42. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  43. package/lib/commonjs/i18n/en.json +2 -0
  44. package/lib/commonjs/i18n/fr.json +2 -0
  45. package/lib/commonjs/i18n/hi.json +2 -0
  46. package/lib/commonjs/i18n/it.json +2 -0
  47. package/lib/commonjs/i18n/ja.json +3 -1
  48. package/lib/commonjs/i18n/ko.json +3 -1
  49. package/lib/commonjs/i18n/nl.json +2 -0
  50. package/lib/commonjs/i18n/ru.json +2 -0
  51. package/lib/commonjs/i18n/tr.json +2 -0
  52. package/lib/commonjs/icons/Warning.js +38 -0
  53. package/lib/commonjs/icons/Warning.js.map +1 -0
  54. package/lib/commonjs/icons/index.js +13 -0
  55. package/lib/commonjs/icons/index.js.map +1 -1
  56. package/lib/commonjs/utils/utils.js +33 -2
  57. package/lib/commonjs/utils/utils.js.map +1 -1
  58. package/lib/commonjs/version.json +1 -1
  59. package/lib/module/components/Attachment/Card.js +25 -28
  60. package/lib/module/components/Attachment/Card.js.map +1 -1
  61. package/lib/module/components/Attachment/FileAttachment.js +19 -24
  62. package/lib/module/components/Attachment/FileAttachment.js.map +1 -1
  63. package/lib/module/components/Attachment/Giphy.js +27 -25
  64. package/lib/module/components/Attachment/Giphy.js.map +1 -1
  65. package/lib/module/components/Attachment/hooks/useGoToURL.js +42 -0
  66. package/lib/module/components/Attachment/hooks/useGoToURL.js.map +1 -0
  67. package/lib/module/components/AttachmentPicker/AttachmentPicker.js +11 -7
  68. package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  69. package/lib/module/components/Channel/Channel.js.map +1 -1
  70. package/lib/module/components/Channel/hooks/useCreatePaginatedMessageListContext.js +4 -12
  71. package/lib/module/components/Channel/hooks/useCreatePaginatedMessageListContext.js.map +1 -1
  72. package/lib/module/components/Channel/hooks/useCreateThreadContext.js +4 -12
  73. package/lib/module/components/Channel/hooks/useCreateThreadContext.js.map +1 -1
  74. package/lib/module/components/Chat/Chat.js +8 -4
  75. package/lib/module/components/Chat/Chat.js.map +1 -1
  76. package/lib/module/components/Chat/hooks/useAppSettings.js +80 -0
  77. package/lib/module/components/Chat/hooks/useAppSettings.js.map +1 -0
  78. package/lib/module/components/Chat/hooks/useCreateChatContext.js +3 -1
  79. package/lib/module/components/Chat/hooks/useCreateChatContext.js.map +1 -1
  80. package/lib/module/components/Message/Message.js +27 -22
  81. package/lib/module/components/Message/Message.js.map +1 -1
  82. package/lib/module/components/Message/MessageSimple/utils/renderText.js +28 -14
  83. package/lib/module/components/Message/MessageSimple/utils/renderText.js.map +1 -1
  84. package/lib/module/components/MessageInput/FileUploadPreview.js +108 -40
  85. package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
  86. package/lib/module/components/MessageInput/ImageUploadPreview.js +117 -24
  87. package/lib/module/components/MessageInput/ImageUploadPreview.js.map +1 -1
  88. package/lib/module/components/MessageInput/UploadProgressIndicator.js +52 -20
  89. package/lib/module/components/MessageInput/UploadProgressIndicator.js.map +1 -1
  90. package/lib/module/components/MessageList/ScrollToBottomButton.js +8 -6
  91. package/lib/module/components/MessageList/ScrollToBottomButton.js.map +1 -1
  92. package/lib/module/contexts/chatContext/ChatContext.js +2 -2
  93. package/lib/module/contexts/chatContext/ChatContext.js.map +1 -1
  94. package/lib/module/contexts/messageContext/MessageContext.js +2 -2
  95. package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
  96. package/lib/module/contexts/messageInputContext/MessageInputContext.js +145 -119
  97. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  98. package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
  99. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  100. package/lib/module/i18n/en.json +2 -0
  101. package/lib/module/i18n/fr.json +2 -0
  102. package/lib/module/i18n/hi.json +2 -0
  103. package/lib/module/i18n/it.json +2 -0
  104. package/lib/module/i18n/ja.json +3 -1
  105. package/lib/module/i18n/ko.json +3 -1
  106. package/lib/module/i18n/nl.json +2 -0
  107. package/lib/module/i18n/ru.json +2 -0
  108. package/lib/module/i18n/tr.json +2 -0
  109. package/lib/module/icons/Warning.js +38 -0
  110. package/lib/module/icons/Warning.js.map +1 -0
  111. package/lib/module/icons/index.js +13 -0
  112. package/lib/module/icons/index.js.map +1 -1
  113. package/lib/module/utils/utils.js +33 -2
  114. package/lib/module/utils/utils.js.map +1 -1
  115. package/lib/module/version.json +1 -1
  116. package/lib/typescript/components/Attachment/FileAttachment.d.ts +0 -1
  117. package/lib/typescript/components/Attachment/hooks/useGoToURL.d.ts +2 -0
  118. package/lib/typescript/components/Chat/hooks/__tests__/useAppSettings.test.d.ts +1 -0
  119. package/lib/typescript/components/Chat/hooks/useAppSettings.d.ts +3 -0
  120. package/lib/typescript/components/Chat/hooks/useCreateChatContext.d.ts +1 -1
  121. package/lib/typescript/components/Message/Message.d.ts +12 -2
  122. package/lib/typescript/components/MessageInput/UploadProgressIndicator.d.ts +1 -3
  123. package/lib/typescript/contexts/chatContext/ChatContext.d.ts +5 -1
  124. package/lib/typescript/contexts/messageContext/MessageContext.d.ts +4 -4
  125. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +3 -3
  126. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +1 -0
  127. package/lib/typescript/i18n/en.json +2 -0
  128. package/lib/typescript/i18n/fr.json +2 -0
  129. package/lib/typescript/i18n/hi.json +2 -0
  130. package/lib/typescript/i18n/it.json +2 -0
  131. package/lib/typescript/i18n/ja.json +3 -1
  132. package/lib/typescript/i18n/ko.json +3 -1
  133. package/lib/typescript/i18n/nl.json +2 -0
  134. package/lib/typescript/i18n/ru.json +2 -0
  135. package/lib/typescript/i18n/tr.json +2 -0
  136. package/lib/typescript/icons/Warning.d.ts +3 -0
  137. package/lib/typescript/icons/index.d.ts +1 -0
  138. package/lib/typescript/utils/Streami18n.d.ts +6 -0
  139. package/lib/typescript/utils/utils.d.ts +15 -2
  140. package/package.json +2 -2
  141. package/src/components/Attachment/Card.tsx +5 -13
  142. package/src/components/Attachment/FileAttachment.tsx +5 -13
  143. package/src/components/Attachment/Giphy.tsx +3 -1
  144. package/src/components/Attachment/__tests__/Attachment.test.js +39 -0
  145. package/src/components/Attachment/hooks/useGoToURL.ts +27 -0
  146. package/src/components/AttachmentPicker/AttachmentPicker.tsx +23 -13
  147. package/src/components/Channel/Channel.tsx +1 -1
  148. package/src/components/Channel/hooks/useCreatePaginatedMessageListContext.ts +3 -9
  149. package/src/components/Channel/hooks/useCreateThreadContext.ts +3 -9
  150. package/src/components/ChannelList/hooks/listeners/__tests__/useChannelUpdated.test.tsx +1 -0
  151. package/src/components/Chat/Chat.tsx +4 -0
  152. package/src/components/Chat/hooks/__tests__/useAppSettings.test.tsx +34 -0
  153. package/src/components/Chat/hooks/useAppSettings.ts +39 -0
  154. package/src/components/Chat/hooks/useCreateChatContext.ts +2 -0
  155. package/src/components/Message/Message.tsx +56 -48
  156. package/src/components/Message/MessageSimple/utils/renderText.tsx +17 -2
  157. package/src/components/MessageInput/FileUploadPreview.tsx +60 -14
  158. package/src/components/MessageInput/ImageUploadPreview.tsx +95 -42
  159. package/src/components/MessageInput/UploadProgressIndicator.tsx +49 -22
  160. package/src/components/MessageInput/__tests__/FileUploadPreview.test.js +50 -80
  161. package/src/components/MessageInput/__tests__/ImageUploadPreview.test.js +49 -74
  162. package/src/components/MessageInput/__tests__/UploadProgressIndicator.test.js +36 -13
  163. package/src/components/MessageInput/__tests__/__snapshots__/MessageInput.test.js.snap +2 -2
  164. package/src/components/MessageInput/__tests__/__snapshots__/UploadProgressIndicator.test.js.snap +122 -17
  165. package/src/components/MessageList/ScrollToBottomButton.tsx +2 -1
  166. package/src/components/MessageList/__tests__/__snapshots__/ScrollToBottomButton.test.js.snap +1 -0
  167. package/src/contexts/chatContext/ChatContext.tsx +5 -1
  168. package/src/contexts/messageContext/MessageContext.tsx +7 -4
  169. package/src/contexts/messageInputContext/MessageInputContext.tsx +127 -96
  170. package/src/contexts/messageInputContext/hooks/useMessageDetailsForState.ts +2 -2
  171. package/src/contexts/themeContext/utils/theme.ts +1 -0
  172. package/src/i18n/en.json +2 -0
  173. package/src/i18n/fr.json +2 -0
  174. package/src/i18n/hi.json +2 -0
  175. package/src/i18n/it.json +2 -0
  176. package/src/i18n/ja.json +3 -1
  177. package/src/i18n/ko.json +3 -1
  178. package/src/i18n/nl.json +2 -0
  179. package/src/i18n/ru.json +2 -0
  180. package/src/i18n/tr.json +2 -0
  181. package/src/icons/Warning.tsx +12 -0
  182. package/src/icons/index.ts +1 -0
  183. package/src/utils/utils.ts +53 -1
  184. package/src/version.json +1 -1
  185. package/src/components/MessageInput/__tests__/__snapshots__/FileUploadPreview.test.js.snap +0 -4413
  186. package/src/components/MessageInput/__tests__/__snapshots__/ImageUploadPreview.test.js.snap +0 -2373
@@ -41,6 +41,7 @@ import {
41
41
  ACITriggerSettings,
42
42
  ACITriggerSettingsParams,
43
43
  FileState,
44
+ FileStateValue,
44
45
  generateRandomId,
45
46
  TriggerSettings,
46
47
  urlRegex,
@@ -61,7 +62,7 @@ export type FileUpload = {
61
62
  uri?: string;
62
63
  };
63
64
  id: string;
64
- state: string;
65
+ state: FileStateValue;
65
66
  url?: string;
66
67
  };
67
68
 
@@ -70,7 +71,7 @@ export type ImageUpload = {
70
71
  name?: string;
71
72
  };
72
73
  id: string;
73
- state: string;
74
+ state: FileStateValue;
74
75
  height?: number;
75
76
  url?: string;
76
77
  width?: number;
@@ -414,7 +415,31 @@ export const MessageInputProvider = <
414
415
  }>) => {
415
416
  const { closePicker, openPicker, selectedPicker, setSelectedPicker } =
416
417
  useAttachmentPickerContext();
417
- const { client } = useChatContext<StreamChatGenerics>();
418
+ const { appSettings, client } = useChatContext<StreamChatGenerics>();
419
+
420
+ const getFileUploadConfig = () => {
421
+ const fileConfig = appSettings?.app?.file_upload_config;
422
+ if (fileConfig !== null || fileConfig !== undefined) {
423
+ return fileConfig;
424
+ } else {
425
+ return {};
426
+ }
427
+ };
428
+
429
+ const blockedFileExtensionTypes = getFileUploadConfig()?.blocked_file_extensions;
430
+ const blockedFileMimeTypes = getFileUploadConfig()?.blocked_mime_types;
431
+
432
+ const getImageUploadConfig = () => {
433
+ const imageConfig = appSettings?.app?.image_upload_config;
434
+ if (imageConfig !== null || imageConfig !== undefined) {
435
+ return imageConfig;
436
+ }
437
+ return {};
438
+ };
439
+
440
+ const blockedImageExtensionTypes = getImageUploadConfig()?.blocked_file_extensions;
441
+ const blockedImageMimeTypes = getImageUploadConfig()?.blocked_mime_types;
442
+
418
443
  const channelCapabities = useOwnCapabilitiesContext();
419
444
 
420
445
  const { channel, giphyEnabled } = useChannelContext<StreamChatGenerics>();
@@ -818,68 +843,75 @@ export const MessageInputProvider = <
818
843
  }
819
844
  };
820
845
 
846
+ const regExcondition = /File (extension \.\w{2,4}|type \S+) is not supported/;
847
+
848
+ const getUploadSetStateAction = <UploadType extends ImageUpload | FileUpload>(
849
+ id: string,
850
+ fileState: FileStateValue,
851
+ extraData: Partial<UploadType> = {},
852
+ ): React.SetStateAction<UploadType[]> => {
853
+ const uploads: (prevUploads: UploadType[]) => UploadType[] = (prevUploads: UploadType[]) =>
854
+ prevUploads.map((prevUpload) => {
855
+ if (prevUpload.id === id) {
856
+ return {
857
+ ...prevUpload,
858
+ ...extraData,
859
+ state: fileState,
860
+ };
861
+ }
862
+ return prevUpload;
863
+ });
864
+
865
+ return uploads;
866
+ };
867
+
868
+ const handleFileOrImageUploadError = (error: unknown, isImageError: boolean, id: string) => {
869
+ if (isImageError) {
870
+ setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
871
+ if (error instanceof Error) {
872
+ if (regExcondition.test(error.message)) {
873
+ return setImageUploads(getUploadSetStateAction(id, FileState.NOT_SUPPORTED));
874
+ }
875
+
876
+ return setImageUploads(getUploadSetStateAction(id, FileState.UPLOAD_FAILED));
877
+ }
878
+ } else {
879
+ setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
880
+
881
+ if (error instanceof Error) {
882
+ if (regExcondition.test(error.message)) {
883
+ return setFileUploads(getUploadSetStateAction(id, FileState.NOT_SUPPORTED));
884
+ }
885
+ return setFileUploads(getUploadSetStateAction(id, FileState.UPLOAD_FAILED));
886
+ }
887
+ }
888
+ };
889
+
821
890
  const uploadFile = async ({ newFile }: { newFile: FileUpload }) => {
822
891
  if (!newFile) {
823
892
  return;
824
893
  }
825
894
  const { file, id } = newFile;
826
895
 
827
- setFileUploads((prevFileUploads) =>
828
- prevFileUploads.map((fileUpload) => {
829
- if (fileUpload.id === id) {
830
- return {
831
- ...fileUpload,
832
- state: FileState.UPLOADING,
833
- };
834
- }
835
- return fileUpload;
836
- }),
837
- );
896
+ setFileUploads(getUploadSetStateAction(id, FileState.UPLOADING));
838
897
 
839
- let response = {} as SendFileAPIResponse;
898
+ let response: Partial<SendFileAPIResponse> = {};
840
899
  try {
841
900
  if (value.doDocUploadRequest) {
842
901
  response = await value.doDocUploadRequest(file, channel);
843
902
  } else if (channel && file.uri) {
844
903
  response = await channel.sendFile(file.uri, file.name, file.type);
845
904
  }
846
- } catch (error) {
847
- console.warn(error);
848
- if (!newFile) {
849
- setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
850
- } else {
851
- setFileUploads((prevFileUploads) =>
852
- prevFileUploads.map((fileUpload) => {
853
- if (fileUpload.id === id) {
854
- return {
855
- ...fileUpload,
856
- state: FileState.UPLOAD_FAILED,
857
- };
858
- }
859
- return fileUpload;
860
- }),
861
- );
862
- setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
863
- }
864
- return;
905
+ const extraData: Partial<FileUpload> = { url: response.file };
906
+ setFileUploads(getUploadSetStateAction(id, FileState.UPLOADED, extraData));
907
+ } catch (error: unknown) {
908
+ handleFileOrImageUploadError(error, false, id);
865
909
  }
866
-
867
- setFileUploads((prevFileUploads) =>
868
- prevFileUploads.map((fileUpload) => {
869
- if (fileUpload.id === id) {
870
- return {
871
- ...fileUpload,
872
- state: FileState.UPLOADED,
873
- url: response.file,
874
- };
875
- }
876
- return fileUpload;
877
- }),
878
- );
879
910
  };
880
911
 
881
912
  const uploadImage = async ({ newImage }: { newImage: ImageUpload }) => {
882
913
  const { file, id } = newImage || {};
914
+
883
915
  if (!file) {
884
916
  return;
885
917
  }
@@ -938,18 +970,7 @@ export const MessageInputProvider = <
938
970
  return prevAsyncUploads;
939
971
  });
940
972
  } else {
941
- setImageUploads((prevImageUploads) =>
942
- prevImageUploads.map((imageUpload) => {
943
- if (imageUpload.id === id) {
944
- return {
945
- ...imageUpload,
946
- state: FileState.UPLOADED,
947
- url: res.file,
948
- };
949
- }
950
- return imageUpload;
951
- }),
952
- );
973
+ setImageUploads(getUploadSetStateAction(id, FileState.UPLOADED, { url: res.file }));
953
974
  }
954
975
  });
955
976
  } else {
@@ -958,39 +979,16 @@ export const MessageInputProvider = <
958
979
  }
959
980
 
960
981
  if (Object.keys(response).length) {
961
- setImageUploads((prevImageUploads) =>
962
- prevImageUploads.map((imageUpload) => {
963
- if (imageUpload.id === id) {
964
- return {
965
- ...imageUpload,
966
- height: file.height,
967
- state: FileState.UPLOADED,
968
- url: response.file,
969
- width: file.width,
970
- };
971
- }
972
- return imageUpload;
982
+ setImageUploads(
983
+ getUploadSetStateAction(id, FileState.UPLOADED, {
984
+ height: file.height,
985
+ url: response.file,
986
+ width: file.width,
973
987
  }),
974
988
  );
975
989
  }
976
990
  } catch (error) {
977
- console.warn(error);
978
- if (newImage) {
979
- setImageUploads((prevImageUploads) =>
980
- prevImageUploads.map((imageUpload) => {
981
- if (imageUpload.id === id) {
982
- return {
983
- ...imageUpload,
984
- state: FileState.UPLOAD_FAILED,
985
- };
986
- }
987
- return imageUpload;
988
- }),
989
- );
990
- }
991
- setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads - 1);
992
-
993
- return;
991
+ handleFileOrImageUploadError(error, true, id);
994
992
  }
995
993
  };
996
994
 
@@ -1000,34 +998,67 @@ export const MessageInputProvider = <
1000
998
  type?: string;
1001
999
  uri?: string;
1002
1000
  }) => {
1003
- const id = generateRandomId();
1004
- const mimeType = lookup(file.name);
1005
- const newFile = {
1001
+ const id: string = generateRandomId();
1002
+ const mimeType: string | boolean = lookup(file.name);
1003
+
1004
+ const isBlockedFileExtension: boolean | undefined = blockedFileExtensionTypes?.some(
1005
+ (fileExtensionType: string) => file.name?.includes(fileExtensionType),
1006
+ );
1007
+ const isBlockedFileMimeType: boolean | undefined = blockedFileMimeTypes?.some(
1008
+ (mimeType: string) => file.name?.includes(mimeType),
1009
+ );
1010
+
1011
+ const fileState =
1012
+ isBlockedFileExtension || isBlockedFileMimeType
1013
+ ? FileState.NOT_SUPPORTED
1014
+ : FileState.UPLOADING;
1015
+
1016
+ const newFile: FileUpload = {
1006
1017
  file: { ...file, type: mimeType || file?.type },
1007
1018
  id,
1008
- state: FileState.UPLOADING,
1019
+ state: fileState,
1009
1020
  };
1021
+
1010
1022
  await Promise.all([
1011
1023
  setFileUploads((prevFileUploads) => prevFileUploads.concat([newFile])),
1012
1024
  setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
1013
1025
  ]);
1014
1026
 
1015
- uploadFile({ newFile });
1027
+ if (!isBlockedFileExtension) {
1028
+ uploadFile({ newFile });
1029
+ }
1016
1030
  };
1017
1031
 
1018
1032
  const uploadNewImage = async (image: Partial<Asset>) => {
1019
1033
  const id = generateRandomId();
1020
- const newImage = {
1034
+
1035
+ const isBlockedImageMimeType = blockedImageMimeTypes?.some((mimeType: string) =>
1036
+ image.uri?.includes(mimeType),
1037
+ );
1038
+
1039
+ const isBlockedImageExtension = blockedImageExtensionTypes?.some((imageExtensionType: string) =>
1040
+ image.uri?.includes(imageExtensionType),
1041
+ );
1042
+
1043
+ const imageState =
1044
+ isBlockedImageExtension || isBlockedImageMimeType
1045
+ ? FileState.NOT_SUPPORTED
1046
+ : FileState.UPLOADING;
1047
+
1048
+ const newImage: ImageUpload = {
1021
1049
  file: image,
1022
1050
  id,
1023
- state: FileState.UPLOADING,
1051
+ state: imageState,
1024
1052
  };
1053
+
1025
1054
  await Promise.all([
1026
1055
  setImageUploads((prevImageUploads) => prevImageUploads.concat([newImage])),
1027
1056
  setNumberOfUploads((prevNumberOfUploads) => prevNumberOfUploads + 1),
1028
1057
  ]);
1029
1058
 
1030
- uploadImage({ newImage });
1059
+ if (!isBlockedImageExtension) {
1060
+ uploadImage({ newImage });
1061
+ }
1031
1062
  };
1032
1063
 
1033
1064
  const messageInputContext = useCreateMessageInputContext({
@@ -44,8 +44,8 @@ export const useMessageDetailsForState = <
44
44
  useEffect(() => {
45
45
  if (message && !isEditingBoolean<StreamChatGenerics>(message)) {
46
46
  setText(message?.text || '');
47
- const newFileUploads = [];
48
- const newImageUploads = [];
47
+ const newFileUploads: FileUpload[] = [];
48
+ const newImageUploads: ImageUpload[] = [];
49
49
 
50
50
  const attachments = Array.isArray(message.attachments) ? message.attachments : [];
51
51
 
@@ -334,6 +334,7 @@ export type Theme = {
334
334
  unreadCountNotificationContainer: ViewStyle;
335
335
  unreadCountNotificationText: TextStyle;
336
336
  wrapper: ViewStyle;
337
+ chevronColor?: Color;
337
338
  };
338
339
  typingIndicatorContainer: ViewStyle;
339
340
  };
package/src/i18n/en.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "Error loading channel list...",
20
20
  "Error loading messages for this channel...": "Error loading messages for this channel...",
21
21
  "Error while loading, please reload/refresh": "Error while loading, please reload/refresh",
22
+ "File type not supported": "File type not supported",
22
23
  "Flag": "Flag",
23
24
  "Flag Message": "Flag Message",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "Flag action failed either due to a network issue or the message is already flagged.",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "Message deleted",
32
33
  "Message flagged": "Message flagged",
33
34
  "Mute User": "Mute User",
35
+ "Not supported": "Not supported",
34
36
  "Nothing yet...": "Nothing yet...",
35
37
  "Ok": "Ok",
36
38
  "Only visible to you": "Only visible to you",
package/src/i18n/fr.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "Erreur lors du chargement de la liste de canaux...",
20
20
  "Error loading messages for this channel...": "Erreur lors du chargement des messages de ce canal...",
21
21
  "Error while loading, please reload/refresh": "Erreur lors du chargement, veuillez recharger/rafraîchir",
22
+ "File type not supported": "Le type de fichier n'est pas pris en charge",
22
23
  "Flag": "Signaler",
23
24
  "Flag Message": "Signaler le message",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "L'action de signalisation a échoué en raison d'un problème de réseau ou le message est déjà signalé.",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "Message supprimé",
32
33
  "Message flagged": "Message signalé",
33
34
  "Mute User": "Utilisateur muet",
35
+ "Not supported": "Non pris en charge",
34
36
  "Nothing yet...": "Aucun message...",
35
37
  "Ok": "Ok",
36
38
  "Only visible to you": "Seulement visible par vous",
package/src/i18n/hi.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "चैनल सूची लोड करने में त्रुटि...",
20
20
  "Error loading messages for this channel...": "इस चैनल के लिए मेसेजेस लोड करने में त्रुटि हुई...",
21
21
  "Error while loading, please reload/refresh": "एरर, रिफ्रेश करे",
22
+ "File type not supported": "फ़ाइल प्रकार समर्थित नहीं है",
22
23
  "Flag": "झंडा",
23
24
  "Flag Message": "झंडा संदेश",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "फ़्लैग कार्रवाई या तो नेटवर्क समस्या के कारण विफल हो गई या संदेश पहले से फ़्लैग किया गया है।",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "मैसेज हटा दिया गया",
32
33
  "Message flagged": "संदेश को ध्वजांकित किया गया",
33
34
  "Mute User": "उपयोगकर्ता को म्यूट करें",
35
+ "Not supported": "समर्थित नहीं",
34
36
  "Nothing yet...": "कोई मैसेज नहीं है...",
35
37
  "Ok": "ठीक",
36
38
  "Only visible to you": "केवल आपको दिखाई दे रहा है",
package/src/i18n/it.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "Errore durante il caricamento della lista dei canali...",
20
20
  "Error loading messages for this channel...": "Errore durante il caricamento dei messaggi per questo canale...",
21
21
  "Error while loading, please reload/refresh": "Errore durante il caricamento, per favore ricarica la pagina",
22
+ "File type not supported": "Tipo di file non supportato",
22
23
  "Flag": "Contrassegna",
23
24
  "Flag Message": "Contrassegna Messaggio",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "L'azione di segnalazione non è riuscita a causa di un problema di rete o il messaggio è già segnalato.",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "Messaggio cancellato",
32
33
  "Message flagged": "Messaggio contrassegnato",
33
34
  "Mute User": "Utente Muto",
35
+ "Not supported": "non supportato",
34
36
  "Nothing yet...": "Ancora niente...",
35
37
  "Ok": "Ok",
36
38
  "Only visible to you": "Visibile solo a te",
package/src/i18n/ja.json CHANGED
@@ -63,5 +63,7 @@
63
63
  "Only visible to you": "あなただけに見える",
64
64
  "Reply": "返事",
65
65
  "Reply to Message": "メッセージに返信",
66
- "🏙 Attachment...": "🏙 アタッチメント..."
66
+ "🏙 Attachment...": "🏙 アタッチメント...",
67
+ "Not supported": "サポートしていません",
68
+ "File type not supported": "サポートされていないファイルです"
67
69
  }
package/src/i18n/ko.json CHANGED
@@ -63,5 +63,7 @@
63
63
  "Only visible to you": "당신만 볼 수 있습니다",
64
64
  "Reply": "답장",
65
65
  "Reply to Message": "메시지에 답장",
66
- "🏙 Attachment...": "🏙 부착..."
66
+ "🏙 Attachment...": "🏙 부착...",
67
+ "File type not supported": "지원하지 않는 파일입니다.",
68
+ "Not supported": "지원하지 않습니다"
67
69
  }
package/src/i18n/nl.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "Probleem bij het laden van de kanalen...",
20
20
  "Error loading messages for this channel...": "Probleem bij het laden van de berichten in dit kanaal...",
21
21
  "Error while loading, please reload/refresh": "Probleem bij het laden, probeer opnieuw",
22
+ "File type not supported": "Bestandstype niet ondersteund",
22
23
  "Flag": "Markeer",
23
24
  "Flag Message": "Markeer bericht",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "Rapporteren mislukt door een netwerk fout of het berich is al gerapporteerd",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "Bericht verwijderd",
32
33
  "Message flagged": "Bericht gemarkeerd",
33
34
  "Mute User": "Gebruiker dempen",
35
+ "Not supported": "niet ondersteund",
34
36
  "Nothing yet...": "Nog niets...",
35
37
  "Ok": "Oké",
36
38
  "Only visible to you": "Alleen zichtbaar voor jou",
package/src/i18n/ru.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "Ошибка загрузки списка каналов...",
20
20
  "Error loading messages for this channel...": "Ошибка загрузки сообщений для этого канала...",
21
21
  "Error while loading, please reload/refresh": "Ошибка загрузки, пожалуйста перезагрузите или обновите",
22
+ "File type not supported": "Тип файла не поддерживается",
22
23
  "Flag": "Пометить",
23
24
  "Flag Message": "Пометить сообщение",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "Не удалось отправить жалобу. Возможные причины: проблема с подключением к интернету или ваша жалоба уже была принята.",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "Сообщение удалено",
32
33
  "Message flagged": "Сообщение отмечено",
33
34
  "Mute User": "Отключить пользователя",
35
+ "Not supported": "не поддерживается",
34
36
  "Nothing yet...": "Пока ничего нет...",
35
37
  "Ok": "Oк",
36
38
  "Only visible to you": "Видно только вам",
package/src/i18n/tr.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "Error loading channel list...": "Kanal listesi yüklenirken hata oluştu...",
20
20
  "Error loading messages for this channel...": "Bu kanal için mesajlar yüklenirken hata oluştu...",
21
21
  "Error while loading, please reload/refresh": "Yüklenirken hata oluştu, lütfen tekrar deneyin",
22
+ "File type not supported": "Dosya türü desteklenmiyor",
22
23
  "Flag": "Raporla",
23
24
  "Flag Message": "Mesajı İşaretle",
24
25
  "Flag action failed either due to a network issue or the message is already flagged": "Raporlama, mesajın raporlanmış olması veya bağlantı hatası sebebiyle başarısız oldu.",
@@ -31,6 +32,7 @@
31
32
  "Message deleted": "Mesaj silindi",
32
33
  "Message flagged": "Mesaj işaretlendi",
33
34
  "Mute User": "Kullanıcının Sesini Kapat",
35
+ "Not supported": "Desteklenmiyor",
34
36
  "Nothing yet...": "Şimdilik hiçbir şey...",
35
37
  "Ok": "Tamam",
36
38
  "Only visible to you": "Sadece siz görebilirsiniz",
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+
3
+ import { IconProps, RootPath, RootSvg } from './utils/base';
4
+
5
+ export const Warning: React.FC<IconProps> = (props) => (
6
+ <RootSvg {...props}>
7
+ <RootPath
8
+ d='M8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0ZM7 11V13H9V11H7ZM7 9V3H9V9H7Z'
9
+ {...props}
10
+ />
11
+ </RootSvg>
12
+ );
@@ -74,6 +74,7 @@ export * from './User';
74
74
  export * from './UserAdd';
75
75
  export * from './UserDelete';
76
76
  export * from './UserMinus';
77
+ export * from './Warning';
77
78
  export * from './WutReaction';
78
79
  export * from './XLS';
79
80
  export * from './XLSX';
@@ -8,6 +8,7 @@ import type {
8
8
  ChannelMemberAPIResponse,
9
9
  ChannelMemberResponse,
10
10
  CommandResponse,
11
+ FormatMessageResponse,
11
12
  StreamChat,
12
13
  UserResponse,
13
14
  } from 'stream-chat';
@@ -32,7 +33,7 @@ export const FileState = Object.freeze({
32
33
  // while later is set on backend side
33
34
  // TODO: Unify both of them
34
35
  FINISHED: 'finished',
35
- NO_FILE: 'no_file',
36
+ NOT_SUPPORTED: 'not_supported',
36
37
  UPLOAD_FAILED: 'upload_failed',
37
38
  UPLOADED: 'uploaded',
38
39
  UPLOADING: 'uploading',
@@ -40,9 +41,13 @@ export const FileState = Object.freeze({
40
41
 
41
42
  export const ProgressIndicatorTypes: {
42
43
  IN_PROGRESS: 'in_progress';
44
+ INACTIVE: 'inactive';
45
+ NOT_SUPPORTED: 'not_supported';
43
46
  RETRY: 'retry';
44
47
  } = Object.freeze({
45
48
  IN_PROGRESS: 'in_progress',
49
+ INACTIVE: 'inactive',
50
+ NOT_SUPPORTED: 'not_supported',
46
51
  RETRY: 'retry',
47
52
  });
48
53
 
@@ -52,6 +57,24 @@ export const MessageStatusTypes = {
52
57
  SENDING: 'sending',
53
58
  };
54
59
 
60
+ export type FileStateValue = typeof FileState[keyof typeof FileState];
61
+
62
+ type ValueOf<T> = T[keyof T];
63
+ type Progress = ValueOf<typeof ProgressIndicatorTypes>;
64
+ type IndicatorStatesMap = Record<ValueOf<typeof FileState>, Progress | null>;
65
+
66
+ export const getIndicatorTypeForFileState = (fileState: FileStateValue): Progress | null => {
67
+ const indicatorMap: IndicatorStatesMap = {
68
+ [FileState.UPLOADING]: ProgressIndicatorTypes.IN_PROGRESS,
69
+ [FileState.UPLOAD_FAILED]: ProgressIndicatorTypes.RETRY,
70
+ [FileState.NOT_SUPPORTED]: ProgressIndicatorTypes.NOT_SUPPORTED,
71
+ [FileState.UPLOADED]: ProgressIndicatorTypes.INACTIVE,
72
+ [FileState.FINISHED]: ProgressIndicatorTypes.INACTIVE,
73
+ };
74
+
75
+ return indicatorMap[fileState];
76
+ };
77
+
55
78
  const defaultAutoCompleteSuggestionsLimit = 10;
56
79
  const defaultMentionAllAppUsersQuery = {
57
80
  filters: {},
@@ -512,3 +535,32 @@ export const emojiRegex =
512
535
 
513
536
  export const urlRegex =
514
537
  /(?:\s|^)((?:https?:\/\/)?(?:[a-z0-9-]+(?:\.[a-z0-9-]+)+)(?::[0-9]+)?(?:\/(?:[^\s]+)?)?)/g;
538
+
539
+ /**
540
+ * Stringifies a message object
541
+ * @param {FormatMessageResponse<StreamChatGenerics>} message - the message object to be stringified
542
+ * @returns {string} The stringified message
543
+ */
544
+ const stringifyMessage = <
545
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
546
+ >({
547
+ deleted_at,
548
+ latest_reactions,
549
+ reply_count,
550
+ status,
551
+ updated_at,
552
+ }: FormatMessageResponse<StreamChatGenerics>): string =>
553
+ `${deleted_at}${
554
+ latest_reactions ? latest_reactions.map(({ type }) => type).join() : ''
555
+ }${reply_count}${status}${updated_at?.toISOString?.() || updated_at}`;
556
+
557
+ /**
558
+ * Reduces a list of messages to strings that are used in useEffect & useMemo
559
+ * @param {messages} messages - the array of messages to be compared
560
+ * @returns {string} The mapped message string
561
+ */
562
+ export const reduceMessagesToString = <
563
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
564
+ >(
565
+ messages: FormatMessageResponse<StreamChatGenerics>[],
566
+ ): string => messages.map(stringifyMessage).join();
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "4.3.1"
2
+ "version": "4.4.0-beta.3"
3
3
  }