Skip to content

Commit 12caa9d

Browse files
authored
Merge pull request #1439 from GetStream/khushal87-issue-1236
feat: replace static video thumbnails with actual thumbnails
2 parents afc059c + 4b83be4 commit 12caa9d

29 files changed

+1563
-45
lines changed

docusaurus/docs/reactnative/ui-components/video_thumbnail.mdx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,14 @@ id: video-thumbnail
33
title: Video Thumbnail
44
---
55

6-
`VideoThumbnail` is a default UI component for rendering video thumbnail for video attachments within `MessageList`. This component doesn't accept any props.
6+
`VideoThumbnail` is a default UI component for rendering video thumbnail for video attachments within `MessageList`.
7+
8+
## Props
9+
10+
### thumb_url
11+
12+
The thumbnail URL to be displayed for the video.
13+
14+
| Type |
15+
| ------ |
16+
| string |

examples/ExpoMessaging/yarn.lock

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,27 @@
16821682
xcode "^3.0.1"
16831683
xml2js "0.4.23"
16841684

1685+
"@expo/config-plugins@^4.0.14":
1686+
version "4.1.5"
1687+
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-4.1.5.tgz#9d357d2cda9c095e511b51583ede8a3b76174068"
1688+
integrity sha512-RVvU40RtZt12HavuDAe+LDIq9lHj7sheOfMEHdmpJ/uTA8pgvkbc56XF6JHQD+yRr6+uhhb+JnAasGq49dsQbw==
1689+
dependencies:
1690+
"@expo/config-types" "^45.0.0"
1691+
"@expo/json-file" "8.2.36"
1692+
"@expo/plist" "0.0.18"
1693+
"@expo/sdk-runtime-versions" "^1.0.0"
1694+
"@react-native/normalize-color" "^2.0.0"
1695+
chalk "^4.1.2"
1696+
debug "^4.3.1"
1697+
find-up "~5.0.0"
1698+
getenv "^1.0.0"
1699+
glob "7.1.6"
1700+
resolve-from "^5.0.0"
1701+
semver "^7.3.5"
1702+
slash "^3.0.0"
1703+
xcode "^3.0.1"
1704+
xml2js "0.4.23"
1705+
16851706
"@expo/config-types@^43.0.1":
16861707
version "43.0.1"
16871708
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-43.0.1.tgz#3e047dccb371741a540980eaff26fb0c95039c30"
@@ -1692,6 +1713,11 @@
16921713
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-44.0.0.tgz#d3480fe2c99f9e895dae4ebba58b74ed72d03e26"
16931714
integrity sha512-d+gpdKOAhqaD5RmcMzGgKzNtvE1w+GCqpFQNSXLliYlXjj+Tv0eL8EPeAdPtvke0vowpPFwd5McXLA90dgY6Jg==
16941715

1716+
"@expo/config-types@^45.0.0":
1717+
version "45.0.0"
1718+
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-45.0.0.tgz#963c2fdce8fbcbd003758b92ed8a25375f437ef6"
1719+
integrity sha512-/QGhhLWyaGautgEyU50UJr5YqKJix5t77ePTwreOVAhmZH+ff3nrrtYTTnccx+qF08ZNQmfAyYMCD3rQfzpiJA==
1720+
16951721
"@expo/[email protected]", "@expo/config@^6.0.6":
16961722
version "6.0.19"
16971723
resolved "https://registry.yarnpkg.com/@expo/config/-/config-6.0.19.tgz#26a7f7ffb6419cc6e6d4205b3c7764aa9ecb551a"
@@ -1775,6 +1801,15 @@
17751801
json5 "^1.0.1"
17761802
write-file-atomic "^2.3.0"
17771803

1804+
1805+
version "8.2.36"
1806+
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.36.tgz#62a505cb7f30a34d097386476794680a3f7385ff"
1807+
integrity sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ==
1808+
dependencies:
1809+
"@babel/code-frame" "~7.10.4"
1810+
json5 "^1.0.1"
1811+
write-file-atomic "^2.3.0"
1812+
17781813
"@expo/metro-config@~0.2.6":
17791814
version "0.2.8"
17801815
resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.2.8.tgz#c0fd56723e2fb9bb352e788e8f8fe0e218aaf663"
@@ -1804,6 +1839,15 @@
18041839
base64-js "^1.2.3"
18051840
xmlbuilder "^14.0.0"
18061841

1842+
1843+
version "0.0.18"
1844+
resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.18.tgz#9abcde78df703a88f6d9fa1a557ee2f045d178b0"
1845+
integrity sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w==
1846+
dependencies:
1847+
"@xmldom/xmldom" "~0.7.0"
1848+
base64-js "^1.2.3"
1849+
xmlbuilder "^14.0.0"
1850+
18071851
"@expo/prebuild-config@^3.0.15":
18081852
version "3.1.0"
18091853
resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-3.1.0.tgz#9fa10f12745ecaa6d3d4957ba97142edb8747a85"
@@ -3478,6 +3522,13 @@ expo-asset@~8.4.6:
34783522
path-browserify "^1.0.0"
34793523
url-parse "^1.4.4"
34803524

3525+
expo-av@~10.2.0:
3526+
version "10.2.1"
3527+
resolved "https://registry.yarnpkg.com/expo-av/-/expo-av-10.2.1.tgz#c08bce464d673d0e90c68cac082bfb75a9437f25"
3528+
integrity sha512-thrkHVg4HVn8L+jHKVnXYd4TLkJQblFE8QXd3d1hwrYG63gehQT2nK4DM0Frl50EcdV8YN9XjhwHobtK5oMc9A==
3529+
dependencies:
3530+
"@expo/config-plugins" "^4.0.2"
3531+
34813532
expo-blur@~11.0.0:
34823533
version "11.0.0"
34833534
resolved "https://registry.yarnpkg.com/expo-blur/-/expo-blur-11.0.0.tgz#3542afed5c0037554657d98c31a5933dd78098dd"
@@ -6660,6 +6711,21 @@ [email protected]:
66606711
jsonwebtoken "^8.5.1"
66616712
ws "^7.4.4"
66626713

6714+
6715+
version "6.7.0"
6716+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-6.7.0.tgz#1add1e612f0009f9e7a69d35f2a2fae1296d85ef"
6717+
integrity sha512-usH/kh0ZjbjOP8TTlsbXS53UZRUmwP0r1dOYf0jrQg3HPfwG51iTkrXGNlzPF9ueNXkPB8ObSm7bcdVRoo+4bg==
6718+
dependencies:
6719+
"@babel/runtime" "^7.16.3"
6720+
"@types/jsonwebtoken" "^8.5.6"
6721+
"@types/ws" "^7.4.0"
6722+
axios "^0.22.0"
6723+
base64-js "^1.5.1"
6724+
form-data "^4.0.0"
6725+
isomorphic-ws "^4.0.1"
6726+
jsonwebtoken "^8.5.1"
6727+
ws "^7.4.4"
6728+
66636729
strict-uri-encode@^2.0.0:
66646730
version "2.0.0"
66656731
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"

examples/SampleApp/yarn.lock

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7433,10 +7433,10 @@ [email protected]:
74337433
resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"
74347434
integrity sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=
74357435

7436-
stream-chat-react-native-core@4.3.1:
7437-
version "4.3.1"
7438-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-4.3.1.tgz#bc53a044c45b60f6bd3feb425e70100d077cc064"
7439-
integrity sha512-2DZO89EyDtXtmc5MhivD1kOOU6aklK/rgZVvo4RZ15419VlpVFqMjswvFAcF41z2ZJujP86cSSKg5YMhNy7uZw==
7436+
stream-chat-react-native-core@4.7.0:
7437+
version "4.7.0"
7438+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-4.7.0.tgz#2ac5fe04f8b57e70b5832feca7e5843554aa9944"
7439+
integrity sha512-6dIHzmoIxNaA9BTxV6mjjfSSUkivVe8Rv8BkNAsyh0u6fhQP5K7aBw+bdhDZ+w/bDjQp/Col0j1UPjNVkh2TWw==
74407440
dependencies:
74417441
"@babel/runtime" "^7.12.5"
74427442
"@gorhom/bottom-sheet" "4.1.5"
@@ -7475,6 +7475,21 @@ [email protected]:
74757475
jsonwebtoken "^8.5.1"
74767476
ws "^7.4.4"
74777477

7478+
7479+
version "6.7.0"
7480+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-6.7.0.tgz#1add1e612f0009f9e7a69d35f2a2fae1296d85ef"
7481+
integrity sha512-usH/kh0ZjbjOP8TTlsbXS53UZRUmwP0r1dOYf0jrQg3HPfwG51iTkrXGNlzPF9ueNXkPB8ObSm7bcdVRoo+4bg==
7482+
dependencies:
7483+
"@babel/runtime" "^7.16.3"
7484+
"@types/jsonwebtoken" "^8.5.6"
7485+
"@types/ws" "^7.4.0"
7486+
axios "^0.22.0"
7487+
base64-js "^1.5.1"
7488+
form-data "^4.0.0"
7489+
isomorphic-ws "^4.0.1"
7490+
jsonwebtoken "^8.5.1"
7491+
ws "^7.4.4"
7492+
74787493
strict-uri-encode@^2.0.0:
74797494
version "2.0.0"
74807495
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"

examples/TypeScriptMessaging/yarn.lock

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6944,6 +6944,21 @@ [email protected]:
69446944
jsonwebtoken "^8.5.1"
69456945
ws "^7.4.4"
69466946

6947+
6948+
version "6.7.0"
6949+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-6.7.0.tgz#1add1e612f0009f9e7a69d35f2a2fae1296d85ef"
6950+
integrity sha512-usH/kh0ZjbjOP8TTlsbXS53UZRUmwP0r1dOYf0jrQg3HPfwG51iTkrXGNlzPF9ueNXkPB8ObSm7bcdVRoo+4bg==
6951+
dependencies:
6952+
"@babel/runtime" "^7.16.3"
6953+
"@types/jsonwebtoken" "^8.5.6"
6954+
"@types/ws" "^7.4.0"
6955+
axios "^0.22.0"
6956+
base64-js "^1.5.1"
6957+
form-data "^4.0.0"
6958+
isomorphic-ws "^4.0.1"
6959+
jsonwebtoken "^8.5.1"
6960+
ws "^7.4.4"
6961+
69476962
strict-uri-encode@^2.0.0:
69486963
version "2.0.0"
69496964
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"

package/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,34 @@
8080
"react-art": "^17.0.2",
8181
"react-native-markdown-package": "1.8.1",
8282
"react-native-url-polyfill": "^1.3.0",
83-
"stream-chat": "6.2.0"
83+
"stream-chat": "6.7.0"
8484
},
8585
"peerDependencies": {
8686
"react-native-svg": "^12.1.0"
8787
},
8888
"devDependencies": {
8989
"@babel/cli": "^7.12.17",
9090
"@babel/core": "^7.12.9",
91-
"@babel/runtime": "^7.12.5",
9291
"@babel/plugin-proposal-object-rest-spread": "7.13.8",
9392
"@babel/plugin-transform-runtime": "7.13.10",
9493
"@babel/polyfill": "7.12.1",
9594
"@babel/preset-env": "7.13.12",
9695
"@babel/preset-typescript": "7.13.0",
96+
"@babel/runtime": "^7.12.5",
9797
"@react-native-community/eslint-config": "2.0.0",
9898
"@react-native-community/eslint-plugin": "1.1.0",
9999
"@react-native-community/netinfo": "6.0.0",
100100
"@testing-library/jest-native": "4.0.4",
101-
"@testing-library/react-native": "9.0.0",
102101
"@testing-library/react-hooks": "7.0.2",
102+
"@testing-library/react-native": "9.0.0",
103103
"@types/eslint": "7.2.10",
104104
"@types/jest": "26.0.23",
105105
"@types/lodash": "4.14.169",
106106
"@types/mime-types": "2.1.0",
107107
"@types/react": "17.0.5",
108108
"@types/react-native": "0.67.3",
109109
"@types/react-test-renderer": "17.0.1",
110+
"@types/uuid": "^8.3.4",
110111
"@typescript-eslint/eslint-plugin": "^5.7.0",
111112
"@typescript-eslint/parser": "^5.7.0",
112113
"babel-eslint": "10.1.0",

package/src/components/Attachment/Gallery.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ const GalleryWithContext = <
212212
]}
213213
testID={`gallery-${invertedDirections ? 'row' : 'column'}-${colIndex}`}
214214
>
215-
{rows.map(({ height, resizeMode, type, url, width }, rowIndex) => {
215+
{rows.map(({ height, resizeMode, thumb_url, type, url, width }, rowIndex) => {
216216
const openImageViewer = () => {
217217
if (!legacyImageViewerSwipeBehaviour && message) {
218218
// Added if-else to keep the logic readable, instead of DRY.
@@ -307,6 +307,7 @@ const GalleryWithContext = <
307307
width: width - 1,
308308
},
309309
]}
310+
thumb_url={thumb_url}
310311
/>
311312
) : (
312313
<View style={styles.imageContainerStyle}>

package/src/components/Attachment/VideoThumbnail.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { StyleSheet, View, ViewProps } from 'react-native';
2+
import { ImageBackground, StyleSheet, View, ViewProps } from 'react-native';
33

44
import { useTheme } from '../../contexts/themeContext/ThemeContext';
55
import { Play } from '../../icons';
@@ -24,7 +24,9 @@ const styles = StyleSheet.create({
2424
},
2525
});
2626

27-
export type VideoThumbnailProps = ViewProps;
27+
export type VideoThumbnailProps = ViewProps & {
28+
thumb_url?: string;
29+
};
2830

2931
export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
3032
const {
@@ -34,12 +36,17 @@ export const VideoThumbnail: React.FC<VideoThumbnailProps> = (props) => {
3436
},
3537
},
3638
} = useTheme();
37-
const { style, ...rest } = props;
39+
const { style, thumb_url, ...rest } = props;
3840
return (
39-
<View {...rest} style={[styles.container, container, style]}>
41+
<ImageBackground
42+
accessibilityLabel='video-thumbnail'
43+
source={{ uri: thumb_url }}
44+
{...rest}
45+
style={[styles.container, container, style]}
46+
>
4047
<View style={[styles.roundedView, roundedView]}>
4148
<Play height={24} pathFill={'#000'} width={24} />
4249
</View>
43-
</View>
50+
</ImageBackground>
4451
);
4552
};

package/src/components/Attachment/__tests__/Attachment.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
generateAudioAttachment,
1212
generateFileAttachment,
1313
generateImageAttachment,
14+
generateVideoAttachment,
1415
} from '../../../mock-builders/generator/attachment';
1516
import { generateMessage } from '../../../mock-builders/generator/message';
17+
import * as NativeUtils from '../../../native';
1618

1719
import { ImageLoadingFailedIndicator } from '../../Attachment/ImageLoadingFailedIndicator';
1820
import { ImageLoadingIndicator } from '../../Attachment/ImageLoadingIndicator';
@@ -47,6 +49,16 @@ describe('Attachment', () => {
4749
});
4850
});
4951

52+
it('should render File component for "video" type attachment', async () => {
53+
jest.spyOn(NativeUtils, 'isVideoPackageAvailable').mockImplementation(jest.fn(() => false));
54+
const attachment = generateVideoAttachment();
55+
const { getByTestId } = render(getAttachmentComponent({ attachment }));
56+
57+
await waitFor(() => {
58+
expect(getByTestId('file-attachment')).toBeTruthy();
59+
});
60+
});
61+
5062
it('should render File component for "file" type attachment', async () => {
5163
const attachment = generateFileAttachment();
5264
const { getByTestId } = render(getAttachmentComponent({ attachment }));

package/src/components/Attachment/__tests__/Gallery.test.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ import { OverlayProvider } from '../../../contexts/overlayContext/OverlayProvide
1111

1212
import { getOrCreateChannelApi } from '../../../mock-builders/api/getOrCreateChannel';
1313
import { useMockedApis } from '../../../mock-builders/api/useMockedApis';
14-
import { generateImageAttachment } from '../../../mock-builders/generator/attachment';
14+
import {
15+
generateImageAttachment,
16+
generateVideoAttachment,
17+
} from '../../../mock-builders/generator/attachment';
1518
import { generateChannelResponse } from '../../../mock-builders/generator/channel';
1619
import { generateMember } from '../../../mock-builders/generator/member';
1720
import { generateMessage } from '../../../mock-builders/generator/message';
1821
import { generateUser } from '../../../mock-builders/generator/user';
1922
import { getTestClientWithUser } from '../../../mock-builders/mock';
23+
import * as NativeUtils from '../../../native';
2024
import { Channel } from '../../Channel/Channel';
2125
import { Chat } from '../../Chat/Chat';
2226
import { MessageList } from '../../MessageList/MessageList';
@@ -75,6 +79,24 @@ describe('Gallery', () => {
7579
});
7680
});
7781

82+
it('should render one image and one video attachment', async () => {
83+
jest.spyOn(NativeUtils, 'isVideoPackageAvailable').mockImplementation(jest.fn(() => true));
84+
const attachment1 = generateImageAttachment({
85+
original_height: 600,
86+
original_width: 400,
87+
});
88+
const attachment2 = generateVideoAttachment();
89+
const component = await getComponent([attachment1, attachment2]);
90+
const { getAllByA11yLabel, queryAllByTestId } = render(component);
91+
92+
await waitFor(() => {
93+
expect(queryAllByTestId('gallery-row-0').length).toBe(1);
94+
95+
expect(queryAllByTestId('gallery-row-0-item-0').length).toBe(1);
96+
expect(getAllByA11yLabel('video-thumbnail').length).toBe(1);
97+
});
98+
});
99+
78100
it('should render portrait and landscape image in two rows', async () => {
79101
const attachment1 = generateImageAttachment({
80102
original_height: 600,

package/src/components/Attachment/utils/buildGallery/buildThumbnail.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export function buildThumbnail<
3636
resizeMode: resizeMode
3737
? resizeMode
3838
: ((image.original_height && image.original_width ? 'contain' : 'cover') as ImageResizeMode),
39+
thumb_url: image.thumb_url,
3940
type: image.type,
4041
url: shouldResize
4142
? getResizedImageUrl({

0 commit comments

Comments
 (0)