Skip to content

Commit 5d3f90b

Browse files
committed
fix: make sure single videos behave like single images
1 parent 9863e65 commit 5d3f90b

File tree

6 files changed

+88
-17
lines changed

6 files changed

+88
-17
lines changed

package/src/components/Attachment/Gallery.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export type GalleryPropsWithContext = Pick<ImageGalleryContextValue, 'imageGalle
6464
> &
6565
Pick<OverlayContextValue, 'setOverlay'> & {
6666
channelId: string | undefined;
67-
messageHasOnlyOneImage: boolean;
67+
messageHasOnlyOneMedia: boolean;
6868
};
6969

7070
const GalleryWithContext = (props: GalleryPropsWithContext) => {
@@ -83,7 +83,7 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => {
8383
setOverlay,
8484
videos,
8585
VideoThumbnail,
86-
messageHasOnlyOneImage = false,
86+
messageHasOnlyOneMedia = false,
8787
} = props;
8888

8989
const { resizableCDNHosts } = useChatConfigContext();
@@ -144,7 +144,7 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => {
144144
flexDirection: invertedDirections ? 'column' : 'row',
145145
alignSelf: alignment === 'right' ? 'flex-end' : 'flex-start',
146146
},
147-
images.length !== 1
147+
imagesAndVideos.length !== 1
148148
? { width: gridWidth, height: gridHeight }
149149
: {
150150
minHeight: height,
@@ -178,7 +178,7 @@ const GalleryWithContext = (props: GalleryPropsWithContext) => {
178178
rowIndex,
179179
sizeConfig,
180180
width,
181-
messageHasOnlyOneImage,
181+
messageHasOnlyOneMedia,
182182
});
183183

184184
if (!message) {
@@ -542,6 +542,7 @@ export const Gallery = (props: GalleryProps) => {
542542

543543
const images = propImages || contextImages;
544544
const videos = propVideos || contextVideos;
545+
const imagesAndVideos = [...images, ...videos];
545546
const message = propMessage || contextMessage;
546547
const alignment = propAlignment || contextAlignment;
547548
if (!images.length && !videos.length) {
@@ -562,10 +563,10 @@ export const Gallery = (props: GalleryProps) => {
562563
const myMessageTheme = propMyMessageTheme || contextMyMessageTheme;
563564
const messageContentOrder = propMessageContentOrder || contextMessageContentOrder;
564565

565-
const messageHasOnlyOneImage =
566+
const messageHasOnlyOneMedia =
566567
messageContentOrder?.length === 1 &&
567568
messageContentOrder?.includes('gallery') &&
568-
images.length === 1;
569+
imagesAndVideos.length === 1;
569570

570571
return (
571572
<MemoizedGallery
@@ -586,7 +587,7 @@ export const Gallery = (props: GalleryProps) => {
586587
setOverlay,
587588
videos,
588589
VideoThumbnail,
589-
messageHasOnlyOneImage,
590+
messageHasOnlyOneMedia,
590591
messageContentOrder,
591592
}}
592593
/>

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import { StyleSheet } from 'react-native';
23

34
import { fireEvent, render, screen, waitFor } from '@testing-library/react-native';
45

@@ -99,6 +100,27 @@ describe('Gallery', () => {
99100
});
100101
});
101102

103+
it('should use single-media sizing for a single video attachment', async () => {
104+
const attachment = generateVideoAttachment({
105+
original_height: 300,
106+
original_width: 600,
107+
});
108+
const component = await getComponent([attachment]);
109+
render(component);
110+
111+
await waitFor(() => {
112+
expect(screen.queryAllByTestId('gallery-container').length).toBe(1);
113+
expect(screen.getAllByLabelText('Video Thumbnail').length).toBe(1);
114+
});
115+
116+
const containerStyle = StyleSheet.flatten(screen.getByTestId('gallery-container').props.style);
117+
118+
expect(containerStyle.width).toBeUndefined();
119+
expect(containerStyle.height).toBeUndefined();
120+
expect(containerStyle.minWidth).toBe(256);
121+
expect(containerStyle.minHeight).toBe(128);
122+
});
123+
102124
it('should render portrait and landscape image in two rows', async () => {
103125
const attachment1 = generateImageAttachment({
104126
original_height: 600,

package/src/components/Attachment/utils/getGalleryImageBorderRadius.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Params = {
1818
height?: number;
1919
invertedDirections?: boolean;
2020
width?: number;
21-
messageHasOnlyOneImage?: boolean;
21+
messageHasOnlyOneMedia?: boolean;
2222
};
2323

2424
export function getGalleryImageBorderRadius({
@@ -30,7 +30,7 @@ export function getGalleryImageBorderRadius({
3030
rowIndex,
3131
sizeConfig,
3232
width,
33-
messageHasOnlyOneImage = false,
33+
messageHasOnlyOneMedia = false,
3434
}: Params) {
3535
const isSingleImage = numOfColumns === 1 && numOfRows === 1;
3636
const isImageSmallerThanMinContainerSize =
@@ -51,12 +51,12 @@ export function getGalleryImageBorderRadius({
5151
return {
5252
borderTopLeftRadius: !isImageSmallerThanMinContainerSize && topLeftEdgeExposed ? 12 : 8,
5353
borderTopRightRadius: !isImageSmallerThanMinContainerSize && topRightEdgeExposed ? 12 : 8,
54-
borderBottomLeftRadius: messageHasOnlyOneImage
54+
borderBottomLeftRadius: messageHasOnlyOneMedia
5555
? primitives.radiusNone
5656
: !isImageSmallerThanMinContainerSize && bottomLeftEdgeExposed
5757
? primitives.radiusLg
5858
: primitives.radiusMd,
59-
borderBottomRightRadius: messageHasOnlyOneImage
59+
borderBottomRightRadius: messageHasOnlyOneMedia
6060
? primitives.radiusNone
6161
: !isImageSmallerThanMinContainerSize && bottomRightEdgeExposed
6262
? primitives.radiusLg

package/src/components/Message/Message.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
438438
isVideoPlayerAvailable()
439439
) {
440440
acc.videos.push({
441+
...cur,
441442
image_url: cur.asset_url,
442443
thumb_url: cur.thumb_url,
443444
type: FileTypes.Video,

package/src/components/Message/MessageSimple/MessageContent.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ export const MessageContent = (props: MessageContentProps) => {
546546
threadList,
547547
files,
548548
images,
549+
videos,
549550
} = useMessageContext();
550551
const {
551552
additionalPressableProps,
@@ -562,10 +563,10 @@ export const MessageContent = (props: MessageContentProps) => {
562563
const { t } = useTranslationContext();
563564
const isSingleFile = files.length === 1;
564565
const messageHasPoll = messageContentOrder.includes('poll');
565-
const messageHasSingleImage =
566+
const messageHasSingleMedia =
566567
messageContentOrder.length === 1 &&
567568
messageContentOrder.includes('gallery') &&
568-
images.length === 1;
569+
images.length + videos.length === 1;
569570
const messageHasSingleFile =
570571
messageContentOrder.length === 1 && messageContentOrder[0] === 'files' && isSingleFile;
571572
const messageHasOnlyText = messageContentOrder.length === 1 && messageContentOrder[0] === 'text';
@@ -576,17 +577,17 @@ export const MessageContent = (props: MessageContentProps) => {
576577

577578
const hidePaddingTop =
578579
messageHasPoll ||
579-
messageHasSingleImage ||
580+
messageHasSingleMedia ||
580581
messageHasSingleFile ||
581582
messageHasOnlyText ||
582583
messageHasGiphyOrImgur;
583584

584585
const hidePaddingHorizontal =
585-
messageHasPoll || messageHasSingleImage || messageHasSingleFile || messageHasGiphyOrImgur;
586+
messageHasPoll || messageHasSingleMedia || messageHasSingleFile || messageHasGiphyOrImgur;
586587

587588
const hidePaddingBottom =
588589
messageHasPoll ||
589-
messageHasSingleImage ||
590+
messageHasSingleMedia ||
590591
messageHasSingleFile ||
591592
messageHasOnlyText ||
592593
messageHasGiphyOrImgur ||

package/src/components/Message/MessageSimple/__tests__/MessageContent.test.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React, { useEffect } from 'react';
2-
import { View } from 'react-native';
2+
import { StyleSheet, View } from 'react-native';
33

44
import { cleanup, render, screen, waitFor } from '@testing-library/react-native';
55

66
import { ChannelsStateProvider } from '../../../../contexts/channelsStateContext/ChannelsStateContext';
77

88
import { getOrCreateChannelApi } from '../../../../mock-builders/api/getOrCreateChannel';
99
import { useMockedApis } from '../../../../mock-builders/api/useMockedApis';
10+
import { generateVideoAttachment } from '../../../../mock-builders/generator/attachment';
1011
import { generateChannelResponse } from '../../../../mock-builders/generator/channel';
1112
import { generateMember } from '../../../../mock-builders/generator/member';
1213
import { generateMessage } from '../../../../mock-builders/generator/message';
@@ -182,6 +183,51 @@ describe('MessageContent', () => {
182183
});
183184
});
184185

186+
it('removes content padding for a single video attachment', async () => {
187+
const user = generateUser();
188+
const message = generateMessage({
189+
attachments: [
190+
generateVideoAttachment({
191+
original_height: 300,
192+
original_width: 600,
193+
}),
194+
],
195+
html: '',
196+
text: '',
197+
user,
198+
});
199+
200+
renderMessage({ message });
201+
202+
await waitFor(() => {
203+
expect(screen.getByTestId('message-content-wrapper')).toBeTruthy();
204+
expect(screen.getByTestId('gallery-container')).toBeTruthy();
205+
});
206+
207+
const galleryContainer = screen.getByTestId('gallery-container');
208+
let ancestor = galleryContainer.parent;
209+
let contentContainerStyle;
210+
211+
while (ancestor && !contentContainerStyle) {
212+
const flattenedStyle = StyleSheet.flatten(ancestor.props.style);
213+
if (
214+
flattenedStyle &&
215+
'paddingTop' in flattenedStyle &&
216+
'paddingHorizontal' in flattenedStyle &&
217+
'paddingBottom' in flattenedStyle
218+
) {
219+
contentContainerStyle = flattenedStyle;
220+
break;
221+
}
222+
ancestor = ancestor.parent;
223+
}
224+
225+
expect(contentContainerStyle).toBeTruthy();
226+
expect(contentContainerStyle.paddingTop).toBe(0);
227+
expect(contentContainerStyle.paddingHorizontal).toBe(0);
228+
expect(contentContainerStyle.paddingBottom).toBe(0);
229+
});
230+
185231
it('renders the FileAttachment component when a file attachment exists', async () => {
186232
const user = generateUser();
187233
const message = generateMessage({

0 commit comments

Comments
 (0)