stream-chat-react-native-core 9.0.2-beta.2 → 9.1.0

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 (212) hide show
  1. package/lib/commonjs/components/Attachment/Attachment.js +38 -10
  2. package/lib/commonjs/components/Attachment/Attachment.js.map +1 -1
  3. package/lib/commonjs/components/Attachment/AttachmentFileUploadProgressIndicator.js +97 -0
  4. package/lib/commonjs/components/Attachment/AttachmentFileUploadProgressIndicator.js.map +1 -0
  5. package/lib/commonjs/components/Attachment/AttachmentUploadIndicator.js +97 -0
  6. package/lib/commonjs/components/Attachment/AttachmentUploadIndicator.js.map +1 -0
  7. package/lib/commonjs/components/Attachment/CircularProgressIndicator.js +141 -0
  8. package/lib/commonjs/components/Attachment/CircularProgressIndicator.js.map +1 -0
  9. package/lib/commonjs/components/Attachment/FileAttachment.js +18 -4
  10. package/lib/commonjs/components/Attachment/FileAttachment.js.map +1 -1
  11. package/lib/commonjs/components/Attachment/Gallery.js +7 -1
  12. package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
  13. package/lib/commonjs/components/Attachment/MediaUploadProgressOverlay.js +59 -0
  14. package/lib/commonjs/components/Attachment/MediaUploadProgressOverlay.js.map +1 -0
  15. package/lib/commonjs/components/Attachment/VideoThumbnail.js +18 -8
  16. package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -1
  17. package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js +2 -0
  18. package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
  19. package/lib/commonjs/components/Channel/Channel.js +94 -92
  20. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  21. package/lib/commonjs/components/Chat/Chat.js +10 -1
  22. package/lib/commonjs/components/Chat/Chat.js.map +1 -1
  23. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.js +42 -54
  24. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.js.map +1 -1
  25. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +10 -6
  26. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
  27. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/FileAttachmentUploadPreview.js +12 -6
  28. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/FileAttachmentUploadPreview.js.map +1 -1
  29. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/ImageAttachmentUploadPreview.js +13 -7
  30. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/ImageAttachmentUploadPreview.js.map +1 -1
  31. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/VideoAttachmentUploadPreview.js +6 -2
  32. package/lib/commonjs/components/MessageInput/components/AttachmentPreview/VideoAttachmentUploadPreview.js.map +1 -1
  33. package/lib/commonjs/components/index.js +33 -0
  34. package/lib/commonjs/components/index.js.map +1 -1
  35. package/lib/commonjs/contexts/componentsContext/defaultComponents.js +6 -0
  36. package/lib/commonjs/contexts/componentsContext/defaultComponents.js.map +1 -1
  37. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +3 -1
  38. package/lib/commonjs/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
  39. package/lib/commonjs/contexts/messageInputContext/hooks/useMessageComposerHasSendableData.js +4 -1
  40. package/lib/commonjs/contexts/messageInputContext/hooks/useMessageComposerHasSendableData.js.map +1 -1
  41. package/lib/commonjs/contexts/themeContext/utils/theme.js +5 -0
  42. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  43. package/lib/commonjs/hooks/index.js +11 -0
  44. package/lib/commonjs/hooks/index.js.map +1 -1
  45. package/lib/commonjs/hooks/usePendingAttachmentUpload.js +106 -0
  46. package/lib/commonjs/hooks/usePendingAttachmentUpload.js.map +1 -0
  47. package/lib/commonjs/index.js +12 -0
  48. package/lib/commonjs/index.js.map +1 -1
  49. package/lib/commonjs/middlewares/attachments.js +2 -0
  50. package/lib/commonjs/middlewares/attachments.js.map +1 -1
  51. package/lib/commonjs/native.js +8 -1
  52. package/lib/commonjs/native.js.map +1 -1
  53. package/lib/commonjs/nativeMultipartUpload.js +237 -0
  54. package/lib/commonjs/nativeMultipartUpload.js.map +1 -0
  55. package/lib/commonjs/types/types.js.map +1 -1
  56. package/lib/commonjs/utils/installNativeMultipartAdapter.js +223 -0
  57. package/lib/commonjs/utils/installNativeMultipartAdapter.js.map +1 -0
  58. package/lib/commonjs/utils/utils.js +2 -2
  59. package/lib/commonjs/utils/utils.js.map +1 -1
  60. package/lib/commonjs/version.json +1 -1
  61. package/lib/module/components/Attachment/Attachment.js +38 -10
  62. package/lib/module/components/Attachment/Attachment.js.map +1 -1
  63. package/lib/module/components/Attachment/AttachmentFileUploadProgressIndicator.js +97 -0
  64. package/lib/module/components/Attachment/AttachmentFileUploadProgressIndicator.js.map +1 -0
  65. package/lib/module/components/Attachment/AttachmentUploadIndicator.js +97 -0
  66. package/lib/module/components/Attachment/AttachmentUploadIndicator.js.map +1 -0
  67. package/lib/module/components/Attachment/CircularProgressIndicator.js +141 -0
  68. package/lib/module/components/Attachment/CircularProgressIndicator.js.map +1 -0
  69. package/lib/module/components/Attachment/FileAttachment.js +18 -4
  70. package/lib/module/components/Attachment/FileAttachment.js.map +1 -1
  71. package/lib/module/components/Attachment/Gallery.js +7 -1
  72. package/lib/module/components/Attachment/Gallery.js.map +1 -1
  73. package/lib/module/components/Attachment/MediaUploadProgressOverlay.js +59 -0
  74. package/lib/module/components/Attachment/MediaUploadProgressOverlay.js.map +1 -0
  75. package/lib/module/components/Attachment/VideoThumbnail.js +18 -8
  76. package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -1
  77. package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js +2 -0
  78. package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
  79. package/lib/module/components/Channel/Channel.js +94 -92
  80. package/lib/module/components/Channel/Channel.js.map +1 -1
  81. package/lib/module/components/Chat/Chat.js +10 -1
  82. package/lib/module/components/Chat/Chat.js.map +1 -1
  83. package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.js +42 -54
  84. package/lib/module/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.js.map +1 -1
  85. package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js +10 -6
  86. package/lib/module/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.js.map +1 -1
  87. package/lib/module/components/MessageInput/components/AttachmentPreview/FileAttachmentUploadPreview.js +12 -6
  88. package/lib/module/components/MessageInput/components/AttachmentPreview/FileAttachmentUploadPreview.js.map +1 -1
  89. package/lib/module/components/MessageInput/components/AttachmentPreview/ImageAttachmentUploadPreview.js +13 -7
  90. package/lib/module/components/MessageInput/components/AttachmentPreview/ImageAttachmentUploadPreview.js.map +1 -1
  91. package/lib/module/components/MessageInput/components/AttachmentPreview/VideoAttachmentUploadPreview.js +6 -2
  92. package/lib/module/components/MessageInput/components/AttachmentPreview/VideoAttachmentUploadPreview.js.map +1 -1
  93. package/lib/module/components/index.js +33 -0
  94. package/lib/module/components/index.js.map +1 -1
  95. package/lib/module/contexts/componentsContext/defaultComponents.js +6 -0
  96. package/lib/module/contexts/componentsContext/defaultComponents.js.map +1 -1
  97. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js +3 -1
  98. package/lib/module/contexts/messageInputContext/hooks/useCreateMessageInputContext.js.map +1 -1
  99. package/lib/module/contexts/messageInputContext/hooks/useMessageComposerHasSendableData.js +4 -1
  100. package/lib/module/contexts/messageInputContext/hooks/useMessageComposerHasSendableData.js.map +1 -1
  101. package/lib/module/contexts/themeContext/utils/theme.js +5 -0
  102. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  103. package/lib/module/hooks/index.js +11 -0
  104. package/lib/module/hooks/index.js.map +1 -1
  105. package/lib/module/hooks/usePendingAttachmentUpload.js +106 -0
  106. package/lib/module/hooks/usePendingAttachmentUpload.js.map +1 -0
  107. package/lib/module/index.js +12 -0
  108. package/lib/module/index.js.map +1 -1
  109. package/lib/module/middlewares/attachments.js +2 -0
  110. package/lib/module/middlewares/attachments.js.map +1 -1
  111. package/lib/module/native.js +8 -1
  112. package/lib/module/native.js.map +1 -1
  113. package/lib/module/nativeMultipartUpload.js +237 -0
  114. package/lib/module/nativeMultipartUpload.js.map +1 -0
  115. package/lib/module/types/types.js.map +1 -1
  116. package/lib/module/utils/installNativeMultipartAdapter.js +223 -0
  117. package/lib/module/utils/installNativeMultipartAdapter.js.map +1 -0
  118. package/lib/module/utils/utils.js +2 -2
  119. package/lib/module/utils/utils.js.map +1 -1
  120. package/lib/module/version.json +1 -1
  121. package/lib/typescript/components/Attachment/Attachment.d.ts.map +1 -1
  122. package/lib/typescript/components/Attachment/AttachmentFileUploadProgressIndicator.d.ts +14 -0
  123. package/lib/typescript/components/Attachment/AttachmentFileUploadProgressIndicator.d.ts.map +1 -0
  124. package/lib/typescript/components/Attachment/AttachmentUploadIndicator.d.ts +18 -0
  125. package/lib/typescript/components/Attachment/AttachmentUploadIndicator.d.ts.map +1 -0
  126. package/lib/typescript/components/Attachment/CircularProgressIndicator.d.ts +18 -0
  127. package/lib/typescript/components/Attachment/CircularProgressIndicator.d.ts.map +1 -0
  128. package/lib/typescript/components/Attachment/FileAttachment.d.ts.map +1 -1
  129. package/lib/typescript/components/Attachment/Gallery.d.ts.map +1 -1
  130. package/lib/typescript/components/Attachment/MediaUploadProgressOverlay.d.ts +12 -0
  131. package/lib/typescript/components/Attachment/MediaUploadProgressOverlay.d.ts.map +1 -0
  132. package/lib/typescript/components/Attachment/VideoThumbnail.d.ts +4 -0
  133. package/lib/typescript/components/Attachment/VideoThumbnail.d.ts.map +1 -1
  134. package/lib/typescript/components/Attachment/utils/buildGallery/buildThumbnail.d.ts.map +1 -1
  135. package/lib/typescript/components/Attachment/utils/buildGallery/types.d.ts +2 -0
  136. package/lib/typescript/components/Attachment/utils/buildGallery/types.d.ts.map +1 -1
  137. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  138. package/lib/typescript/components/Chat/Chat.d.ts +10 -0
  139. package/lib/typescript/components/Chat/Chat.d.ts.map +1 -1
  140. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.d.ts +7 -2
  141. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.d.ts.map +1 -1
  142. package/lib/typescript/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.d.ts.map +1 -1
  143. package/lib/typescript/components/MessageInput/components/AttachmentPreview/FileAttachmentUploadPreview.d.ts.map +1 -1
  144. package/lib/typescript/components/MessageInput/components/AttachmentPreview/ImageAttachmentUploadPreview.d.ts.map +1 -1
  145. package/lib/typescript/components/MessageInput/components/AttachmentPreview/VideoAttachmentUploadPreview.d.ts.map +1 -1
  146. package/lib/typescript/components/index.d.ts +3 -0
  147. package/lib/typescript/components/index.d.ts.map +1 -1
  148. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts +5 -2
  149. package/lib/typescript/contexts/componentsContext/defaultComponents.d.ts.map +1 -1
  150. package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts +1 -1
  151. package/lib/typescript/contexts/messageInputContext/hooks/useCreateMessageInputContext.d.ts.map +1 -1
  152. package/lib/typescript/contexts/messageInputContext/hooks/useMessageComposerHasSendableData.d.ts.map +1 -1
  153. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts +5 -0
  154. package/lib/typescript/contexts/themeContext/ThemeContext.d.ts.map +1 -1
  155. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +5 -0
  156. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  157. package/lib/typescript/hooks/index.d.ts +1 -0
  158. package/lib/typescript/hooks/index.d.ts.map +1 -1
  159. package/lib/typescript/hooks/usePendingAttachmentUpload.d.ts +14 -0
  160. package/lib/typescript/hooks/usePendingAttachmentUpload.d.ts.map +1 -0
  161. package/lib/typescript/index.d.ts +1 -0
  162. package/lib/typescript/index.d.ts.map +1 -1
  163. package/lib/typescript/middlewares/attachments.d.ts.map +1 -1
  164. package/lib/typescript/native.d.ts +5 -2
  165. package/lib/typescript/native.d.ts.map +1 -1
  166. package/lib/typescript/nativeMultipartUpload.d.ts +98 -0
  167. package/lib/typescript/nativeMultipartUpload.d.ts.map +1 -0
  168. package/lib/typescript/types/types.d.ts +2 -0
  169. package/lib/typescript/types/types.d.ts.map +1 -1
  170. package/lib/typescript/utils/installNativeMultipartAdapter.d.ts +8 -0
  171. package/lib/typescript/utils/installNativeMultipartAdapter.d.ts.map +1 -0
  172. package/lib/typescript/utils/utils.d.ts +1 -1
  173. package/lib/typescript/utils/utils.d.ts.map +1 -1
  174. package/package.json +2 -2
  175. package/src/__tests__/nativeMultipartUpload.test.ts +267 -0
  176. package/src/components/Attachment/Attachment.tsx +54 -5
  177. package/src/components/Attachment/AttachmentFileUploadProgressIndicator.tsx +108 -0
  178. package/src/components/Attachment/AttachmentUploadIndicator.tsx +112 -0
  179. package/src/components/Attachment/CircularProgressIndicator.tsx +161 -0
  180. package/src/components/Attachment/FileAttachment.tsx +22 -6
  181. package/src/components/Attachment/Gallery.tsx +9 -1
  182. package/src/components/Attachment/MediaUploadProgressOverlay.tsx +77 -0
  183. package/src/components/Attachment/VideoThumbnail.tsx +17 -9
  184. package/src/components/Attachment/__tests__/Attachment.test.tsx +63 -16
  185. package/src/components/Attachment/utils/buildGallery/buildThumbnail.ts +3 -0
  186. package/src/components/Attachment/utils/buildGallery/types.ts +2 -0
  187. package/src/components/Channel/Channel.tsx +65 -61
  188. package/src/components/Chat/Chat.tsx +20 -0
  189. package/src/components/MessageInput/__tests__/AttachmentUploadPreviewList.test.tsx +51 -6
  190. package/src/components/MessageInput/__tests__/AudioAttachmentUploadPreview.test.tsx +31 -1
  191. package/src/components/MessageInput/components/AttachmentPreview/AttachmentUploadProgressIndicator.tsx +30 -44
  192. package/src/components/MessageInput/components/AttachmentPreview/AudioAttachmentUploadPreview.tsx +11 -5
  193. package/src/components/MessageInput/components/AttachmentPreview/FileAttachmentUploadPreview.tsx +20 -5
  194. package/src/components/MessageInput/components/AttachmentPreview/ImageAttachmentUploadPreview.tsx +20 -9
  195. package/src/components/MessageInput/components/AttachmentPreview/VideoAttachmentUploadPreview.tsx +7 -1
  196. package/src/components/index.ts +3 -0
  197. package/src/contexts/componentsContext/defaultComponents.ts +6 -0
  198. package/src/contexts/messageInputContext/hooks/useCreateMessageInputContext.ts +3 -1
  199. package/src/contexts/messageInputContext/hooks/useMessageComposerHasSendableData.ts +5 -1
  200. package/src/contexts/themeContext/utils/theme.ts +10 -0
  201. package/src/hooks/__tests__/usePendingAttachmentUpload.test.tsx +106 -0
  202. package/src/hooks/index.ts +1 -0
  203. package/src/hooks/usePendingAttachmentUpload.ts +131 -0
  204. package/src/index.ts +1 -0
  205. package/src/middlewares/attachments.ts +2 -0
  206. package/src/native.ts +28 -0
  207. package/src/nativeMultipartUpload.ts +384 -0
  208. package/src/types/types.ts +2 -0
  209. package/src/utils/__tests__/installNativeMultipartAdapter.test.ts +437 -0
  210. package/src/utils/installNativeMultipartAdapter.ts +302 -0
  211. package/src/utils/utils.ts +3 -3
  212. package/src/version.json +1 -1
@@ -1,8 +1,10 @@
1
1
  import React, { useMemo } from 'react';
2
- import { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native';
2
+ import { Pressable, StyleSheet, Text, View } from 'react-native';
3
3
 
4
4
  import { LocalAttachmentUploadMetadata } from 'stream-chat';
5
5
 
6
+ import { AttachmentFileUploadProgressIndicator } from '../../../../components/Attachment/AttachmentFileUploadProgressIndicator';
7
+ import { useComponentsContext } from '../../../../contexts/componentsContext/ComponentsContext';
6
8
  import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
7
9
  import { useTranslationContext } from '../../../../contexts/translationContext/TranslationContext';
8
10
  import { ExclamationCircle } from '../../../../icons/exclamation-circle-fill';
@@ -10,24 +12,30 @@ import { Warning } from '../../../../icons/exclamation-triangle-fill';
10
12
  import { primitives } from '../../../../theme';
11
13
  import { RetryBadge } from '../../../ui/Badge/RetryBadge';
12
14
 
13
- export const FileUploadInProgressIndicator = () => {
15
+ export type UploadInProgressIndicatorProps = {
16
+ localId?: string;
17
+ sourceUrl?: string;
18
+ totalBytes?: number | string | null;
19
+ };
20
+
21
+ export const FileUploadInProgressIndicator = ({
22
+ localId,
23
+ sourceUrl,
24
+ totalBytes,
25
+ }: UploadInProgressIndicatorProps = {}) => {
14
26
  const {
15
27
  theme: {
16
- semantics,
17
28
  messageComposer: { fileUploadInProgressIndicator },
18
29
  },
19
30
  } = useTheme();
20
31
 
21
32
  return (
22
- <View
23
- style={[styles.activityIndicatorContainer, fileUploadInProgressIndicator.container]}
24
- testID='upload-progress-indicator'
25
- >
26
- <ActivityIndicator
27
- color={semantics.accentPrimary}
28
- style={[styles.activityIndicator, fileUploadInProgressIndicator.indicator]}
29
- />
30
- </View>
33
+ <AttachmentFileUploadProgressIndicator
34
+ containerStyle={[styles.activityIndicatorContainer, fileUploadInProgressIndicator.container]}
35
+ localId={localId}
36
+ sourceUrl={sourceUrl}
37
+ totalBytes={totalBytes}
38
+ />
31
39
  );
32
40
  };
33
41
 
@@ -108,24 +116,13 @@ export const FileUploadNotSupportedIndicator = ({
108
116
  );
109
117
  };
110
118
 
111
- export const ImageUploadInProgressIndicator = () => {
112
- const {
113
- theme: {
114
- semantics,
115
- messageComposer: { imageUploadInProgressIndicator },
116
- },
117
- } = useTheme();
118
- const styles = useImageUploadInProgressIndicatorStyles();
119
- return (
120
- <View style={[styles.container, imageUploadInProgressIndicator.container]}>
121
- <ActivityIndicator
122
- size='small'
123
- color={semantics.accentPrimary}
124
- style={imageUploadInProgressIndicator.indicator}
125
- testID='upload-progress-indicator'
126
- />
127
- </View>
128
- );
119
+ export const ImageUploadInProgressIndicator = ({
120
+ localId,
121
+ sourceUrl,
122
+ }: UploadInProgressIndicatorProps = {}) => {
123
+ const { AttachmentUploadIndicator } = useComponentsContext();
124
+
125
+ return <AttachmentUploadIndicator localId={localId} sourceUrl={sourceUrl} variant='overlay' />;
129
126
  };
130
127
 
131
128
  export type ImageUploadRetryIndicatorProps = {
@@ -158,16 +155,6 @@ export const ImageUploadNotSupportedIndicator = () => {
158
155
  );
159
156
  };
160
157
 
161
- const useImageUploadInProgressIndicatorStyles = () => {
162
- return StyleSheet.create({
163
- container: {
164
- position: 'absolute',
165
- left: primitives.spacingXxs,
166
- bottom: primitives.spacingXxs,
167
- },
168
- });
169
- };
170
-
171
158
  const useImageUploadNotSupportedIndicatorStyles = () => {
172
159
  const {
173
160
  theme: { semantics },
@@ -235,9 +222,8 @@ const useFileUploadNotSupportedStyles = () => {
235
222
  };
236
223
 
237
224
  const styles = StyleSheet.create({
238
- activityIndicatorContainer: {},
239
- activityIndicator: {
240
- alignItems: 'flex-start',
241
- justifyContent: 'flex-start',
225
+ activityIndicatorContainer: {
226
+ alignItems: 'center',
227
+ justifyContent: 'center',
242
228
  },
243
229
  });
@@ -13,8 +13,8 @@ import {
13
13
 
14
14
  import { AudioAttachment } from '../../../../components/Attachment/Audio';
15
15
  import { useTheme } from '../../../../contexts';
16
- import { useChatContext } from '../../../../contexts/chatContext/ChatContext';
17
16
  import { useMessageComposer } from '../../../../contexts/messageInputContext/hooks/useMessageComposer';
17
+ import { useMessageInputContext } from '../../../../contexts/messageInputContext/MessageInputContext';
18
18
  import { primitives } from '../../../../theme';
19
19
  import { UploadAttachmentPreviewProps } from '../../../../types/types';
20
20
  import { getIndicatorTypeForFileState, ProgressIndicatorTypes } from '../../../../utils/utils';
@@ -30,10 +30,10 @@ export const AudioAttachmentUploadPreview = ({
30
30
  removeAttachments,
31
31
  }: AudioAttachmentUploadPreviewProps) => {
32
32
  const styles = useStyles();
33
- const { enableOfflineSupport } = useChatContext();
33
+ const { allowSendBeforeAttachmentsUpload } = useMessageInputContext();
34
34
  const indicatorType = getIndicatorTypeForFileState(
35
35
  attachment.localMetadata.uploadState,
36
- enableOfflineSupport,
36
+ !!allowSendBeforeAttachmentsUpload,
37
37
  );
38
38
  const messageComposer = useMessageComposer();
39
39
  const isDraft = messageComposer.draftId;
@@ -63,7 +63,13 @@ export const AudioAttachmentUploadPreview = ({
63
63
 
64
64
  const renderIndicator = useMemo(() => {
65
65
  if (indicatorType === ProgressIndicatorTypes.IN_PROGRESS) {
66
- return <FileUploadInProgressIndicator />;
66
+ return (
67
+ <FileUploadInProgressIndicator
68
+ localId={attachment.localMetadata.id}
69
+ sourceUrl={assetUrl}
70
+ totalBytes={attachment.file_size}
71
+ />
72
+ );
67
73
  }
68
74
  if (indicatorType === ProgressIndicatorTypes.RETRY) {
69
75
  return <FileUploadRetryIndicator onPress={onRetryHandler} />;
@@ -72,7 +78,7 @@ export const AudioAttachmentUploadPreview = ({
72
78
  return <FileUploadNotSupportedIndicator localMetadata={attachment.localMetadata} />;
73
79
  }
74
80
  return null;
75
- }, [attachment.localMetadata, indicatorType, onRetryHandler]);
81
+ }, [assetUrl, attachment.file_size, attachment.localMetadata, indicatorType, onRetryHandler]);
76
82
 
77
83
  return (
78
84
  <View style={styles.wrapper} testID={'audio-attachment-upload-preview'}>
@@ -2,13 +2,18 @@ import React, { useCallback, useMemo } from 'react';
2
2
 
3
3
  import { StyleSheet, View } from 'react-native';
4
4
 
5
- import { LocalAudioAttachment, LocalFileAttachment, LocalVideoAttachment } from 'stream-chat';
5
+ import {
6
+ FileReference,
7
+ LocalAudioAttachment,
8
+ LocalFileAttachment,
9
+ LocalVideoAttachment,
10
+ } from 'stream-chat';
6
11
 
7
12
  import { AttachmentRemoveControl } from './AttachmentRemoveControl';
8
13
 
9
14
  import { FilePreview } from '../../../../components/Attachment/FilePreview';
10
- import { useChatContext } from '../../../../contexts/chatContext/ChatContext';
11
15
  import { useComponentsContext } from '../../../../contexts/componentsContext/ComponentsContext';
16
+ import { useMessageInputContext } from '../../../../contexts/messageInputContext/MessageInputContext';
12
17
  import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
13
18
  import { primitives } from '../../../../theme';
14
19
  import { UploadAttachmentPreviewProps } from '../../../../types/types';
@@ -27,15 +32,17 @@ export const FileAttachmentUploadPreview = ({
27
32
  removeAttachments,
28
33
  }: FileAttachmentUploadPreviewProps) => {
29
34
  const styles = useStyles();
35
+ const sourceUrl =
36
+ attachment.asset_url ?? (attachment.localMetadata.file as FileReference | undefined)?.uri;
30
37
  const {
31
38
  FileUploadInProgressIndicator,
32
39
  FileUploadRetryIndicator,
33
40
  FileUploadNotSupportedIndicator,
34
41
  } = useComponentsContext();
35
- const { enableOfflineSupport } = useChatContext();
42
+ const { allowSendBeforeAttachmentsUpload } = useMessageInputContext();
36
43
  const indicatorType = getIndicatorTypeForFileState(
37
44
  attachment.localMetadata.uploadState,
38
- enableOfflineSupport,
45
+ !!allowSendBeforeAttachmentsUpload,
39
46
  );
40
47
 
41
48
  const {
@@ -56,7 +63,13 @@ export const FileAttachmentUploadPreview = ({
56
63
 
57
64
  const renderIndicator = useMemo(() => {
58
65
  if (indicatorType === ProgressIndicatorTypes.IN_PROGRESS) {
59
- return <FileUploadInProgressIndicator />;
66
+ return (
67
+ <FileUploadInProgressIndicator
68
+ localId={attachment.localMetadata.id}
69
+ sourceUrl={sourceUrl}
70
+ totalBytes={attachment.file_size}
71
+ />
72
+ );
60
73
  }
61
74
  if (indicatorType === ProgressIndicatorTypes.RETRY) {
62
75
  return <FileUploadRetryIndicator onPress={onRetryHandler} />;
@@ -70,8 +83,10 @@ export const FileAttachmentUploadPreview = ({
70
83
  FileUploadNotSupportedIndicator,
71
84
  FileUploadRetryIndicator,
72
85
  attachment.localMetadata,
86
+ attachment.file_size,
73
87
  indicatorType,
74
88
  onRetryHandler,
89
+ sourceUrl,
75
90
  ]);
76
91
 
77
92
  return (
@@ -6,8 +6,8 @@ import { LocalImageAttachment } from 'stream-chat';
6
6
 
7
7
  import { AttachmentRemoveControl } from './AttachmentRemoveControl';
8
8
 
9
- import { useChatContext } from '../../../../contexts/chatContext/ChatContext';
10
9
  import { useComponentsContext } from '../../../../contexts/componentsContext/ComponentsContext';
10
+ import { useMessageInputContext } from '../../../../contexts/messageInputContext/MessageInputContext';
11
11
  import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
12
12
  import { primitives } from '../../../../theme';
13
13
  import { UploadAttachmentPreviewProps } from '../../../../types/types';
@@ -24,15 +24,20 @@ export const ImageAttachmentUploadPreview = ({
24
24
  removeAttachments,
25
25
  }: ImageAttachmentUploadPreviewProps) => {
26
26
  const [loading, setLoading] = useState(true);
27
- const { enableOfflineSupport } = useChatContext();
27
+ const { allowSendBeforeAttachmentsUpload } = useMessageInputContext();
28
28
  const {
29
+ ImageLoadingIndicator,
29
30
  ImageUploadInProgressIndicator,
30
31
  ImageUploadRetryIndicator,
31
32
  ImageUploadNotSupportedIndicator,
32
33
  } = useComponentsContext();
33
- const indicatorType = loading
34
- ? ProgressIndicatorTypes.IN_PROGRESS
35
- : getIndicatorTypeForFileState(attachment.localMetadata.uploadState, enableOfflineSupport);
34
+ const indicatorType = getIndicatorTypeForFileState(
35
+ attachment.localMetadata.uploadState,
36
+ !!allowSendBeforeAttachmentsUpload,
37
+ );
38
+ const previewUri = attachment.localMetadata.previewUri ?? attachment.image_url;
39
+ const shouldShowImageLoadingIndicator =
40
+ loading && indicatorType !== ProgressIndicatorTypes.IN_PROGRESS;
36
41
 
37
42
  const {
38
43
  theme: {
@@ -65,15 +70,21 @@ export const ImageAttachmentUploadPreview = ({
65
70
  <Image
66
71
  onError={onErrorHandler}
67
72
  onLoadEnd={onLoadEndHandler}
68
- source={{ uri: attachment.localMetadata.previewUri ?? attachment.image_url }}
73
+ source={{ uri: previewUri }}
69
74
  style={StyleSheet.absoluteFill}
70
75
  testID={'image-attachment-upload-preview-image'}
71
76
  />
72
- {indicatorType === ProgressIndicatorTypes.IN_PROGRESS && <ImageUploadInProgressIndicator />}
73
- {indicatorType === ProgressIndicatorTypes.RETRY && (
77
+ {shouldShowImageLoadingIndicator ? <ImageLoadingIndicator /> : null}
78
+ {indicatorType === ProgressIndicatorTypes.IN_PROGRESS && (
79
+ <ImageUploadInProgressIndicator
80
+ localId={attachment.localMetadata.id}
81
+ sourceUrl={previewUri}
82
+ />
83
+ )}
84
+ {!loading && indicatorType === ProgressIndicatorTypes.RETRY && (
74
85
  <ImageUploadRetryIndicator onRetryHandler={onRetryHandler} />
75
86
  )}
76
- {indicatorType === ProgressIndicatorTypes.NOT_SUPPORTED && (
87
+ {!loading && indicatorType === ProgressIndicatorTypes.NOT_SUPPORTED && (
77
88
  <ImageUploadNotSupportedIndicator />
78
89
  )}
79
90
  </View>
@@ -7,6 +7,7 @@ import { LocalImageAttachment, LocalVideoAttachment } from 'stream-chat';
7
7
  import { FileAttachmentUploadPreview } from './FileAttachmentUploadPreview';
8
8
  import { ImageAttachmentUploadPreview } from './ImageAttachmentUploadPreview';
9
9
 
10
+ import { useMessageInputContext } from '../../../../contexts';
10
11
  import { useTheme } from '../../../../contexts/themeContext/ThemeContext';
11
12
  import { Recorder } from '../../../../icons';
12
13
  import { primitives } from '../../../../theme';
@@ -22,6 +23,9 @@ export const VideoAttachmentUploadPreview = ({
22
23
  removeAttachments,
23
24
  }: VideoAttachmentUploadPreviewProps) => {
24
25
  const previewUri = attachment.thumb_url ?? attachment.localMetadata.previewUri;
26
+ const { allowSendBeforeAttachmentsUpload } = useMessageInputContext();
27
+ const shouldShowMetadataPill =
28
+ allowSendBeforeAttachmentsUpload || attachment.localMetadata.uploadState !== 'uploading';
25
29
 
26
30
  return previewUri ? (
27
31
  <>
@@ -38,7 +42,9 @@ export const VideoAttachmentUploadPreview = ({
38
42
  handleRetry={handleRetry}
39
43
  removeAttachments={removeAttachments}
40
44
  />
41
- <VideoAttachmentMetadataPill duration={attachment.duration} format={'descriptive'} />
45
+ {shouldShowMetadataPill ? (
46
+ <VideoAttachmentMetadataPill duration={attachment.duration} format={'descriptive'} />
47
+ ) : null}
42
48
  </>
43
49
  ) : (
44
50
  <FileAttachmentUploadPreview
@@ -6,6 +6,9 @@ export * from './Attachment/FileAttachmentGroup';
6
6
  export * from './Attachment/FileIcon';
7
7
  export * from './Attachment/Gallery';
8
8
  export * from './Attachment/Giphy';
9
+ export * from './Attachment/CircularProgressIndicator';
10
+ export * from './Attachment/AttachmentUploadIndicator';
11
+ export * from './Attachment/MediaUploadProgressOverlay';
9
12
  export * from './Attachment/VideoThumbnail';
10
13
  export * from './Attachment/UrlPreview';
11
14
  export * from './Attachment/utils/buildGallery/buildGallery';
@@ -4,7 +4,9 @@ import { Image, ImageProps, TextInputProps } from 'react-native';
4
4
  import type { LocalMessage, UserResponse } from 'stream-chat';
5
5
 
6
6
  import { Attachment } from '../../components/Attachment/Attachment';
7
+ import { AttachmentUploadIndicator } from '../../components/Attachment/AttachmentUploadIndicator';
7
8
  import { AudioAttachment } from '../../components/Attachment/Audio';
9
+ import { CircularProgressIndicator } from '../../components/Attachment/CircularProgressIndicator';
8
10
  import { FileAttachment } from '../../components/Attachment/FileAttachment';
9
11
  import { FileAttachmentGroup } from '../../components/Attachment/FileAttachmentGroup';
10
12
  import { FileIcon } from '../../components/Attachment/FileIcon';
@@ -13,6 +15,7 @@ import { Gallery } from '../../components/Attachment/Gallery';
13
15
  import { Giphy } from '../../components/Attachment/Giphy';
14
16
  import { ImageLoadingFailedIndicator } from '../../components/Attachment/ImageLoadingFailedIndicator';
15
17
  import { ImageLoadingIndicator } from '../../components/Attachment/ImageLoadingIndicator';
18
+ import { MediaUploadProgressOverlay } from '../../components/Attachment/MediaUploadProgressOverlay';
16
19
  import { UnsupportedAttachment } from '../../components/Attachment/UnsupportedAttachment';
17
20
  import { URLPreview } from '../../components/Attachment/UrlPreview';
18
21
  import { URLPreviewCompact } from '../../components/Attachment/UrlPreview/URLPreviewCompact';
@@ -160,6 +163,7 @@ type NormalizeComponents<T> = {
160
163
 
161
164
  const components = {
162
165
  Attachment,
166
+ AttachmentUploadIndicator,
163
167
  AttachButton,
164
168
  AttachmentPickerContent,
165
169
  AttachmentPickerSelectionBar,
@@ -176,6 +180,7 @@ const components = {
176
180
  AutoCompleteSuggestionList,
177
181
  ChannelDetailsBottomSheet,
178
182
  CooldownTimer,
183
+ CircularProgressIndicator,
179
184
  DateHeader,
180
185
  EmptyStateIndicator,
181
186
  FileAttachment,
@@ -206,6 +211,7 @@ const components = {
206
211
  LoadingErrorIndicator,
207
212
  ChannelListLoadingIndicator,
208
213
  MessageListLoadingIndicator: LoadingIndicator,
214
+ MediaUploadProgressOverlay,
209
215
  Message,
210
216
  MessageActionList,
211
217
  MessageActionListItem,
@@ -5,6 +5,7 @@ import type { MessageInputContextValue } from '../MessageInputContext';
5
5
 
6
6
  export const useCreateMessageInputContext = ({
7
7
  additionalTextInputProps,
8
+ allowSendBeforeAttachmentsUpload,
8
9
  asyncMessagesLockDistance,
9
10
  asyncMessagesMinimumPressDuration,
10
11
  asyncMessagesSlideToCancelDistance,
@@ -47,6 +48,7 @@ export const useCreateMessageInputContext = ({
47
48
  const messageInputContext: MessageInputContextValue = useMemo(
48
49
  () => ({
49
50
  additionalTextInputProps,
51
+ allowSendBeforeAttachmentsUpload,
50
52
  asyncMessagesLockDistance,
51
53
  asyncMessagesMinimumPressDuration,
52
54
  asyncMessagesSlideToCancelDistance,
@@ -84,7 +86,7 @@ export const useCreateMessageInputContext = ({
84
86
  stopVoiceRecording,
85
87
  }),
86
88
  // eslint-disable-next-line react-hooks/exhaustive-deps
87
- [threadId, showPollCreationDialog],
89
+ [threadId, showPollCreationDialog, allowSendBeforeAttachmentsUpload],
88
90
  );
89
91
 
90
92
  return messageInputContext;
@@ -3,11 +3,15 @@ import type { EditingAuditState } from 'stream-chat';
3
3
  import { useMessageComposer } from './useMessageComposer';
4
4
 
5
5
  import { useStateStore } from '../../../hooks/useStateStore';
6
+ import { useMessageInputContext } from '../MessageInputContext';
6
7
 
7
8
  const editingAuditStateStateSelector = (state: EditingAuditState) => state;
8
9
 
9
10
  export const useMessageComposerHasSendableData = () => {
11
+ const { allowSendBeforeAttachmentsUpload } = useMessageInputContext();
10
12
  const messageComposer = useMessageComposer();
11
13
  useStateStore(messageComposer.editingAuditState, editingAuditStateStateSelector);
12
- return messageComposer.hasSendableData;
14
+ return allowSendBeforeAttachmentsUpload
15
+ ? !messageComposer.contentIsEmpty
16
+ : messageComposer.hasSendableData;
13
17
  };
@@ -677,6 +677,11 @@ export type Theme = {
677
677
  attachmentContainer: ViewStyle;
678
678
  container: ViewStyle;
679
679
  };
680
+ attachmentUploadIndicator: {
681
+ indicator: ViewStyle;
682
+ overlay: ViewStyle;
683
+ overlayContent: ViewStyle;
684
+ };
680
685
  gallery: {
681
686
  galleryContainer: ViewStyle;
682
687
  galleryItemColumn: ViewStyle;
@@ -1602,6 +1607,11 @@ export const defaultTheme: Theme = {
1602
1607
  attachmentContainer: {},
1603
1608
  container: {},
1604
1609
  },
1610
+ attachmentUploadIndicator: {
1611
+ indicator: {},
1612
+ overlay: {},
1613
+ overlayContent: {},
1614
+ },
1605
1615
  gallery: {
1606
1616
  galleryContainer: {},
1607
1617
  galleryItemColumn: {},
@@ -0,0 +1,106 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+
3
+ import { act, renderHook } from '@testing-library/react-native';
4
+ import { StateStore } from 'stream-chat';
5
+
6
+ import { ChatProvider } from '../../contexts/chatContext/ChatContext';
7
+ import { usePendingAttachmentUpload } from '../usePendingAttachmentUpload';
8
+
9
+ type UploadManagerState = {
10
+ uploads: Record<
11
+ string,
12
+ {
13
+ id: string;
14
+ uploadProgress?: number;
15
+ }
16
+ >;
17
+ };
18
+
19
+ const createWrapper = (state: StateStore<UploadManagerState>) => {
20
+ const client = {
21
+ uploadManager: {
22
+ state,
23
+ },
24
+ };
25
+
26
+ return ({ children }: PropsWithChildren) => (
27
+ <ChatProvider value={{ client } as never}>{children}</ChatProvider>
28
+ );
29
+ };
30
+
31
+ describe('usePendingAttachmentUpload', () => {
32
+ beforeEach(() => {
33
+ jest.useFakeTimers();
34
+ });
35
+
36
+ afterEach(() => {
37
+ jest.useRealTimers();
38
+ });
39
+
40
+ it('briefly holds completed upload progress after a ready upload record disappears', () => {
41
+ const state = new StateStore<UploadManagerState>({ uploads: {} });
42
+ const { result } = renderHook(() => usePendingAttachmentUpload('upload-id'), {
43
+ wrapper: createWrapper(state),
44
+ });
45
+
46
+ expect(result.current).toEqual({
47
+ isUploading: false,
48
+ uploadProgress: undefined,
49
+ });
50
+
51
+ act(() => {
52
+ state.partialNext({
53
+ uploads: {
54
+ 'upload-id': { id: 'upload-id', uploadProgress: 90 },
55
+ },
56
+ });
57
+ });
58
+
59
+ expect(result.current).toEqual({
60
+ isUploading: true,
61
+ uploadProgress: 90,
62
+ });
63
+
64
+ act(() => {
65
+ state.partialNext({ uploads: {} });
66
+ });
67
+
68
+ expect(result.current).toEqual({
69
+ isUploading: true,
70
+ uploadProgress: 100,
71
+ });
72
+
73
+ act(() => {
74
+ jest.advanceTimersByTime(350);
75
+ });
76
+
77
+ expect(result.current).toEqual({
78
+ isUploading: false,
79
+ uploadProgress: undefined,
80
+ });
81
+ });
82
+
83
+ it('does not hold completed progress when an upload record disappears before reaching the ready threshold', () => {
84
+ const state = new StateStore<UploadManagerState>({ uploads: {} });
85
+ const { result } = renderHook(() => usePendingAttachmentUpload('upload-id'), {
86
+ wrapper: createWrapper(state),
87
+ });
88
+
89
+ act(() => {
90
+ state.partialNext({
91
+ uploads: {
92
+ 'upload-id': { id: 'upload-id', uploadProgress: 50 },
93
+ },
94
+ });
95
+ });
96
+
97
+ act(() => {
98
+ state.partialNext({ uploads: {} });
99
+ });
100
+
101
+ expect(result.current).toEqual({
102
+ isUploading: false,
103
+ uploadProgress: undefined,
104
+ });
105
+ });
106
+ });
@@ -3,6 +3,7 @@ export * from './useStreami18n';
3
3
  export * from './useViewport';
4
4
  export * from './useScreenDimensions';
5
5
  export * from './useStateStore';
6
+ export * from './usePendingAttachmentUpload';
6
7
  export * from './useStableCallback';
7
8
  export * from './useLoadingImage';
8
9
  export * from './useMessageReminder';