From 6c56d5a5f1a0f56d4b67c7a8d0cce34dea41f0f2 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Thu, 24 Jun 2021 14:00:11 -0700 Subject: [PATCH] Fix UI for GIFs in groups --- stylesheets/_modules.scss | 16 ++- ts/components/conversation/Image.tsx | 8 +- ts/components/conversation/ImageGrid.tsx | 66 +++++++----- .../conversation/Message.stories.tsx | 100 +++++++++++------- ts/components/conversation/Message.tsx | 4 +- ts/types/Attachment.ts | 19 +++- 6 files changed, 137 insertions(+), 76 deletions(-) diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index d5599b8509..5d2da3dec1 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -3938,7 +3938,6 @@ button.module-conversation-details__action-button { .module-image { position: relative; display: inline-block; - margin: 1px; vertical-align: middle; overflow: hidden; } @@ -4061,6 +4060,10 @@ button.module-conversation-details__action-button { border-radius: 4px; } +.module-image--cropped { + overflow: hidden; +} + .module-image--curved-top-left { border-top-left-radius: 16px; } @@ -4105,8 +4108,6 @@ button.module-conversation-details__action-button { } .module-image--gif { - border-radius: 18px; - &__filesize { position: absolute; top: 10px; @@ -4279,7 +4280,7 @@ button.module-image__border-overlay:focus { flex-direction: row; align-items: center; - margin: -1px; + gap: 1px; } .module-image-grid--one-image { @@ -4294,6 +4295,7 @@ button.module-image__border-overlay:focus { display: inline-flex; flex-direction: column; align-items: center; + gap: 1px; } .module-image-grid__row { @@ -4301,6 +4303,7 @@ button.module-image__border-overlay:focus { flex-direction: row; align-items: center; flex-grow: 1; + gap: 1px; } // Module: Typing Animation @@ -10621,11 +10624,6 @@ $contact-modal-padding: 18px; &--deleted-for-everyone { font-style: italic; } - - &--gif { - border-radius: inherit; - background: inherit; - } } .module-message__context { diff --git a/ts/components/conversation/Image.tsx b/ts/components/conversation/Image.tsx index 2052adfb90..9dc8ef616a 100644 --- a/ts/components/conversation/Image.tsx +++ b/ts/components/conversation/Image.tsx @@ -20,6 +20,8 @@ export type Props = { height?: number; width?: number; + cropWidth?: number; + cropHeight?: number; tabIndex?: number; overlayText?: string; @@ -158,6 +160,8 @@ export class Image extends React.Component { theme, url, width = 0, + cropWidth = 0, + cropHeight = 0, } = this.props; const { caption, pending } = attachment || { caption: null, pending: true }; @@ -204,8 +208,10 @@ export class Image extends React.Component { curveTopLeft ? 'module-image--curved-top-left' : null, curveTopRight ? 'module-image--curved-top-right' : null, smallCurveTopLeft ? 'module-image--small-curved-top-left' : null, - softCorners ? 'module-image--soft-corners' : null + softCorners ? 'module-image--soft-corners' : null, + cropWidth || cropHeight ? 'module-image--cropped' : null )} + style={{ width: width - cropWidth, height: height - cropHeight }} > {pending ? ( this.renderPending() diff --git a/ts/components/conversation/ImageGrid.tsx b/ts/components/conversation/ImageGrid.tsx index 7fc0bb7a78..83e122c2b0 100644 --- a/ts/components/conversation/ImageGrid.tsx +++ b/ts/components/conversation/ImageGrid.tsx @@ -34,6 +34,8 @@ export type Props = { onClick?: (attachment: AttachmentType) => void; }; +const GAP = 1; + export const ImageGrid = ({ attachments, bottomOverlay, @@ -113,8 +115,9 @@ export const ImageGrid = ({ curveTopLeft={curveTopLeft} curveBottomLeft={curveBottomLeft} playIconOverlay={isVideoAttachment(attachments[0])} - height={149} - width={149} + height={150} + width={150} + cropWidth={GAP} url={getThumbnailUrl(attachments[0])} onClick={onClick} onError={onError} @@ -129,8 +132,8 @@ export const ImageGrid = ({ curveTopRight={curveTopRight} curveBottomRight={curveBottomRight} playIconOverlay={isVideoAttachment(attachments[1])} - height={149} - width={149} + height={150} + width={150} attachment={attachments[1]} url={getThumbnailUrl(attachments[1])} onClick={onClick} @@ -155,7 +158,8 @@ export const ImageGrid = ({ attachment={attachments[0]} playIconOverlay={isVideoAttachment(attachments[0])} height={200} - width={199} + width={200} + cropWidth={GAP} url={getUrl(attachments[0])} onClick={onClick} onError={onError} @@ -167,8 +171,9 @@ export const ImageGrid = ({ theme={theme} blurHash={attachments[1].blurHash} curveTopRight={curveTopRight} - height={99} - width={99} + height={100} + width={100} + cropHeight={GAP} attachment={attachments[1]} playIconOverlay={isVideoAttachment(attachments[1])} url={getThumbnailUrl(attachments[1])} @@ -183,8 +188,8 @@ export const ImageGrid = ({ bottomOverlay={withBottomOverlay} noBorder={false} curveBottomRight={curveBottomRight} - height={99} - width={99} + height={100} + width={100} attachment={attachments[2]} playIconOverlay={isVideoAttachment(attachments[2])} url={getThumbnailUrl(attachments[2])} @@ -210,8 +215,10 @@ export const ImageGrid = ({ noBorder={false} attachment={attachments[0]} playIconOverlay={isVideoAttachment(attachments[0])} - height={149} - width={149} + height={150} + width={150} + cropHeight={GAP} + cropWidth={GAP} url={getThumbnailUrl(attachments[0])} onClick={onClick} onError={onError} @@ -224,8 +231,9 @@ export const ImageGrid = ({ curveTopRight={curveTopRight} playIconOverlay={isVideoAttachment(attachments[1])} noBorder={false} - height={149} - width={149} + height={150} + width={150} + cropHeight={GAP} attachment={attachments[1]} url={getThumbnailUrl(attachments[1])} onClick={onClick} @@ -242,8 +250,9 @@ export const ImageGrid = ({ noBorder={false} curveBottomLeft={curveBottomLeft} playIconOverlay={isVideoAttachment(attachments[2])} - height={149} - width={149} + height={150} + width={150} + cropWidth={GAP} attachment={attachments[2]} url={getThumbnailUrl(attachments[2])} onClick={onClick} @@ -258,8 +267,8 @@ export const ImageGrid = ({ noBorder={false} curveBottomRight={curveBottomRight} playIconOverlay={isVideoAttachment(attachments[3])} - height={149} - width={149} + height={150} + width={150} attachment={attachments[3]} url={getThumbnailUrl(attachments[3])} onClick={onClick} @@ -288,8 +297,9 @@ export const ImageGrid = ({ curveTopLeft={curveTopLeft} attachment={attachments[0]} playIconOverlay={isVideoAttachment(attachments[0])} - height={149} - width={149} + height={150} + width={150} + cropWidth={GAP} url={getThumbnailUrl(attachments[0])} onClick={onClick} onError={onError} @@ -301,8 +311,8 @@ export const ImageGrid = ({ blurHash={attachments[1].blurHash} curveTopRight={curveTopRight} playIconOverlay={isVideoAttachment(attachments[1])} - height={149} - width={149} + height={150} + width={150} attachment={attachments[1]} url={getThumbnailUrl(attachments[1])} onClick={onClick} @@ -319,8 +329,9 @@ export const ImageGrid = ({ noBorder={isSticker} curveBottomLeft={curveBottomLeft} playIconOverlay={isVideoAttachment(attachments[2])} - height={99} - width={99} + height={100} + width={100} + cropWidth={GAP} attachment={attachments[2]} url={getThumbnailUrl(attachments[2])} onClick={onClick} @@ -334,8 +345,9 @@ export const ImageGrid = ({ bottomOverlay={withBottomOverlay} noBorder={isSticker} playIconOverlay={isVideoAttachment(attachments[3])} - height={99} - width={98} + height={100} + width={100} + cropWidth={GAP} attachment={attachments[3]} url={getThumbnailUrl(attachments[3])} onClick={onClick} @@ -350,8 +362,8 @@ export const ImageGrid = ({ noBorder={isSticker} curveBottomRight={curveBottomRight} playIconOverlay={isVideoAttachment(attachments[4])} - height={99} - width={99} + height={100} + width={100} darkOverlay={moreMessagesOverlay} overlayText={moreMessagesOverlayText} attachment={attachments[4]} diff --git a/ts/components/conversation/Message.stories.tsx b/ts/components/conversation/Message.stories.tsx index 0424bd5ec4..7c330acbea 100644 --- a/ts/components/conversation/Message.stories.tsx +++ b/ts/components/conversation/Message.stories.tsx @@ -720,43 +720,52 @@ story.add('Image', () => { return renderBothDirections(props); }); -story.add('Multiple Images', () => { - const props = createProps({ - attachments: [ - { - url: '/fixtures/tina-rolf-269345-unsplash.jpg', - fileName: 'tina-rolf-269345-unsplash.jpg', - contentType: IMAGE_JPEG, - width: 128, - height: 128, - }, - { - url: '/fixtures/tina-rolf-269345-unsplash.jpg', - fileName: 'tina-rolf-269345-unsplash.jpg', - contentType: IMAGE_JPEG, - width: 128, - height: 128, - }, - { - url: '/fixtures/tina-rolf-269345-unsplash.jpg', - fileName: 'tina-rolf-269345-unsplash.jpg', - contentType: IMAGE_JPEG, - width: 128, - height: 128, - }, - { - url: '/fixtures/tina-rolf-269345-unsplash.jpg', - fileName: 'tina-rolf-269345-unsplash.jpg', - contentType: IMAGE_JPEG, - width: 128, - height: 128, - }, - ], - status: 'sent', - }); +for (let i = 2; i <= 5; i += 1) { + story.add(`Multiple Images x${i}`, () => { + const props = createProps({ + attachments: [ + { + url: '/fixtures/tina-rolf-269345-unsplash.jpg', + fileName: 'tina-rolf-269345-unsplash.jpg', + contentType: IMAGE_JPEG, + width: 128, + height: 128, + }, + { + url: '/fixtures/tina-rolf-269345-unsplash.jpg', + fileName: 'tina-rolf-269345-unsplash.jpg', + contentType: IMAGE_JPEG, + width: 128, + height: 128, + }, + { + url: '/fixtures/tina-rolf-269345-unsplash.jpg', + fileName: 'tina-rolf-269345-unsplash.jpg', + contentType: IMAGE_JPEG, + width: 128, + height: 128, + }, + { + url: '/fixtures/tina-rolf-269345-unsplash.jpg', + fileName: 'tina-rolf-269345-unsplash.jpg', + contentType: IMAGE_JPEG, + width: 128, + height: 128, + }, + { + url: '/fixtures/tina-rolf-269345-unsplash.jpg', + fileName: 'tina-rolf-269345-unsplash.jpg', + contentType: IMAGE_JPEG, + width: 128, + height: 128, + }, + ].slice(0, i), + status: 'sent', + }); - return renderBothDirections(props); -}); + return renderBothDirections(props); + }); +} story.add('Image with Caption', () => { const props = createProps({ @@ -794,6 +803,25 @@ story.add('GIF', () => { return renderBothDirections(props); }); +story.add('GIF in a group', () => { + const props = createProps({ + attachments: [ + { + contentType: VIDEO_MP4, + flags: SignalService.AttachmentPointer.Flags.GIF, + fileName: 'cat-gif.mp4', + url: '/fixtures/cat-gif.mp4', + width: 400, + height: 332, + }, + ], + conversationType: 'group', + status: 'sent', + }); + + return renderBothDirections(props); +}); + story.add('Not Downloaded GIF', () => { const props = createProps({ attachments: [ diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 2c11fcb257..2826b1a9ae 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -1662,8 +1662,8 @@ export class Message extends React.Component { if (attachments && attachments.length) { if (isGIF(attachments)) { - // Message container border + image border - return GIF_SIZE + 4; + // Message container border + return GIF_SIZE + 2; } if (isSticker) { diff --git a/ts/types/Attachment.ts b/ts/types/Attachment.ts index 1faff2ff15..ae8ad86a33 100644 --- a/ts/types/Attachment.ts +++ b/ts/types/Attachment.ts @@ -280,21 +280,38 @@ export function getGridDimensions( } if (attachments.length === 2) { + // A B return { height: 150, width: 300, }; } + if (attachments.length === 3) { + // A A B + // A A C + return { + height: 200, + width: 300, + }; + } + if (attachments.length === 4) { + // A B + // C D return { height: 300, width: 300, }; } + // A A A B B B + // A A A B B B + // A A A B B B + // C C D D E E + // C C D D E E return { - height: 200, + height: 250, width: 300, }; }