stream-chat-react-native-core 4.6.1 → 4.7.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.
- package/lib/commonjs/components/Attachment/Attachment.js +22 -13
- package/lib/commonjs/components/Attachment/Attachment.js.map +1 -1
- package/lib/commonjs/components/Attachment/Gallery.js +72 -37
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/Attachment/VideoThumbnail.js +83 -0
- package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -0
- package/lib/commonjs/components/Attachment/hooks/useGoToURL.js +1 -1
- package/lib/commonjs/components/Attachment/hooks/useGoToURL.js.map +1 -1
- package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js +1 -0
- package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
- package/lib/commonjs/components/Attachment/utils/getAspectRatio.js +5 -5
- package/lib/commonjs/components/Attachment/utils/getAspectRatio.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +19 -14
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +4 -2
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js +43 -28
- package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/ImageGallery.js +167 -345
- package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js +4 -4
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js +225 -0
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +102 -40
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +145 -0
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/components/ImageGrid.js +31 -34
- package/lib/commonjs/components/ImageGallery/components/ImageGrid.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ProgressControl.js +153 -0
- package/lib/commonjs/components/ImageGallery/components/ProgressControl.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js +373 -0
- package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -0
- package/lib/commonjs/components/Message/Message.js +23 -13
- package/lib/commonjs/components/Message/Message.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +4 -2
- package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
- package/lib/commonjs/components/MessageOverlay/MessageOverlay.js +25 -23
- package/lib/commonjs/components/MessageOverlay/MessageOverlay.js.map +1 -1
- package/lib/commonjs/components/Reply/Reply.js +32 -12
- package/lib/commonjs/components/Reply/Reply.js.map +1 -1
- package/lib/commonjs/components/Spinner/Spinner.js +12 -4
- package/lib/commonjs/components/Spinner/Spinner.js.map +1 -1
- package/lib/commonjs/components/index.js +26 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/messageContext/MessageContext.js +2 -2
- package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
- package/lib/commonjs/contexts/messageOverlayContext/MessageOverlayContext.js +2 -2
- package/lib/commonjs/contexts/messageOverlayContext/MessageOverlayContext.js.map +1 -1
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +10 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/icons/Pause.js +61 -0
- package/lib/commonjs/icons/Pause.js.map +1 -0
- package/lib/commonjs/icons/Play.js +42 -0
- package/lib/commonjs/icons/Play.js.map +1 -0
- package/lib/commonjs/icons/index.js +26 -0
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/mock-builders/api/queryMembers.js +98 -1
- package/lib/commonjs/mock-builders/api/queryMembers.js.map +1 -1
- package/lib/commonjs/native.js +7 -1
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/utils/getUrlOfImageAttachment.js +1 -1
- package/lib/commonjs/utils/getUrlOfImageAttachment.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/Attachment.js +22 -13
- package/lib/module/components/Attachment/Attachment.js.map +1 -1
- package/lib/module/components/Attachment/Gallery.js +72 -37
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/Attachment/VideoThumbnail.js +83 -0
- package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -0
- package/lib/module/components/Attachment/hooks/useGoToURL.js +1 -1
- package/lib/module/components/Attachment/hooks/useGoToURL.js.map +1 -1
- package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js +1 -0
- package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
- package/lib/module/components/Attachment/utils/getAspectRatio.js +5 -5
- package/lib/module/components/Attachment/utils/getAspectRatio.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +19 -14
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +4 -2
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js +43 -28
- package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js.map +1 -1
- package/lib/module/components/ImageGallery/ImageGallery.js +167 -345
- package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js +4 -4
- package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
- package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js +225 -0
- package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -0
- package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +102 -40
- package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +145 -0
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -0
- package/lib/module/components/ImageGallery/components/ImageGrid.js +31 -34
- package/lib/module/components/ImageGallery/components/ImageGrid.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ProgressControl.js +153 -0
- package/lib/module/components/ImageGallery/components/ProgressControl.js.map +1 -0
- package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js +373 -0
- package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -0
- package/lib/module/components/Message/Message.js +23 -13
- package/lib/module/components/Message/Message.js.map +1 -1
- package/lib/module/components/Message/hooks/useCreateMessageContext.js +4 -2
- package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
- package/lib/module/components/MessageOverlay/MessageOverlay.js +25 -23
- package/lib/module/components/MessageOverlay/MessageOverlay.js.map +1 -1
- package/lib/module/components/Reply/Reply.js +32 -12
- package/lib/module/components/Reply/Reply.js.map +1 -1
- package/lib/module/components/Spinner/Spinner.js +12 -4
- package/lib/module/components/Spinner/Spinner.js.map +1 -1
- package/lib/module/components/index.js +26 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/messageContext/MessageContext.js +2 -2
- package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
- package/lib/module/contexts/messageOverlayContext/MessageOverlayContext.js +2 -2
- package/lib/module/contexts/messageOverlayContext/MessageOverlayContext.js.map +1 -1
- package/lib/module/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +10 -1
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/icons/Pause.js +61 -0
- package/lib/module/icons/Pause.js.map +1 -0
- package/lib/module/icons/Play.js +42 -0
- package/lib/module/icons/Play.js.map +1 -0
- package/lib/module/icons/index.js +26 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/mock-builders/api/queryMembers.js +98 -1
- package/lib/module/mock-builders/api/queryMembers.js.map +1 -1
- package/lib/module/native.js +7 -1
- package/lib/module/native.js.map +1 -1
- package/lib/module/utils/getUrlOfImageAttachment.js +1 -1
- package/lib/module/utils/getUrlOfImageAttachment.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Attachment/Gallery.d.ts +1 -1
- package/lib/typescript/components/Attachment/VideoThumbnail.d.ts +4 -0
- package/lib/typescript/components/Attachment/utils/buildGallery/types.d.ts +1 -0
- package/lib/typescript/components/Attachment/utils/getAspectRatio.d.ts +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +1 -1
- package/lib/typescript/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayName.test.d.ts +1 -0
- package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewDisplayName.d.ts +4 -4
- package/lib/typescript/components/ImageGallery/ImageGallery.d.ts +2 -0
- package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts +27 -0
- package/lib/typescript/components/ImageGallery/components/ImageGalleryFooter.d.ts +18 -2
- package/lib/typescript/components/ImageGallery/components/ImageGalleryVideoControl.d.ts +3 -0
- package/lib/typescript/components/ImageGallery/components/ProgressControl.d.ts +5 -0
- package/lib/typescript/components/ImageGallery/hooks/useImageGalleryGestures.d.ts +36 -0
- package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts +1 -1
- package/lib/typescript/components/Spinner/Spinner.d.ts +7 -1
- package/lib/typescript/components/index.d.ts +2 -0
- package/lib/typescript/contexts/messageContext/MessageContext.d.ts +3 -1
- package/lib/typescript/contexts/messageOverlayContext/MessageOverlayContext.d.ts +1 -0
- package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +2 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +9 -0
- package/lib/typescript/icons/Pause.d.ts +3 -0
- package/lib/typescript/icons/Play.d.ts +3 -0
- package/lib/typescript/icons/index.d.ts +2 -0
- package/lib/typescript/mock-builders/api/queryMembers.d.ts +161 -0
- package/lib/typescript/mock-builders/api/utils.d.ts +7 -0
- package/lib/typescript/mock-builders/generator/user.d.ts +30 -0
- package/lib/typescript/mock-builders/mock.d.ts +3 -0
- package/lib/typescript/native.d.ts +66 -1
- package/package.json +1 -1
- package/src/components/Attachment/Attachment.tsx +11 -7
- package/src/components/Attachment/Gallery.tsx +75 -36
- package/src/components/Attachment/VideoThumbnail.tsx +45 -0
- package/src/components/Attachment/hooks/useGoToURL.ts +1 -1
- package/src/components/Attachment/utils/buildGallery/buildThumbnail.ts +1 -0
- package/src/components/Attachment/utils/buildGallery/types.ts +1 -0
- package/src/components/Attachment/utils/getAspectRatio.ts +7 -5
- package/src/components/Channel/Channel.tsx +4 -0
- package/src/components/Channel/hooks/useCreateMessagesContext.ts +2 -0
- package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayName.test.tsx +83 -0
- package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayName.ts +43 -26
- package/src/components/ImageGallery/ImageGallery.tsx +145 -667
- package/src/components/ImageGallery/components/AnimatedGalleryImage.tsx +4 -4
- package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx +224 -0
- package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +114 -19
- package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +103 -0
- package/src/components/ImageGallery/components/ImageGrid.tsx +12 -25
- package/src/components/ImageGallery/components/ProgressControl.tsx +107 -0
- package/src/components/ImageGallery/hooks/useImageGalleryGestures.tsx +722 -0
- package/src/components/Message/Message.tsx +10 -3
- package/src/components/Message/hooks/useCreateMessageContext.ts +2 -0
- package/src/components/MessageOverlay/MessageOverlay.tsx +2 -0
- package/src/components/Reply/Reply.tsx +36 -23
- package/src/components/Spinner/Spinner.tsx +11 -4
- package/src/components/index.ts +2 -0
- package/src/contexts/messageContext/MessageContext.tsx +2 -0
- package/src/contexts/messageOverlayContext/MessageOverlayContext.tsx +1 -0
- package/src/contexts/messagesContext/MessagesContext.tsx +2 -0
- package/src/contexts/themeContext/utils/theme.ts +18 -0
- package/src/icons/Pause.tsx +14 -0
- package/src/icons/Play.tsx +17 -0
- package/src/icons/index.ts +2 -0
- package/src/mock-builders/api/queryMembers.js +98 -0
- package/src/native.ts +59 -1
- package/src/utils/getUrlOfImageAttachment.ts +1 -1
- package/src/version.json +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stream-chat-react-native-core",
|
|
3
3
|
"description": "The official React Native and Expo components for Stream Chat, a service for building chat applications",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.7.0-beta.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"company": "Stream.io Inc",
|
|
7
7
|
"name": "Stream.io Inc"
|
|
@@ -75,17 +75,21 @@ const AttachmentWithContext = <
|
|
|
75
75
|
);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
if (attachment.type === '
|
|
79
|
-
return <FileAttachment attachment={attachment} />;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (attachment.type === 'video' && attachment.asset_url) {
|
|
78
|
+
if (attachment.type === 'video' && !attachment.og_scrape_url) {
|
|
83
79
|
return (
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
<>
|
|
81
|
+
<Gallery videos={[attachment]} />
|
|
82
|
+
{hasAttachmentActions && (
|
|
83
|
+
<AttachmentActions key={`key-actions-${attachment.id}`} {...attachment} />
|
|
84
|
+
)}
|
|
85
|
+
</>
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
if (attachment.type === 'file' || attachment.type === 'audio') {
|
|
90
|
+
return <FileAttachment attachment={attachment} />;
|
|
91
|
+
}
|
|
92
|
+
|
|
89
93
|
if (hasAttachmentActions) {
|
|
90
94
|
return (
|
|
91
95
|
<>
|
|
@@ -59,7 +59,7 @@ const styles = StyleSheet.create({
|
|
|
59
59
|
flexWrap: 'wrap',
|
|
60
60
|
overflow: 'hidden',
|
|
61
61
|
},
|
|
62
|
-
imageContainer: { padding: 1 },
|
|
62
|
+
imageContainer: { display: 'flex', flexDirection: 'row', justifyContent: 'center', padding: 1 },
|
|
63
63
|
moreImagesContainer: {
|
|
64
64
|
alignItems: 'center',
|
|
65
65
|
justifyContent: 'center',
|
|
@@ -76,6 +76,7 @@ export type GalleryPropsWithContext<
|
|
|
76
76
|
| 'alignment'
|
|
77
77
|
| 'groupStyles'
|
|
78
78
|
| 'images'
|
|
79
|
+
| 'videos'
|
|
79
80
|
| 'onLongPress'
|
|
80
81
|
| 'onPress'
|
|
81
82
|
| 'onPressIn'
|
|
@@ -84,7 +85,7 @@ export type GalleryPropsWithContext<
|
|
|
84
85
|
> &
|
|
85
86
|
Pick<
|
|
86
87
|
MessagesContextValue<StreamChatGenerics>,
|
|
87
|
-
'additionalTouchableProps' | 'legacyImageViewerSwipeBehaviour'
|
|
88
|
+
'additionalTouchableProps' | 'legacyImageViewerSwipeBehaviour' | 'VideoThumbnail'
|
|
88
89
|
> &
|
|
89
90
|
Pick<OverlayContextValue, 'setOverlay'> & {
|
|
90
91
|
channelId: string | undefined;
|
|
@@ -125,6 +126,8 @@ const GalleryWithContext = <
|
|
|
125
126
|
setImages,
|
|
126
127
|
setOverlay,
|
|
127
128
|
threadList,
|
|
129
|
+
videos,
|
|
130
|
+
VideoThumbnail,
|
|
128
131
|
} = props;
|
|
129
132
|
|
|
130
133
|
const {
|
|
@@ -158,16 +161,17 @@ const GalleryWithContext = <
|
|
|
158
161
|
minWidth,
|
|
159
162
|
};
|
|
160
163
|
|
|
164
|
+
const imagesAndVideos = [...(images || []), ...(videos || [])];
|
|
161
165
|
const { height, invertedDirections, thumbnailGrid, width } = useMemo(
|
|
162
166
|
() =>
|
|
163
167
|
buildGallery({
|
|
164
|
-
images,
|
|
168
|
+
images: imagesAndVideos,
|
|
165
169
|
sizeConfig,
|
|
166
170
|
}),
|
|
167
|
-
[
|
|
171
|
+
[imagesAndVideos.length],
|
|
168
172
|
);
|
|
169
173
|
|
|
170
|
-
if (!
|
|
174
|
+
if (!imagesAndVideos?.length) return null;
|
|
171
175
|
const messageText = message?.text;
|
|
172
176
|
const messageId = message?.id;
|
|
173
177
|
const numOfColumns = thumbnailGrid.length;
|
|
@@ -200,7 +204,7 @@ const GalleryWithContext = <
|
|
|
200
204
|
]}
|
|
201
205
|
testID={`gallery-${invertedDirections ? 'row' : 'column'}-${colIndex}`}
|
|
202
206
|
>
|
|
203
|
-
{rows.map(({ height, resizeMode, url, width }, rowIndex) => {
|
|
207
|
+
{rows.map(({ height, resizeMode, type, url, width }, rowIndex) => {
|
|
204
208
|
const defaultOnPress = () => {
|
|
205
209
|
// Added if-else to keep the logic readable, instead of DRY.
|
|
206
210
|
// if - legacyImageViewerSwipeBehaviour is disabled
|
|
@@ -214,11 +218,28 @@ const GalleryWithContext = <
|
|
|
214
218
|
setOverlay('gallery');
|
|
215
219
|
}
|
|
216
220
|
};
|
|
221
|
+
|
|
222
|
+
const borderRadius = getGalleryImageBorderRadius({
|
|
223
|
+
alignment,
|
|
224
|
+
colIndex,
|
|
225
|
+
groupStyles,
|
|
226
|
+
hasThreadReplies,
|
|
227
|
+
height,
|
|
228
|
+
invertedDirections,
|
|
229
|
+
messageText,
|
|
230
|
+
numOfColumns,
|
|
231
|
+
numOfRows,
|
|
232
|
+
rowIndex,
|
|
233
|
+
sizeConfig,
|
|
234
|
+
threadList,
|
|
235
|
+
width,
|
|
236
|
+
});
|
|
237
|
+
|
|
217
238
|
return (
|
|
218
239
|
<TouchableOpacity
|
|
219
240
|
activeOpacity={0.8}
|
|
220
241
|
disabled={preventPress}
|
|
221
|
-
key={`gallery-item-${messageId}/${colIndex}/${rowIndex}/${
|
|
242
|
+
key={`gallery-item-${messageId}/${colIndex}/${rowIndex}/${imagesAndVideos.length}`}
|
|
222
243
|
onLongPress={(event) => {
|
|
223
244
|
if (onLongPress) {
|
|
224
245
|
onLongPress({
|
|
@@ -258,35 +279,34 @@ const GalleryWithContext = <
|
|
|
258
279
|
}-${colIndex}-item-${rowIndex}`}
|
|
259
280
|
{...additionalTouchableProps}
|
|
260
281
|
>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
/>
|
|
282
|
+
{type === 'video' ? (
|
|
283
|
+
<VideoThumbnail
|
|
284
|
+
style={[
|
|
285
|
+
borderRadius,
|
|
286
|
+
image,
|
|
287
|
+
{
|
|
288
|
+
height: height - 1,
|
|
289
|
+
width: width - 1,
|
|
290
|
+
},
|
|
291
|
+
]}
|
|
292
|
+
/>
|
|
293
|
+
) : (
|
|
294
|
+
<MemoizedGalleryImage
|
|
295
|
+
resizeMode={resizeMode}
|
|
296
|
+
style={[
|
|
297
|
+
borderRadius,
|
|
298
|
+
image,
|
|
299
|
+
{
|
|
300
|
+
height: height - 1,
|
|
301
|
+
width: width - 1,
|
|
302
|
+
},
|
|
303
|
+
]}
|
|
304
|
+
uri={url}
|
|
305
|
+
/>
|
|
306
|
+
)}
|
|
287
307
|
{colIndex === numOfColumns - 1 &&
|
|
288
308
|
rowIndex === numOfRows - 1 &&
|
|
289
|
-
|
|
309
|
+
imagesAndVideos.length > 4 ? (
|
|
290
310
|
<View
|
|
291
311
|
style={[
|
|
292
312
|
StyleSheet.absoluteFillObject,
|
|
@@ -296,7 +316,7 @@ const GalleryWithContext = <
|
|
|
296
316
|
]}
|
|
297
317
|
>
|
|
298
318
|
<Text style={[styles.moreImagesText, moreImagesText]}>
|
|
299
|
-
{`+${
|
|
319
|
+
{`+${imagesAndVideos.length - 4}`}
|
|
300
320
|
</Text>
|
|
301
321
|
</View>
|
|
302
322
|
) : null}
|
|
@@ -319,12 +339,14 @@ const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = Default
|
|
|
319
339
|
hasThreadReplies: prevHasThreadReplies,
|
|
320
340
|
images: prevImages,
|
|
321
341
|
message: prevMessage,
|
|
342
|
+
videos: prevVideos,
|
|
322
343
|
} = prevProps;
|
|
323
344
|
const {
|
|
324
345
|
groupStyles: nextGroupStyles,
|
|
325
346
|
hasThreadReplies: nextHasThreadReplies,
|
|
326
347
|
images: nextImages,
|
|
327
348
|
message: nextMessage,
|
|
349
|
+
videos: nextVideos,
|
|
328
350
|
} = nextProps;
|
|
329
351
|
|
|
330
352
|
const messageEqual = prevMessage?.id === nextMessage?.id;
|
|
@@ -346,6 +368,15 @@ const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = Default
|
|
|
346
368
|
);
|
|
347
369
|
if (!imagesEqual) return false;
|
|
348
370
|
|
|
371
|
+
const videosEqual =
|
|
372
|
+
prevVideos.length === nextVideos.length &&
|
|
373
|
+
prevVideos.every(
|
|
374
|
+
(image, index) =>
|
|
375
|
+
getUrlWithoutParams(image.image_url) === getUrlWithoutParams(nextVideos[index].image_url) &&
|
|
376
|
+
getUrlWithoutParams(image.thumb_url) === getUrlWithoutParams(nextVideos[index].thumb_url),
|
|
377
|
+
);
|
|
378
|
+
if (!videosEqual) return false;
|
|
379
|
+
|
|
349
380
|
return true;
|
|
350
381
|
};
|
|
351
382
|
|
|
@@ -376,6 +407,8 @@ export const Gallery = <
|
|
|
376
407
|
setImage: propSetImage,
|
|
377
408
|
setOverlay: propSetOverlay,
|
|
378
409
|
threadList: propThreadList,
|
|
410
|
+
videos: propVideos,
|
|
411
|
+
VideoThumbnail: PropVideoThumbnail,
|
|
379
412
|
} = props;
|
|
380
413
|
|
|
381
414
|
const { setImage: contextSetImage, setImages } = useImageGalleryContext<StreamChatGenerics>();
|
|
@@ -389,16 +422,19 @@ export const Gallery = <
|
|
|
389
422
|
onPressIn: contextOnPressIn,
|
|
390
423
|
preventPress: contextPreventPress,
|
|
391
424
|
threadList: contextThreadList,
|
|
425
|
+
videos: contextVideos,
|
|
392
426
|
} = useMessageContext<StreamChatGenerics>();
|
|
393
427
|
const {
|
|
394
428
|
additionalTouchableProps: contextAdditionalTouchableProps,
|
|
395
429
|
legacyImageViewerSwipeBehaviour,
|
|
430
|
+
VideoThumbnail: ContextVideoThumnbnail,
|
|
396
431
|
} = useMessagesContext<StreamChatGenerics>();
|
|
397
432
|
const { setOverlay: contextSetOverlay } = useOverlayContext();
|
|
398
433
|
|
|
399
434
|
const images = propImages || contextImages;
|
|
435
|
+
const videos = propVideos || contextVideos;
|
|
400
436
|
|
|
401
|
-
if (!images.length) return null;
|
|
437
|
+
if (!images.length && !videos.length) return null;
|
|
402
438
|
|
|
403
439
|
const additionalTouchableProps = propAdditionalTouchableProps || contextAdditionalTouchableProps;
|
|
404
440
|
const alignment = propAlignment || contextAlignment;
|
|
@@ -411,6 +447,7 @@ export const Gallery = <
|
|
|
411
447
|
const setImage = propSetImage || contextSetImage;
|
|
412
448
|
const setOverlay = propSetOverlay || contextSetOverlay;
|
|
413
449
|
const threadList = propThreadList || contextThreadList;
|
|
450
|
+
const VideoThumbnail = PropVideoThumbnail || ContextVideoThumnbnail;
|
|
414
451
|
|
|
415
452
|
return (
|
|
416
453
|
<MemoizedGallery
|
|
@@ -431,6 +468,8 @@ export const Gallery = <
|
|
|
431
468
|
setImages,
|
|
432
469
|
setOverlay,
|
|
433
470
|
threadList,
|
|
471
|
+
videos,
|
|
472
|
+
VideoThumbnail,
|
|
434
473
|
}}
|
|
435
474
|
/>
|
|
436
475
|
);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet, View, ViewProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
|
|
5
|
+
import { Play } from '../../icons';
|
|
6
|
+
|
|
7
|
+
const styles = StyleSheet.create({
|
|
8
|
+
container: {
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
backgroundColor: 'black',
|
|
11
|
+
display: 'flex',
|
|
12
|
+
height: '100%',
|
|
13
|
+
justifyContent: 'center',
|
|
14
|
+
width: '100%',
|
|
15
|
+
},
|
|
16
|
+
roundedView: {
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
backgroundColor: '#fff',
|
|
19
|
+
borderRadius: 50,
|
|
20
|
+
display: 'flex',
|
|
21
|
+
height: 36,
|
|
22
|
+
justifyContent: 'center',
|
|
23
|
+
width: 36,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export type VideoThumbnailProps = ViewProps;
|
|
28
|
+
|
|
29
|
+
export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
|
|
30
|
+
const {
|
|
31
|
+
theme: {
|
|
32
|
+
messageSimple: {
|
|
33
|
+
videoThumbnail: { container, roundedView },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
} = useTheme();
|
|
37
|
+
const { style, ...rest } = props;
|
|
38
|
+
return (
|
|
39
|
+
<View {...rest} style={[styles.container, container, style]}>
|
|
40
|
+
<View style={[styles.roundedView, roundedView]}>
|
|
41
|
+
<Play height={24} pathFill={'#000'} width={24} />
|
|
42
|
+
</View>
|
|
43
|
+
</View>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -10,12 +10,14 @@ import type { DefaultStreamChatGenerics } from '../../../types/types';
|
|
|
10
10
|
*/
|
|
11
11
|
export function getAspectRatio<
|
|
12
12
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
13
|
-
>(
|
|
14
|
-
if (
|
|
15
|
-
throw new Error(
|
|
13
|
+
>(attachment: Attachment<StreamChatGenerics>) {
|
|
14
|
+
if (!(attachment.type === 'image' || attachment.type === 'video')) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
'getAspectRatio() can only be called on an image attachment or video thumbnail',
|
|
17
|
+
);
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
if (!
|
|
20
|
+
if (!attachment.original_width || !attachment.original_height) return 1;
|
|
19
21
|
|
|
20
|
-
return
|
|
22
|
+
return attachment.original_width / attachment.original_height;
|
|
21
23
|
}
|
|
@@ -82,6 +82,7 @@ import { FileAttachmentGroup as FileAttachmentGroupDefault } from '../Attachment
|
|
|
82
82
|
import { FileIcon as FileIconDefault } from '../Attachment/FileIcon';
|
|
83
83
|
import { Gallery as GalleryDefault } from '../Attachment/Gallery';
|
|
84
84
|
import { Giphy as GiphyDefault } from '../Attachment/Giphy';
|
|
85
|
+
import { VideoThumbnail as VideoThumbnailDefault } from '../Attachment/VideoThumbnail';
|
|
85
86
|
import { AutoCompleteSuggestionHeader as AutoCompleteSuggestionHeaderDefault } from '../AutoCompleteInput/AutoCompleteSuggestionHeader';
|
|
86
87
|
import { AutoCompleteSuggestionItem as AutoCompleteSuggestionItemDefault } from '../AutoCompleteInput/AutoCompleteSuggestionItem';
|
|
87
88
|
import { AutoCompleteSuggestionList as AutoCompleteSuggestionListDefault } from '../AutoCompleteInput/AutoCompleteSuggestionList';
|
|
@@ -287,6 +288,7 @@ export type ChannelPropsWithContext<
|
|
|
287
288
|
| 'TypingIndicator'
|
|
288
289
|
| 'TypingIndicatorContainer'
|
|
289
290
|
| 'UrlPreview'
|
|
291
|
+
| 'VideoThumbnail'
|
|
290
292
|
>
|
|
291
293
|
> &
|
|
292
294
|
Partial<
|
|
@@ -534,6 +536,7 @@ const ChannelWithContext = <
|
|
|
534
536
|
TypingIndicatorContainer = TypingIndicatorContainerDefault,
|
|
535
537
|
UploadProgressIndicator = UploadProgressIndicatorDefault,
|
|
536
538
|
UrlPreview = CardDefault,
|
|
539
|
+
VideoThumbnail = VideoThumbnailDefault,
|
|
537
540
|
watcherCount,
|
|
538
541
|
watchers,
|
|
539
542
|
} = props;
|
|
@@ -1738,6 +1741,7 @@ const ChannelWithContext = <
|
|
|
1738
1741
|
TypingIndicatorContainer,
|
|
1739
1742
|
updateMessage,
|
|
1740
1743
|
UrlPreview,
|
|
1744
|
+
VideoThumbnail,
|
|
1741
1745
|
});
|
|
1742
1746
|
|
|
1743
1747
|
const suggestionsContext = {
|
|
@@ -80,6 +80,7 @@ export const useCreateMessagesContext = <
|
|
|
80
80
|
TypingIndicatorContainer,
|
|
81
81
|
updateMessage,
|
|
82
82
|
UrlPreview,
|
|
83
|
+
VideoThumbnail,
|
|
83
84
|
}: MessagesContextValue<StreamChatGenerics> & {
|
|
84
85
|
/**
|
|
85
86
|
* To ensure we allow re-render, when channel is changed
|
|
@@ -166,6 +167,7 @@ export const useCreateMessagesContext = <
|
|
|
166
167
|
TypingIndicatorContainer,
|
|
167
168
|
updateMessage,
|
|
168
169
|
UrlPreview,
|
|
170
|
+
VideoThumbnail,
|
|
169
171
|
}),
|
|
170
172
|
[
|
|
171
173
|
additionalTouchablePropsLength,
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { render, waitFor } from '@testing-library/react-native';
|
|
5
|
+
|
|
6
|
+
import type { DefaultStreamChatGenerics } from 'src/types/types';
|
|
7
|
+
import type { Channel, ChannelMemberResponse, DefaultGenerics, StreamChat } from 'stream-chat';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
GROUP_CHANNEL_MEMBERS_MOCK,
|
|
11
|
+
ONE_CHANNEL_MEMBER_MOCK,
|
|
12
|
+
ONE_MEMBER_WITH_EMPTY_USER_MOCK,
|
|
13
|
+
} from '../../../../mock-builders/api/queryMembers';
|
|
14
|
+
import { generateUser } from '../../../../mock-builders/generator/user';
|
|
15
|
+
import { getTestClientWithUser } from '../../../../mock-builders/mock';
|
|
16
|
+
import {
|
|
17
|
+
getChannelPreviewDisplayName,
|
|
18
|
+
useChannelPreviewDisplayName,
|
|
19
|
+
} from '../useChannelPreviewDisplayName';
|
|
20
|
+
|
|
21
|
+
describe('useChannelPreviewDisplayName', () => {
|
|
22
|
+
const clientUser = generateUser();
|
|
23
|
+
let chatClient: StreamChat<DefaultGenerics> | StreamChat<DefaultStreamChatGenerics>;
|
|
24
|
+
const CHARACTER_LENGTH = 15;
|
|
25
|
+
|
|
26
|
+
beforeEach(async () => {
|
|
27
|
+
chatClient = await getTestClientWithUser(clientUser);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return a channel display name', async () => {
|
|
31
|
+
const channelName = 'okechukwu';
|
|
32
|
+
|
|
33
|
+
const TestComponent = () => {
|
|
34
|
+
const channelDisplayName = useChannelPreviewDisplayName(
|
|
35
|
+
{
|
|
36
|
+
data: { name: channelName },
|
|
37
|
+
} as unknown as Channel<DefaultGenerics>,
|
|
38
|
+
CHARACTER_LENGTH,
|
|
39
|
+
);
|
|
40
|
+
return <Text>{channelDisplayName}</Text>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const { getByText } = render(<TestComponent />);
|
|
44
|
+
|
|
45
|
+
await waitFor(() => {
|
|
46
|
+
expect(getByText(channelName)).toBeTruthy();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should return the full channelName when channelName length is less than characterLength', () => {
|
|
51
|
+
const channelName = 'okechukwu';
|
|
52
|
+
const currentUserId = chatClient.userID;
|
|
53
|
+
|
|
54
|
+
const displayName = getChannelPreviewDisplayName({
|
|
55
|
+
channelName,
|
|
56
|
+
characterLimit: CHARACTER_LENGTH,
|
|
57
|
+
currentUserId,
|
|
58
|
+
members: ONE_CHANNEL_MEMBER_MOCK,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(displayName).toEqual(channelName);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it.each([
|
|
65
|
+
[CHARACTER_LENGTH, GROUP_CHANNEL_MEMBERS_MOCK, 'okechukwu nwagba', 'ben, nick, q,...+2'],
|
|
66
|
+
[CHARACTER_LENGTH, ONE_CHANNEL_MEMBER_MOCK, 'okechukwu nwagba', 'okechukwu nw...'],
|
|
67
|
+
[CHARACTER_LENGTH, ONE_MEMBER_WITH_EMPTY_USER_MOCK, 'okechukwu nwagba', 'Unknown User...'],
|
|
68
|
+
])(
|
|
69
|
+
'getChannelPreviewDisplayName(%i, %p, %s) result in %s',
|
|
70
|
+
(characterLength, members, currentUserId, expected) => {
|
|
71
|
+
const displayName = getChannelPreviewDisplayName({
|
|
72
|
+
characterLimit: characterLength,
|
|
73
|
+
currentUserId,
|
|
74
|
+
members: members as unknown as Record<
|
|
75
|
+
string,
|
|
76
|
+
ChannelMemberResponse<DefaultStreamChatGenerics>
|
|
77
|
+
>,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
expect(displayName).toEqual(expected);
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
});
|
|
@@ -1,48 +1,66 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import type { Channel } from 'stream-chat';
|
|
3
|
+
import type { Channel, ChannelMemberResponse } from 'stream-chat';
|
|
4
4
|
|
|
5
5
|
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
|
|
6
6
|
|
|
7
7
|
import type { DefaultStreamChatGenerics } from '../../../types/types';
|
|
8
8
|
import { vw } from '../../../utils/utils';
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const DEFAULT_MAX_CHARACTER_LENGTH = (vw(100) - 16) / 6;
|
|
11
|
+
|
|
12
|
+
const ELLIPSIS = `...`;
|
|
13
|
+
|
|
14
|
+
const getMemberName = (member: ChannelMemberResponse) =>
|
|
15
|
+
member.user?.name || member.user?.id || 'Unknown User';
|
|
11
16
|
|
|
12
17
|
export const getChannelPreviewDisplayName = <
|
|
13
18
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
14
19
|
>({
|
|
15
20
|
channelName,
|
|
21
|
+
characterLimit,
|
|
16
22
|
currentUserId,
|
|
17
|
-
maxCharacterLength,
|
|
18
23
|
members,
|
|
19
24
|
}: {
|
|
20
|
-
|
|
25
|
+
characterLimit: number;
|
|
21
26
|
channelName?: string;
|
|
22
27
|
currentUserId?: string;
|
|
23
28
|
members?: Channel<StreamChatGenerics>['state']['members'];
|
|
24
|
-
}) => {
|
|
29
|
+
}): string => {
|
|
25
30
|
if (channelName) return channelName;
|
|
26
31
|
|
|
27
32
|
const channelMembers = Object.values(members || {});
|
|
33
|
+
|
|
28
34
|
const otherMembers = channelMembers.filter((member) => member.user?.id !== currentUserId);
|
|
35
|
+
otherMembers.sort((prevUser, nextUser) =>
|
|
36
|
+
(prevUser?.user?.name ?? '')
|
|
37
|
+
.toLowerCase()
|
|
38
|
+
.localeCompare((nextUser?.user?.name ?? '').toLocaleUpperCase()),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const createChannelNameSuffix = (remainingNumberOfMembers: number) =>
|
|
42
|
+
remainingNumberOfMembers <= 1 ? `${ELLIPSIS}` : `,${ELLIPSIS}+${remainingNumberOfMembers}`;
|
|
29
43
|
|
|
30
|
-
const name = otherMembers.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
const name = otherMembers.reduce((result, currentMember, index, originalArray) => {
|
|
45
|
+
if (result.length >= characterLimit) {
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const currentMemberName = getMemberName(currentMember);
|
|
50
|
+
|
|
51
|
+
const resultHasSpaceForCurrentMemberName =
|
|
52
|
+
result.length + (currentMemberName.length + ELLIPSIS.length) < characterLimit;
|
|
53
|
+
if (resultHasSpaceForCurrentMemberName) {
|
|
54
|
+
return result.length > 0 ? `${result}, ${currentMemberName}, ` : currentMemberName;
|
|
40
55
|
} else {
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
const remainingNumberOfMembers = originalArray.length - index;
|
|
57
|
+
const truncateLimit = characterLimit - (ELLIPSIS.length + result.length);
|
|
58
|
+
const tuncatedCurrentMemberName = `${currentMemberName.slice(0, truncateLimit)}`;
|
|
59
|
+
|
|
60
|
+
const channelNameSuffix = createChannelNameSuffix(remainingNumberOfMembers);
|
|
61
|
+
|
|
62
|
+
return `${result}${tuncatedCurrentMemberName}${channelNameSuffix}`;
|
|
44
63
|
}
|
|
45
|
-
return returnString;
|
|
46
64
|
}, '');
|
|
47
65
|
|
|
48
66
|
return name;
|
|
@@ -56,17 +74,16 @@ export const useChannelPreviewDisplayName = <
|
|
|
56
74
|
) => {
|
|
57
75
|
const { client } = useChatContext<StreamChatGenerics>();
|
|
58
76
|
|
|
59
|
-
const currentUserId = client
|
|
60
|
-
const members = channel?.state
|
|
77
|
+
const currentUserId = client?.userID;
|
|
78
|
+
const members = channel?.state?.members;
|
|
61
79
|
const numOfMembers = Object.keys(members || {}).length;
|
|
62
80
|
const channelName = channel?.data?.name;
|
|
63
|
-
const
|
|
64
|
-
|
|
81
|
+
const characterLimit = characterLength || DEFAULT_MAX_CHARACTER_LENGTH;
|
|
65
82
|
const [displayName, setDisplayName] = useState(
|
|
66
83
|
getChannelPreviewDisplayName({
|
|
67
84
|
channelName,
|
|
85
|
+
characterLimit,
|
|
68
86
|
currentUserId,
|
|
69
|
-
maxCharacterLength,
|
|
70
87
|
members,
|
|
71
88
|
}),
|
|
72
89
|
);
|
|
@@ -75,12 +92,12 @@ export const useChannelPreviewDisplayName = <
|
|
|
75
92
|
setDisplayName(
|
|
76
93
|
getChannelPreviewDisplayName({
|
|
77
94
|
channelName,
|
|
95
|
+
characterLimit,
|
|
78
96
|
currentUserId,
|
|
79
|
-
maxCharacterLength,
|
|
80
97
|
members,
|
|
81
98
|
}),
|
|
82
99
|
);
|
|
83
|
-
}, [channelName, currentUserId,
|
|
100
|
+
}, [channelName, currentUserId, characterLimit, numOfMembers]);
|
|
84
101
|
|
|
85
102
|
return displayName;
|
|
86
103
|
};
|