stream-chat-react-native-core 4.5.1-beta.1 → 4.6.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 (83) hide show
  1. package/lib/commonjs/components/Attachment/FileIcon.js +9 -1
  2. package/lib/commonjs/components/Attachment/FileIcon.js.map +1 -1
  3. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +208 -31
  4. package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  5. package/lib/commonjs/components/Message/MessageSimple/MessageContent.js +39 -21
  6. package/lib/commonjs/components/Message/MessageSimple/MessageContent.js.map +1 -1
  7. package/lib/commonjs/components/MessageInput/FileUploadPreview.js +1 -1
  8. package/lib/commonjs/components/MessageInput/FileUploadPreview.js.map +1 -1
  9. package/lib/commonjs/components/MessageInput/MessageInput.js +129 -44
  10. package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
  11. package/lib/commonjs/components/Reply/Reply.js +25 -9
  12. package/lib/commonjs/components/Reply/Reply.js.map +1 -1
  13. package/lib/commonjs/contexts/attachmentPickerContext/AttachmentPickerContext.js +15 -8
  14. package/lib/commonjs/contexts/attachmentPickerContext/AttachmentPickerContext.js.map +1 -1
  15. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +10 -7
  16. package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  17. package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js +16 -1
  18. package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
  19. package/lib/commonjs/contexts/themeContext/utils/theme.js +1 -0
  20. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  21. package/lib/commonjs/icons/Recorder.js +47 -0
  22. package/lib/commonjs/icons/Recorder.js.map +1 -0
  23. package/lib/commonjs/icons/Video.js +82 -0
  24. package/lib/commonjs/icons/Video.js.map +1 -0
  25. package/lib/commonjs/icons/index.js +26 -0
  26. package/lib/commonjs/icons/index.js.map +1 -1
  27. package/lib/commonjs/native.js.map +1 -1
  28. package/lib/commonjs/version.json +1 -1
  29. package/lib/module/components/Attachment/FileIcon.js +9 -1
  30. package/lib/module/components/Attachment/FileIcon.js.map +1 -1
  31. package/lib/module/components/AttachmentPicker/AttachmentPicker.js +208 -31
  32. package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
  33. package/lib/module/components/Message/MessageSimple/MessageContent.js +39 -21
  34. package/lib/module/components/Message/MessageSimple/MessageContent.js.map +1 -1
  35. package/lib/module/components/MessageInput/FileUploadPreview.js +1 -1
  36. package/lib/module/components/MessageInput/FileUploadPreview.js.map +1 -1
  37. package/lib/module/components/MessageInput/MessageInput.js +129 -44
  38. package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
  39. package/lib/module/components/Reply/Reply.js +25 -9
  40. package/lib/module/components/Reply/Reply.js.map +1 -1
  41. package/lib/module/contexts/attachmentPickerContext/AttachmentPickerContext.js +15 -8
  42. package/lib/module/contexts/attachmentPickerContext/AttachmentPickerContext.js.map +1 -1
  43. package/lib/module/contexts/messageInputContext/MessageInputContext.js +10 -7
  44. package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
  45. package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js +16 -1
  46. package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
  47. package/lib/module/contexts/themeContext/utils/theme.js +1 -0
  48. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  49. package/lib/module/icons/Recorder.js +47 -0
  50. package/lib/module/icons/Recorder.js.map +1 -0
  51. package/lib/module/icons/Video.js +82 -0
  52. package/lib/module/icons/Video.js.map +1 -0
  53. package/lib/module/icons/index.js +26 -0
  54. package/lib/module/icons/index.js.map +1 -1
  55. package/lib/module/native.js.map +1 -1
  56. package/lib/module/version.json +1 -1
  57. package/lib/typescript/components/MessageInput/MessageInput.d.ts +1 -1
  58. package/lib/typescript/contexts/attachmentPickerContext/AttachmentPickerContext.d.ts +3 -2
  59. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +4 -15
  60. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +1 -0
  61. package/lib/typescript/icons/Recorder.d.ts +3 -0
  62. package/lib/typescript/icons/Video.d.ts +3 -0
  63. package/lib/typescript/icons/index.d.ts +2 -0
  64. package/lib/typescript/native.d.ts +3 -14
  65. package/lib/typescript/types/types.d.ts +24 -0
  66. package/package.json +1 -1
  67. package/src/components/Attachment/FileIcon.tsx +45 -0
  68. package/src/components/AttachmentPicker/AttachmentPicker.tsx +172 -22
  69. package/src/components/Message/MessageSimple/MessageContent.tsx +23 -12
  70. package/src/components/MessageInput/FileUploadPreview.tsx +1 -1
  71. package/src/components/MessageInput/MessageInput.tsx +106 -19
  72. package/src/components/Reply/Reply.tsx +31 -14
  73. package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +12 -0
  74. package/src/contexts/attachmentPickerContext/AttachmentPickerContext.tsx +6 -2
  75. package/src/contexts/messageInputContext/MessageInputContext.tsx +17 -24
  76. package/src/contexts/messageInputContext/hooks/useMessageDetailsForState.ts +17 -1
  77. package/src/contexts/themeContext/utils/theme.ts +2 -0
  78. package/src/icons/Recorder.tsx +16 -0
  79. package/src/icons/Video.tsx +37 -0
  80. package/src/icons/index.ts +2 -0
  81. package/src/native.ts +4 -14
  82. package/src/types/types.ts +27 -0
  83. package/src/version.json +1 -1
@@ -30,8 +30,7 @@ import {
30
30
  useTranslationContext,
31
31
  } from '../../contexts/translationContext/TranslationContext';
32
32
 
33
- import type { Asset } from '../../native';
34
- import type { DefaultStreamChatGenerics } from '../../types/types';
33
+ import type { Asset, DefaultStreamChatGenerics } from '../../types/types';
35
34
  import { AttachmentSelectionBar } from '../AttachmentPicker/components/AttachmentSelectionBar';
36
35
  import { AutoCompleteInput } from '../AutoCompleteInput/AutoCompleteInput';
37
36
 
@@ -115,7 +114,9 @@ type MessageInputPropsWithContext<
115
114
  | 'setGiphyActive'
116
115
  | 'showMoreOptions'
117
116
  | 'ShowThreadMessageInChannelButton'
117
+ | 'removeFile'
118
118
  | 'removeImage'
119
+ | 'uploadNewFile'
119
120
  | 'uploadNewImage'
120
121
  > &
121
122
  Pick<MessagesContextValue<StreamChatGenerics>, 'Reply'> &
@@ -164,6 +165,7 @@ const MessageInputWithContext = <
164
165
  mentionedUsers,
165
166
  numberOfUploads,
166
167
  quotedMessage,
168
+ removeFile,
167
169
  removeImage,
168
170
  Reply,
169
171
  resetInput,
@@ -175,6 +177,7 @@ const MessageInputWithContext = <
175
177
  thread,
176
178
  threadList,
177
179
  triggerType,
180
+ uploadNewFile,
178
181
  uploadNewImage,
179
182
  watchers,
180
183
  } = props;
@@ -202,9 +205,11 @@ const MessageInputWithContext = <
202
205
  attachmentPickerBottomSheetHeight,
203
206
  attachmentSelectionBarHeight,
204
207
  bottomInset,
208
+ selectedFiles,
205
209
  selectedImages,
206
210
  selectedPicker,
207
211
  setMaxNumberOfFiles,
212
+ setSelectedFiles,
208
213
  setSelectedImages,
209
214
  } = useAttachmentPickerContext();
210
215
 
@@ -224,8 +229,11 @@ const MessageInputWithContext = <
224
229
  }, []);
225
230
 
226
231
  const [hasResetImages, setHasResetImages] = useState(false);
232
+ const [hasResetFiles, setHasResetFiles] = useState(false);
227
233
  const selectedImagesLength = hasResetImages ? selectedImages.length : 0;
228
234
  const imageUploadsLength = hasResetImages ? imageUploads.length : 0;
235
+ const selectedFilesLength = hasResetFiles ? selectedFiles.length : 0;
236
+ const fileUploadsLength = hasResetFiles ? fileUploads.length : 0;
229
237
  const imagesForInput = (!!thread && !!threadList) || (!thread && !threadList);
230
238
 
231
239
  useEffect(() => {
@@ -236,44 +244,90 @@ const MessageInputWithContext = <
236
244
  return () => setSelectedImages([]);
237
245
  }, []);
238
246
 
247
+ useEffect(() => {
248
+ setSelectedFiles([]);
249
+ if (fileUploads.length) {
250
+ fileUploads.forEach((file) => removeFile(file.id));
251
+ }
252
+ return () => setSelectedFiles([]);
253
+ }, []);
254
+
239
255
  useEffect(() => {
240
256
  if (hasResetImages === false && imageUploadsLength === 0 && selectedImagesLength === 0) {
241
257
  setHasResetImages(true);
242
258
  }
243
259
  }, [imageUploadsLength, selectedImagesLength]);
244
260
 
261
+ useEffect(() => {
262
+ if (hasResetFiles === false && fileUploadsLength === 0 && selectedFilesLength === 0) {
263
+ setHasResetFiles(true);
264
+ }
265
+ }, [fileUploadsLength, selectedFilesLength]);
266
+
245
267
  useEffect(() => {
246
268
  if (imagesForInput === false && imageUploads.length) {
247
269
  imageUploads.forEach((image) => removeImage(image.id));
248
270
  }
249
271
  }, [imagesForInput]);
250
272
 
273
+ const uploadImagesHandler = () => {
274
+ const imagesToUpload = selectedImages.filter((selectedImage) => {
275
+ const uploadedImage = imageUploads.find(
276
+ (imageUpload) =>
277
+ imageUpload.file.uri === selectedImage.uri || imageUpload.url === selectedImage.uri,
278
+ );
279
+ return !uploadedImage;
280
+ });
281
+ imagesToUpload.forEach((image) => uploadNewImage(image));
282
+ };
283
+
284
+ const removeImagesHandler = () => {
285
+ const imagesToRemove = imageUploads.filter(
286
+ (imageUpload) =>
287
+ !selectedImages.find(
288
+ (selectedImage) =>
289
+ selectedImage.uri === imageUpload.file.uri || selectedImage.uri === imageUpload.url,
290
+ ),
291
+ );
292
+ imagesToRemove.forEach((image) => removeImage(image.id));
293
+ };
294
+
251
295
  useEffect(() => {
252
296
  if (imagesForInput) {
253
297
  if (selectedImagesLength > imageUploadsLength) {
254
298
  /** User selected an image in bottom sheet attachment picker */
255
- const imagesToUpload = selectedImages.filter((selectedImage) => {
256
- const uploadedImage = imageUploads.find(
257
- (imageUpload) =>
258
- imageUpload.file.uri === selectedImage.uri || imageUpload.url === selectedImage.uri,
259
- );
260
- return !uploadedImage;
261
- });
262
- imagesToUpload.forEach((image) => uploadNewImage(image));
263
- } else if (selectedImagesLength < imageUploadsLength) {
299
+ uploadImagesHandler();
300
+ } else {
264
301
  /** User de-selected an image in bottom sheet attachment picker */
265
- const imagesToRemove = imageUploads.filter(
266
- (imageUpload) =>
267
- !selectedImages.find(
268
- (selectedImage) =>
269
- selectedImage.uri === imageUpload.file.uri || selectedImage.uri === imageUpload.url,
270
- ),
271
- );
272
- imagesToRemove.forEach((image) => removeImage(image.id));
302
+ removeImagesHandler();
273
303
  }
274
304
  }
275
305
  }, [selectedImagesLength]);
276
306
 
307
+ useEffect(() => {
308
+ if (selectedFilesLength > fileUploadsLength) {
309
+ /** User selected a video in bottom sheet attachment picker */
310
+ const filesToUpload = selectedFiles.filter((selectedFile) => {
311
+ const uploadedFile = fileUploads.find(
312
+ (fileUpload) =>
313
+ fileUpload.file.uri === selectedFile.uri || fileUpload.url === selectedFile.uri,
314
+ );
315
+ return !uploadedFile;
316
+ });
317
+ filesToUpload.forEach((file) => uploadNewFile(file));
318
+ } else {
319
+ /** User de-selected a video in bottom sheet attachment picker */
320
+ const filesToRemove = fileUploads.filter(
321
+ (fileUpload) =>
322
+ !selectedFiles.find(
323
+ (selectedFile) =>
324
+ selectedFile.uri === fileUpload.file.uri || selectedFile.uri === fileUpload.url,
325
+ ),
326
+ );
327
+ filesToRemove.forEach((file) => removeFile(file.id));
328
+ }
329
+ }, [selectedFilesLength]);
330
+
277
331
  useEffect(() => {
278
332
  if (imagesForInput) {
279
333
  if (imageUploadsLength < selectedImagesLength) {
@@ -306,6 +360,35 @@ const MessageInputWithContext = <
306
360
  }
307
361
  }, [imageUploadsLength]);
308
362
 
363
+ useEffect(() => {
364
+ if (fileUploadsLength < selectedFilesLength) {
365
+ /** User removed some video from seleted files within ImageUploadPreview. */
366
+ const updatedSelectedFiles = selectedFiles.filter((selectedFile) => {
367
+ const uploadedFile = fileUploads.find(
368
+ (fileUpload) =>
369
+ fileUpload.file.uri === selectedFile.uri || fileUpload.url === selectedFile.uri,
370
+ );
371
+ return uploadedFile;
372
+ });
373
+ setSelectedFiles(updatedSelectedFiles);
374
+ } else if (fileUploadsLength > selectedFilesLength) {
375
+ /**
376
+ * User is editing some message which contains video attachments OR
377
+ * video attachment is added from custom image picker (other than the default bottomsheet image picker)
378
+ * using `uploadNewFile` function from `MessageInputContext`.
379
+ **/
380
+ setSelectedFiles(
381
+ fileUploads.map((fileUpload) => ({
382
+ duration: fileUpload.file.duration,
383
+ name: fileUpload.file.name,
384
+ size: fileUpload.file.size,
385
+ type: fileUpload.file.type,
386
+ uri: fileUpload.file.uri,
387
+ })),
388
+ );
389
+ }
390
+ }, [fileUploadsLength]);
391
+
309
392
  const editingExists = !!editing;
310
393
  useEffect(() => {
311
394
  if (editing && inputBoxRef.current) {
@@ -666,6 +749,7 @@ export const MessageInput = <
666
749
  mentionedUsers,
667
750
  numberOfUploads,
668
751
  quotedMessage,
752
+ removeFile,
669
753
  removeImage,
670
754
  resetInput,
671
755
  SendButton,
@@ -676,6 +760,7 @@ export const MessageInput = <
676
760
  setShowMoreOptions,
677
761
  showMoreOptions,
678
762
  ShowThreadMessageInChannelButton,
763
+ uploadNewFile,
679
764
  uploadNewImage,
680
765
  } = useMessageInputContext<StreamChatGenerics>();
681
766
 
@@ -730,6 +815,7 @@ export const MessageInput = <
730
815
  mentionedUsers,
731
816
  numberOfUploads,
732
817
  quotedMessage,
818
+ removeFile,
733
819
  removeImage,
734
820
  Reply,
735
821
  resetInput,
@@ -744,6 +830,7 @@ export const MessageInput = <
744
830
  t,
745
831
  thread,
746
832
  triggerType,
833
+ uploadNewFile,
747
834
  uploadNewImage,
748
835
  watchers,
749
836
  }}
@@ -69,6 +69,36 @@ type ReplyPropsWithContext<
69
69
  }>;
70
70
  };
71
71
 
72
+ const getMessageType = <
73
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
74
+ >(
75
+ lastAttachment: Attachment<StreamChatGenerics>,
76
+ ) => {
77
+ let messageType;
78
+
79
+ const isLastAttachmentFile =
80
+ lastAttachment.type === 'file' ||
81
+ lastAttachment.type === 'audio' ||
82
+ lastAttachment.type === 'video';
83
+
84
+ const isLastAttachmentGiphy = lastAttachment.type === 'giphy' || lastAttachment.type === 'imgur';
85
+
86
+ const isLastAttachmentImageOrGiphy =
87
+ lastAttachment.type === 'image' && !lastAttachment.title_link && !lastAttachment.og_scrape_url;
88
+
89
+ const isLastAttachmentImage = lastAttachment.image_url || lastAttachment.thumb_url;
90
+
91
+ if (isLastAttachmentFile) {
92
+ messageType = 'file';
93
+ } else if (isLastAttachmentImageOrGiphy) {
94
+ if (isLastAttachmentImage) messageType = 'image';
95
+ else messageType = undefined;
96
+ } else if (isLastAttachmentGiphy) messageType = 'giphy';
97
+ else messageType = 'other';
98
+
99
+ return messageType;
100
+ };
101
+
72
102
  const ReplyWithContext = <
73
103
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
74
104
  >(
@@ -105,20 +135,7 @@ const ReplyWithContext = <
105
135
  if (typeof quotedMessage === 'boolean') return null;
106
136
 
107
137
  const lastAttachment = quotedMessage.attachments?.slice(-1)[0] as Attachment<StreamChatGenerics>;
108
-
109
- const messageType = lastAttachment
110
- ? lastAttachment.type === 'file' || lastAttachment.type === 'audio'
111
- ? 'file'
112
- : lastAttachment.type === 'image' &&
113
- !lastAttachment.title_link &&
114
- !lastAttachment.og_scrape_url
115
- ? lastAttachment.image_url || lastAttachment.thumb_url
116
- ? 'image'
117
- : undefined
118
- : lastAttachment.type === 'giphy' || lastAttachment.type === 'imgur'
119
- ? 'giphy'
120
- : 'other'
121
- : undefined;
138
+ const messageType = lastAttachment && getMessageType(lastAttachment);
122
139
 
123
140
  const hasImage =
124
141
  !error &&
@@ -369,6 +369,9 @@ exports[`Thread should match thread snapshot 1`] = `
369
369
  "borderBottomLeftRadius": 0,
370
370
  "borderBottomRightRadius": 16,
371
371
  "borderColor": "#ECEBEB",
372
+ "borderRadius": undefined,
373
+ "borderTopLeftRadius": 16,
374
+ "borderTopRightRadius": 16,
372
375
  },
373
376
  Object {},
374
377
  Object {},
@@ -617,6 +620,9 @@ exports[`Thread should match thread snapshot 1`] = `
617
620
  "borderBottomLeftRadius": 0,
618
621
  "borderBottomRightRadius": 16,
619
622
  "borderColor": "#ECEBEB",
623
+ "borderRadius": undefined,
624
+ "borderTopLeftRadius": 16,
625
+ "borderTopRightRadius": 16,
620
626
  },
621
627
  Object {},
622
628
  Object {},
@@ -865,6 +871,9 @@ exports[`Thread should match thread snapshot 1`] = `
865
871
  "borderBottomLeftRadius": 0,
866
872
  "borderBottomRightRadius": 16,
867
873
  "borderColor": "#ECEBEB",
874
+ "borderRadius": undefined,
875
+ "borderTopLeftRadius": 16,
876
+ "borderTopRightRadius": 16,
868
877
  },
869
878
  Object {},
870
879
  Object {},
@@ -1161,6 +1170,9 @@ exports[`Thread should match thread snapshot 1`] = `
1161
1170
  "borderBottomLeftRadius": 0,
1162
1171
  "borderBottomRightRadius": 16,
1163
1172
  "borderColor": "#ECEBEB",
1173
+ "borderRadius": undefined,
1174
+ "borderTopLeftRadius": 16,
1175
+ "borderTopRightRadius": 16,
1164
1176
  },
1165
1177
  Object {},
1166
1178
  Object {},
@@ -1,7 +1,6 @@
1
1
  import React, { PropsWithChildren, useContext, useEffect, useState } from 'react';
2
2
 
3
- import type { Asset } from '../../native';
4
- import type { DefaultStreamChatGenerics } from '../../types/types';
3
+ import type { Asset, DefaultStreamChatGenerics, File } from '../../types/types';
5
4
  import { getDisplayName } from '../utils/getDisplayName';
6
5
 
7
6
  export type AttachmentPickerIconProps = {
@@ -42,9 +41,11 @@ export type AttachmentPickerContextValue = {
42
41
  */
43
42
  maxNumberOfFiles: number;
44
43
  openPicker: () => void;
44
+ selectedFiles: File[];
45
45
  selectedImages: Asset[];
46
46
  setBottomInset: React.Dispatch<React.SetStateAction<number>>;
47
47
  setMaxNumberOfFiles: React.Dispatch<React.SetStateAction<number>>;
48
+ setSelectedFiles: React.Dispatch<React.SetStateAction<File[]>>;
48
49
  setSelectedImages: React.Dispatch<React.SetStateAction<Asset[]>>;
49
50
  setSelectedPicker: React.Dispatch<React.SetStateAction<'images' | undefined>>;
50
51
  setTopInset: React.Dispatch<React.SetStateAction<number>>;
@@ -80,6 +81,7 @@ export const AttachmentPickerProvider = ({
80
81
  const [bottomInset, setBottomInset] = useState<number>(bottomInsetValue ?? 0);
81
82
  const [maxNumberOfFiles, setMaxNumberOfFiles] = useState(10);
82
83
  const [selectedImages, setSelectedImages] = useState<Asset[]>([]);
84
+ const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
83
85
  const [selectedPicker, setSelectedPicker] = useState<'images'>();
84
86
  const [topInset, setTopInset] = useState<number>(value?.topInset ?? 0);
85
87
 
@@ -93,10 +95,12 @@ export const AttachmentPickerProvider = ({
93
95
 
94
96
  const combinedValue = {
95
97
  maxNumberOfFiles,
98
+ selectedFiles,
96
99
  selectedImages,
97
100
  selectedPicker,
98
101
  setBottomInset,
99
102
  setMaxNumberOfFiles,
103
+ setSelectedFiles,
100
104
  setSelectedImages,
101
105
  setSelectedPicker,
102
106
  setTopInset,
@@ -35,8 +35,8 @@ import type { MoreOptionsButtonProps } from '../../components/MessageInput/MoreO
35
35
  import type { SendButtonProps } from '../../components/MessageInput/SendButton';
36
36
  import type { UploadProgressIndicatorProps } from '../../components/MessageInput/UploadProgressIndicator';
37
37
  import type { MessageType } from '../../components/MessageList/hooks/useMessageList';
38
- import { Asset, compressImage, getLocalAssetUri, pickDocument } from '../../native';
39
- import type { DefaultStreamChatGenerics, UnknownType } from '../../types/types';
38
+ import { compressImage, getLocalAssetUri, pickDocument } from '../../native';
39
+ import type { Asset, DefaultStreamChatGenerics, File, UnknownType } from '../../types/types';
40
40
  import {
41
41
  ACITriggerSettings,
42
42
  ACITriggerSettingsParams,
@@ -55,12 +55,7 @@ import { useTranslationContext } from '../translationContext/TranslationContext'
55
55
  import { getDisplayName } from '../utils/getDisplayName';
56
56
 
57
57
  export type FileUpload = {
58
- file: {
59
- name: string;
60
- size?: number | string;
61
- type?: string;
62
- uri?: string;
63
- };
58
+ file: File;
64
59
  id: string;
65
60
  state: FileStateValue;
66
61
  url?: string;
@@ -207,13 +202,8 @@ export type LocalMessageInputContext<
207
202
  uploadFile: ({ newFile }: { newFile: FileUpload }) => Promise<void>;
208
203
  /** Function for attempting to upload an image */
209
204
  uploadImage: ({ newImage }: { newImage: ImageUpload }) => Promise<void>;
210
- uploadNewFile: (file: {
211
- name: string;
212
- size?: number | string;
213
- type?: string;
214
- uri?: string;
215
- }) => Promise<void>;
216
- uploadNewImage: (image: Partial<Asset>) => Promise<void>;
205
+ uploadNewFile: (file: File) => Promise<void>;
206
+ uploadNewImage: (image: Asset) => Promise<void>;
217
207
  };
218
208
 
219
209
  export type InputMessageInputContextValue<
@@ -699,6 +689,7 @@ export const MessageInputProvider = <
699
689
  } else if (file.file.type?.startsWith('video/')) {
700
690
  attachments.push({
701
691
  asset_url: file.url,
692
+ duration: file.file.duration,
702
693
  file_size: file.file.size,
703
694
  mime_type: file.file.type,
704
695
  title: file.file.name,
@@ -970,7 +961,10 @@ export const MessageInputProvider = <
970
961
  return prevAsyncUploads;
971
962
  });
972
963
  } else {
973
- setImageUploads(getUploadSetStateAction(id, FileState.UPLOADED, { url: res.file }));
964
+ const newImageUploads = getUploadSetStateAction<ImageUpload>(id, FileState.UPLOADED, {
965
+ url: res.file,
966
+ });
967
+ setImageUploads(newImageUploads);
974
968
  }
975
969
  });
976
970
  } else {
@@ -979,13 +973,12 @@ export const MessageInputProvider = <
979
973
  }
980
974
 
981
975
  if (Object.keys(response).length) {
982
- setImageUploads(
983
- getUploadSetStateAction(id, FileState.UPLOADED, {
984
- height: file.height,
985
- url: response.file,
986
- width: file.width,
987
- }),
988
- );
976
+ const newImageUploads = getUploadSetStateAction<ImageUpload>(id, FileState.UPLOADED, {
977
+ height: file.height,
978
+ url: response.file,
979
+ width: file.width,
980
+ });
981
+ setImageUploads(newImageUploads);
989
982
  }
990
983
  } catch (error) {
991
984
  handleFileOrImageUploadError(error, true, id);
@@ -1029,7 +1022,7 @@ export const MessageInputProvider = <
1029
1022
  }
1030
1023
  };
1031
1024
 
1032
- const uploadNewImage = async (image: Partial<Asset>) => {
1025
+ const uploadNewImage = async (image: Asset) => {
1033
1026
  const id = generateRandomId();
1034
1027
 
1035
1028
  const isBlockedImageMimeType = blockedImageMimeTypes?.some((mimeType: string) =>
@@ -65,11 +65,27 @@ export const useMessageDetailsForState = <
65
65
  } else if (attachment.type === 'image') {
66
66
  const id = generateRandomId();
67
67
  newImageUploads.push({
68
- file: { name: attachment.fallback },
68
+ file: {
69
+ name: attachment.fallback,
70
+ size: attachment.file_size,
71
+ type: attachment.type,
72
+ },
69
73
  id,
70
74
  state: 'finished',
71
75
  url: attachment.image_url || attachment.asset_url || attachment.thumb_url,
72
76
  });
77
+ } else if (attachment.type === 'video') {
78
+ const id = generateRandomId();
79
+ newFileUploads.push({
80
+ file: {
81
+ name: attachment.title || '',
82
+ size: attachment.file_size,
83
+ type: attachment.mime_type,
84
+ },
85
+ id,
86
+ state: 'finished',
87
+ url: attachment.asset_url,
88
+ });
73
89
  }
74
90
  }
75
91
  if (newFileUploads.length) {
@@ -80,6 +80,7 @@ export type MarkdownStyle = Partial<{
80
80
  export type Theme = {
81
81
  attachmentPicker: {
82
82
  bottomSheetContentContainer: ViewStyle;
83
+ durationText: TextStyle;
83
84
  errorButtonText: TextStyle;
84
85
  errorContainer: ViewStyle;
85
86
  errorText: TextStyle;
@@ -530,6 +531,7 @@ export type Theme = {
530
531
  export const defaultTheme: Theme = {
531
532
  attachmentPicker: {
532
533
  bottomSheetContentContainer: {},
534
+ durationText: {},
533
535
  errorButtonText: {},
534
536
  errorContainer: {},
535
537
  errorText: {},
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+
3
+ import { IconProps, RootPath, RootSvg } from './utils/base';
4
+
5
+ export const Recorder: React.FC<IconProps> = (props) => (
6
+ <RootSvg {...props}>
7
+ <RootPath
8
+ d='M0 2C0 0.895432 0.89543 0 2 0H16C17.1046 0 18 0.895431 18 2V5.38526L22.4855 3.14251C22.7944 2.95715 23.1792 2.95229 23.4927 3.1298C23.8062 3.30731 24 3.63973 24 4V16C24 16.3603 23.8062 16.6927 23.4927 16.8702C23.1792 17.0477 22.7944 17.0429 22.4855 16.8575L18 14.6147V18C18 19.1046 17.1046 20 16 20H2C0.895431 20 0 19.1046 0 18V2ZM2 2H16V6V6.94546C16 7.67313 16.7524 8.15716 17.4146 7.85545L22 5.76619V14.2338L17.4146 12.1446C16.7524 11.8428 16 12.3269 16 13.0545V14.6147V18H2V2Z'
9
+ {...props}
10
+ />
11
+ <RootPath
12
+ d='M7 5.5C7 6.32843 6.32843 7 5.5 7C4.67157 7 4 6.32843 4 5.5C4 4.67157 4.67157 4 5.5 4C6.32843 4 7 4.67157 7 5.5Z'
13
+ {...props}
14
+ />
15
+ </RootSvg>
16
+ );
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+
3
+ import { IconProps, RootPath, RootSvg } from './utils/base';
4
+
5
+ export const Video: React.FC<IconProps> = (props) => (
6
+ <RootSvg
7
+ height={props.height || 40}
8
+ viewBox={props.viewBox || '0 0 34 40'}
9
+ width={props.width || 34}
10
+ {...props}
11
+ >
12
+ <RootPath
13
+ d='M 17.7168 33.172 C 18.2348 33.172 18.4238 33.655 18.4238 34.18 C 18.4238 34.642 18.2978 35.195 17.7168 35.195 C 17.1708 35.195 16.9888 34.642 16.9888 34.145 C 16.9888 33.683 17.1708 33.172 17.7168 33.172 Z M 19.5718 31.002 H 18.3818 V 32.7589 H 18.3678 C 18.1228 32.43 17.7798 32.262 17.3318 32.262 C 16.3028 32.262 15.7988 33.158 15.7988 34.103 C 15.7988 35.125 16.2818 36.1049 17.4228 36.1049 C 17.8428 36.1049 18.1928 35.923 18.4238 35.58 H 18.4378 V 36 H 19.5718 V 31.002 Z M 12.7095 34.1872 C 12.7095 33.7252 12.8775 33.1722 13.4305 33.1722 C 13.9835 33.1722 14.1585 33.7252 14.1585 34.1872 C 14.1585 34.6492 13.9835 35.1952 13.4305 35.1952 C 12.8775 35.1952 12.7095 34.6492 12.7095 34.1872 Z M 11.5195 34.1872 C 11.5195 35.2792 12.3035 36.1052 13.4305 36.1052 C 14.5575 36.1052 15.3485 35.2792 15.3485 34.1872 C 15.3485 33.0952 14.5575 32.2622 13.4305 32.2622 C 12.3035 32.2622 11.5195 33.0952 11.5195 34.1872 Z M 21.839 32.3671 H 22.574 V 33.1371 H 21.839 V 34.7891 C 21.839 35.0761 22.007 35.1391 22.266 35.1391 C 22.3142 35.1391 22.364 35.1357 22.4147 35.1323 C 22.4672 35.1287 22.5206 35.1251 22.574 35.1251 V 36.0001 C 22.481 36.0031 22.388 36.0099 22.295 36.0168 C 22.171 36.0259 22.047 36.0351 21.923 36.0351 C 20.908 36.0351 20.649 35.7411 20.649 34.7541 V 33.1371 H 20.047 V 32.3671 H 20.649 V 31.2681 H 21.839 V 32.3671 Z'
14
+ {...props}
15
+ />
16
+ <RootPath
17
+ d='M 0 28 H 34 V 37 C 34 38.6569 32.6569 40 31 40 H 3 C 1.34315 40 0 38.6569 0 37 V 28 Z'
18
+ pathFill={'rgb(157, 39, 176)'}
19
+ {...props}
20
+ />
21
+ <RootPath
22
+ d='M 0 3 C 0 1.34315 1.34315 0 3 0 H 23 L 34 11 V 28 H 0 V 3 Z'
23
+ pathFill={'rgb(245, 245, 245)'}
24
+ {...props}
25
+ />
26
+ <RootPath
27
+ d='M 34 11 L 26 11 C 24.3431 11 23 9.65685 23 8 V 0 L 34 11 Z'
28
+ pathFill={'rgb(219, 219, 219)'}
29
+ {...props}
30
+ />
31
+ <RootPath
32
+ d='M 9 17 H 25 V 24 H 9 V 17 Z M 27 14 C 27 12.8954 26.1046 12 25 12 H 22 L 24 15 H 21 L 19 12 H 17 L 19 15 H 16 L 14 12 H 12 L 14 15 H 11 L 9 12 C 7.9 12 7.01 12.9 7.01 14 L 7 24 C 7 25.1 7.9 26 9 26 H 25 C 26.1 26 27 25.1 27 24 V 14 Z'
33
+ pathFill={'rgb(157, 39, 176)'}
34
+ {...props}
35
+ />
36
+ </RootSvg>
37
+ );
@@ -69,11 +69,13 @@ export * from './ThumbsUpReaction';
69
69
  export * from './Time';
70
70
  export * from './TXT';
71
71
  export * from './Unknown';
72
+ export * from './Recorder';
72
73
  export * from './Unpin';
73
74
  export * from './User';
74
75
  export * from './UserAdd';
75
76
  export * from './UserDelete';
76
77
  export * from './UserMinus';
78
+ export * from './Video';
77
79
  export * from './Warning';
78
80
  export * from './WutReaction';
79
81
  export * from './XLS';
package/src/native.ts CHANGED
@@ -2,6 +2,8 @@ import { FlatList as DefaultFlatList } from 'react-native';
2
2
 
3
3
  import type { NetInfoSubscription } from '@react-native-community/netinfo';
4
4
 
5
+ import type { Asset, File } from './types/types';
6
+
5
7
  const fail = () => {
6
8
  throw Error(
7
9
  'Native handler was not registered, you should import stream-chat-expo or stream-chat-react-native',
@@ -24,16 +26,9 @@ export let compressImage: CompressImage = fail;
24
26
  type DeleteFile = ({ uri }: { uri: string }) => Promise<boolean> | never;
25
27
  export let deleteFile: DeleteFile = fail;
26
28
 
27
- type GetLocalAssetUri = (uriOrAssetId: string) => Promise<string> | never;
29
+ type GetLocalAssetUri = (uriOrAssetId: string) => never;
28
30
  export let getLocalAssetUri: GetLocalAssetUri = fail;
29
31
 
30
- export type Asset = {
31
- height: number;
32
- source: 'camera' | 'picker';
33
- uri: string;
34
- width: number;
35
- id?: string;
36
- };
37
32
  type GetPhotos = ({ after, first }: { first: number; after?: string }) =>
38
33
  | Promise<{
39
34
  assets: Array<Omit<Asset, 'source'> & { source: 'picker' }>;
@@ -58,12 +53,7 @@ export let NetInfo: NetInfo = {
58
53
  type PickDocument = ({ maxNumberOfFiles }: { maxNumberOfFiles?: number }) =>
59
54
  | Promise<{
60
55
  cancelled: boolean;
61
- docs?: {
62
- name: string;
63
- size?: number | string;
64
- type?: string;
65
- uri?: string;
66
- }[];
56
+ docs?: File[];
67
57
  }>
68
58
  | never;
69
59
  export let pickDocument: PickDocument = fail;
@@ -1,5 +1,32 @@
1
1
  import type { ExtendableGenerics, LiteralStringForUnion } from 'stream-chat';
2
2
 
3
+ export type Asset = {
4
+ duration: number | null;
5
+ filename: string;
6
+ fileSize: string;
7
+ height: number;
8
+ playableDuration: number | null;
9
+ source: 'camera' | 'picker';
10
+ type: string;
11
+ uri: string;
12
+ width: number;
13
+ id?: string;
14
+ size?: number | string;
15
+ };
16
+
17
+ export type File = {
18
+ name: string;
19
+ duration?: string | null;
20
+ size?: number | string;
21
+ type?: string;
22
+ uri?: string;
23
+ };
24
+
25
+ export type DefaultAttachmentType = UnknownType & {
26
+ file_size?: number | string;
27
+ mime_type?: string;
28
+ };
29
+
3
30
  interface DefaultUserType extends UnknownType {
4
31
  image?: string;
5
32
  }
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "4.5.1-beta.1"
2
+ "version": "4.6.0-beta.1"
3
3
  }