feat: move attachments outside of the message box

pull/2459/head
Audric Ackermann
parent d512f6911d
commit 7c80f9e233

@ -27,7 +27,7 @@
margin: 4px 16px;
padding: 4px;
border-radius: 15px;
border-radius: $border-radius-message-box;
align-self: flex-start;

@ -145,17 +145,13 @@
.module-message__link-preview {
cursor: pointer;
border-top-left-radius: $session_message-container-border-radius;
border-top-right-radius: $session_message-container-border-radius;
}
.module-message__link-preview__content {
padding: 8px;
background-color: $color-white;
display: flex;
flex-direction: row;
align-items: flex-start;
border: 1px solid $color-black-015;
}
.module-message__link-preview__image_container {
@ -208,7 +204,6 @@
}
.module-message__link-preview__title {
color: $color-gray-90;
font-size: 16px;
font-weight: 300;
letter-spacing: 0.15px;
@ -222,7 +217,6 @@
.module-message__link-preview__location {
margin-top: 4px;
color: $color-gray-60;
font-size: 12px;
height: 16px;
letter-spacing: 0.4px;
@ -787,7 +781,7 @@
}
.module-image--soft-corners {
border-radius: 4px;
border-radius: $border-radius-message-box;
}
.module-image__border-overlay {
@ -819,21 +813,6 @@
}
}
.module-image__bottom-overlay {
height: 48px;
background-image: linear-gradient(
to bottom,
rgba(0, 0, 0, 0),
rgba(0, 0, 0, 0) 9%,
rgba(0, 0, 0, 0.6)
);
position: absolute;
bottom: 0;
z-index: 1;
left: 0;
right: 0;
}
.module-image__play-overlay__circle {
position: absolute;
top: 50%;
@ -885,29 +864,6 @@
background-image: url('../images/x-shadow-16.svg');
}
// Module: Image Grid
.module-image-grid {
display: inline-flex;
flex-direction: row;
align-items: center;
margin: -1px;
}
.module-image-grid__column {
display: inline-flex;
flex-direction: column;
align-items: center;
}
.module-image-grid__row {
display: inline-flex;
flex-direction: row;
align-items: center;
flex-grow: 1;
}
// Module: Typing Animation
.module-typing-animation {

@ -20,6 +20,7 @@
&--outgoing {
.module-quote__primary__author {
color: var(--color-sent-message-text);
font-weight: bold;
.module-contact-name {
@ -38,6 +39,7 @@
&--incoming {
.module-quote__primary__author {
color: var(--color-received-message-text);
font-weight: bold;
.module-contact-name {
font-weight: bold;

@ -345,11 +345,6 @@ label {
text-align: center;
position: relative;
overflow: hidden;
border-top-left-radius: $session_message-container-border-radius;
border-bottom-left-radius: $session_message-container-border-radius;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.conversation-header {

@ -216,8 +216,6 @@ $session-modal-size-sm: 220px;
$session-modal-size-md: 400px;
$session-modal-size-lg: 650px;
$session_message-container-border-radius: 13px;
// Spacing
$session-margin-xs: 5px;
$session-margin-sm: 10px;
@ -241,3 +239,6 @@ $session-transition-duration: 0.25s;
// //////////////////////////////////////////////
$composition-container-height: 60px;
$padding-message-content: 7px 13px; // FIXME to move to SessionTheme
$border-radius-message-box: 16px; // FIXME to move to SessionTheme

@ -348,6 +348,9 @@ $rhap_font-family: inherit !default;
padding: 0px;
background-color: transparent;
box-shadow: none;
background: var(--color-accent);
padding: $padding-message-content;
border-radius: $border-radius-message-box;
svg {
transition: fill $session-transition-duration;

@ -6,6 +6,22 @@
background: var(--color-cell-background);
}
.module-message__container {
.module-message__text {
font-size: 14px;
line-height: 18px;
text-align: start;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-word;
white-space: pre-wrap;
a {
text-decoration: underline;
}
}
}
.module-message {
position: relative;
display: inline-flex;
@ -26,22 +42,18 @@
word-break: break-word;
white-space: pre-wrap;
padding: $padding-message-content;
border-radius: $border-radius-message-box;
a {
text-decoration: underline;
}
}
&__container--incoming {
&--opaque {
background: var(--color-received-message-background);
}
&--transparent {
background: none;
}
color: var(--color-received-message-text);
.module-message__text {
color: var(--color-received-message-text);
display: flex;
flex-direction: row;
align-items: center;
@ -52,26 +64,17 @@
a {
text-decoration: underline;
color: var(--color-received-message-text);
color: inherit;
}
}
}
color: var(--color-sent-message-text);
&__container--outgoing {
&--opaque {
background: var(--color-sent-message-background);
}
&--transparent {
background: none;
}
.module-message__text {
color: var(--color-sent-message-text);
a {
text-decoration: underline;
color: var(--color-sent-message-text);
color: inherit;
}
}
}

@ -16,7 +16,6 @@ type Props = {
overlayText?: string;
bottomOverlay?: boolean;
closeButton?: boolean;
darkOverlay?: boolean;
@ -35,7 +34,6 @@ export const Image = (props: Props) => {
const {
alt,
attachment,
bottomOverlay,
closeButton,
darkOverlay,
height,
@ -154,7 +152,6 @@ export const Image = (props: Props) => {
className="module-image__close-button"
/>
) : null}
{bottomOverlay ? <div className={classNames('module-image__bottom-overlay')} /> : null}
{!(pending || loading) && playIconOverlay ? (
<div className="module-image__play-overlay__circle">
<div className="module-image__play-overlay__icon" />

@ -1,263 +1,142 @@
import React, { useContext } from 'react';
import classNames from 'classnames';
import {
areAllAttachmentsVisual,
AttachmentType,
AttachmentTypeWithPath,
getAlt,
getImageDimensionsInAttachment,
getThumbnailUrl,
isVideoAttachment,
} from '../../types/Attachment';
import { Image } from './Image';
import { IsMessageVisibleContext } from './message/message-content/MessageContent';
import styled from 'styled-components';
import { THUMBNAIL_SIDE } from '../../types/attachments/VisualAttachment';
type Props = {
attachments: Array<AttachmentTypeWithPath>;
bottomOverlay?: boolean;
onError: () => void;
onClickAttachment?: (attachment: AttachmentTypeWithPath | AttachmentType) => void;
};
const StyledImageGrid = styled.div`
display: inline-flex;
flex-direction: row;
align-items: center;
gap: var(--margins-sm);
`;
const StyledImageGridColumn = styled.div`
display: inline-flex;
flex-direction: column;
align-items: center;
gap: var(--margins-sm);
`;
// tslint:disable: cyclomatic-complexity max-func-body-length use-simple-attributes
export const ImageGrid = (props: Props) => {
const { attachments, bottomOverlay, onError, onClickAttachment } = props;
const { attachments, onError, onClickAttachment } = props;
const isMessageVisible = useContext(IsMessageVisibleContext);
const withBottomOverlay = Boolean(bottomOverlay);
if (!attachments || !attachments.length) {
return null;
}
if (attachments.length === 1 || !areAllAttachmentsVisual(attachments)) {
const { height, width } = getImageDimensionsInAttachment(attachments[0]);
const shared = {
onClick: onClickAttachment,
onError: onError,
softCorners: true,
};
if (attachments.length === 1 || !areAllAttachmentsVisual(attachments)) {
return (
<div className={classNames('module-image-grid', 'module-image-grid--one-image')}>
<StyledImageGrid>
<Image
alt={getAlt(attachments[0])}
bottomOverlay={withBottomOverlay}
attachment={attachments[0]}
playIconOverlay={isVideoAttachment(attachments[0])}
height={height}
width={width}
height={THUMBNAIL_SIDE}
width={THUMBNAIL_SIDE}
url={isMessageVisible ? getThumbnailUrl(attachments[0]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={0}
{...shared}
/>
</div>
</StyledImageGrid>
);
}
if (attachments.length === 2) {
// when we got 2 attachments we render them side by side with the full size of THUMBNAIL_SIDE
return (
<div className="module-image-grid">
<StyledImageGrid>
<Image
alt={getAlt(attachments[0])}
attachment={attachments[0]}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[0])}
height={149}
width={149}
height={THUMBNAIL_SIDE}
width={THUMBNAIL_SIDE}
url={isMessageVisible ? getThumbnailUrl(attachments[0]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={0}
{...shared}
/>
<Image
alt={getAlt(attachments[1])}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[1])}
height={149}
width={149}
height={THUMBNAIL_SIDE}
width={THUMBNAIL_SIDE}
attachment={attachments[1]}
url={isMessageVisible ? getThumbnailUrl(attachments[1]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={1}
{...shared}
/>
</div>
</StyledImageGrid>
);
}
if (attachments.length === 3) {
return (
<div className="module-image-grid">
<Image
alt={getAlt(attachments[0])}
bottomOverlay={withBottomOverlay}
attachment={attachments[0]}
playIconOverlay={isVideoAttachment(attachments[0])}
height={200}
width={199}
url={isMessageVisible ? getThumbnailUrl(attachments[0]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={0}
/>
<div className="module-image-grid__column">
<Image
alt={getAlt(attachments[1])}
height={99}
width={99}
attachment={attachments[1]}
playIconOverlay={isVideoAttachment(attachments[1])}
url={isMessageVisible ? getThumbnailUrl(attachments[1]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={1}
/>
<Image
alt={getAlt(attachments[2])}
bottomOverlay={withBottomOverlay}
height={99}
width={99}
attachment={attachments[2]}
playIconOverlay={isVideoAttachment(attachments[2])}
url={isMessageVisible ? getThumbnailUrl(attachments[2]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={2}
/>
</div>
</div>
);
}
const moreMessagesOverlay = attachments.length > 3;
const moreMessagesOverlayText = moreMessagesOverlay ? `+${attachments.length - 3}` : undefined;
if (attachments.length === 4) {
return (
<div className="module-image-grid">
<div className="module-image-grid__column">
<div className="module-image-grid__row">
<Image
alt={getAlt(attachments[0])}
attachment={attachments[0]}
playIconOverlay={isVideoAttachment(attachments[0])}
height={149}
width={149}
url={isMessageVisible ? getThumbnailUrl(attachments[0]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={0}
/>
<Image
alt={getAlt(attachments[1])}
playIconOverlay={isVideoAttachment(attachments[1])}
height={149}
width={149}
attachment={attachments[1]}
url={isMessageVisible ? getThumbnailUrl(attachments[1]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={1}
/>
</div>
<div className="module-image-grid__row">
<Image
alt={getAlt(attachments[2])}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[2])}
height={149}
width={149}
attachment={attachments[2]}
url={isMessageVisible ? getThumbnailUrl(attachments[2]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={2}
/>
<Image
alt={getAlt(attachments[3])}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[3])}
height={149}
width={149}
attachment={attachments[3]}
url={isMessageVisible ? getThumbnailUrl(attachments[3]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={3}
/>
</div>
</div>
</div>
);
}
const moreMessagesOverlay = attachments.length > 5;
const moreMessagesOverlayText = moreMessagesOverlay ? `+${attachments.length - 5}` : undefined;
const columnImageSide = THUMBNAIL_SIDE / 2 - 5;
// we know only support having 3 attachments displayed at most.
return (
<div className="module-image-grid">
<div className="module-image-grid__column">
<div className="module-image-grid__row">
<Image
alt={getAlt(attachments[0])}
attachment={attachments[0]}
playIconOverlay={isVideoAttachment(attachments[0])}
height={149}
width={149}
url={isMessageVisible ? getThumbnailUrl(attachments[0]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={0}
/>
<Image
alt={getAlt(attachments[1])}
playIconOverlay={isVideoAttachment(attachments[1])}
height={149}
width={149}
attachment={attachments[1]}
url={isMessageVisible ? getThumbnailUrl(attachments[1]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={1}
/>
</div>
<div className="module-image-grid__row">
<Image
alt={getAlt(attachments[2])}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[2])}
height={99}
width={99}
attachment={attachments[2]}
url={isMessageVisible ? getThumbnailUrl(attachments[2]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={2}
/>
<Image
alt={getAlt(attachments[3])}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[3])}
height={99}
width={98}
attachment={attachments[3]}
url={isMessageVisible ? getThumbnailUrl(attachments[3]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={3}
/>
<Image
alt={getAlt(attachments[4])}
bottomOverlay={withBottomOverlay}
playIconOverlay={isVideoAttachment(attachments[4])}
height={99}
width={99}
darkOverlay={moreMessagesOverlay}
overlayText={moreMessagesOverlayText}
attachment={attachments[4]}
url={isMessageVisible ? getThumbnailUrl(attachments[4]) : undefined}
onClick={onClickAttachment}
onError={onError}
attachmentIndex={4}
/>
</div>
</div>
</div>
<StyledImageGrid>
<Image
alt={getAlt(attachments[0])}
attachment={attachments[0]}
playIconOverlay={isVideoAttachment(attachments[0])}
height={THUMBNAIL_SIDE}
width={THUMBNAIL_SIDE}
url={isMessageVisible ? getThumbnailUrl(attachments[0]) : undefined}
attachmentIndex={0}
{...shared}
/>
<StyledImageGridColumn>
<Image
alt={getAlt(attachments[1])}
height={columnImageSide}
width={columnImageSide}
attachment={attachments[1]}
playIconOverlay={isVideoAttachment(attachments[1])}
url={isMessageVisible ? getThumbnailUrl(attachments[1]) : undefined}
attachmentIndex={1}
{...shared}
/>
<Image
alt={getAlt(attachments[2])}
height={columnImageSide}
width={columnImageSide}
attachment={attachments[2]}
playIconOverlay={isVideoAttachment(attachments[2])}
url={isMessageVisible ? getThumbnailUrl(attachments[2]) : undefined}
attachmentIndex={2}
darkOverlay={moreMessagesOverlay}
overlayText={moreMessagesOverlayText}
{...shared}
/>
</StyledImageGridColumn>
</StyledImageGrid>
);
};

@ -4,27 +4,16 @@ import React, { createContext, useCallback, useContext, useLayoutEffect, useStat
import { InView } from 'react-intersection-observer';
import { useSelector } from 'react-redux';
import { isEmpty } from 'lodash';
import { MessageRenderingProps } from '../../../../models/messageType';
import { MessageModelType, MessageRenderingProps } from '../../../../models/messageType';
import {
getMessageContentSelectorProps,
getMessageTextProps,
getQuotedMessageToAnimate,
getShouldHighlightMessage,
} from '../../../../state/selectors/conversations';
import {
canDisplayImage,
getGridDimensions,
getImageDimensionsInAttachment,
hasImage,
hasVideoScreenshot,
isImage,
isImageAttachment,
isVideo,
} from '../../../../types/Attachment';
import { Flex } from '../../../basic/Flex';
import { MINIMUM_LINK_PREVIEW_IMAGE_WIDTH } from '../message-item/Message';
import { MessageAttachment } from './MessageAttachment';
import { MessagePreview } from './MessagePreview';
import { MessageLinkPreview } from './MessageLinkPreview';
import { MessageQuote } from './MessageQuote';
import { MessageText } from './MessageText';
import { ScrollToLoadedMessageContext } from '../../SessionMessagesListContainer';
@ -40,40 +29,6 @@ type Props = {
isDetailView?: boolean;
};
function getIsShowingImage(
props: Pick<MessageRenderingProps, 'attachments' | 'previews' | 'text'> & { imageBroken: boolean }
): boolean {
const { attachments, previews, text, imageBroken } = props;
if (imageBroken) {
return false;
}
if (attachments && attachments.length) {
const displayImage = canDisplayImage(attachments);
const hasText = text?.length;
return Boolean(
displayImage &&
!hasText &&
((isImage(attachments) && hasImage(attachments)) ||
(isVideo(attachments) && hasVideoScreenshot(attachments)))
);
}
if (previews && previews.length) {
const first = previews[0];
const { image } = first;
if (!image) {
return false;
}
return isImageAttachment(image);
}
return false;
}
function onClickOnMessageInnerContainer(event: React.MouseEvent<HTMLDivElement>) {
const selection = window.getSelection();
// Text is being selected
@ -88,11 +43,17 @@ function onClickOnMessageInnerContainer(event: React.MouseEvent<HTMLDivElement>)
}
}
const StyledMessageContent = styled.div`
border-radius: 18px;
const StyledMessageOpaqueContent = styled.div<{ messageDirection: MessageModelType }>`
background: ${props =>
props.messageDirection === 'incoming'
? 'var(--color-received-message-background)'
: 'var(--color-sent-message-background)'};
padding: 7px 13px; // FIXME
border-radius: 16px; //FIXME
`;
export const IsMessageVisibleContext = createContext(false);
// tslint:disable: use-simple-attributes
export const MessageContent = (props: Props) => {
const [flashGreen, setFlashGreen] = useState(false);
@ -151,15 +112,7 @@ export const MessageContent = (props: Props) => {
return null;
}
const {
direction,
text,
timestamp,
serverTimestamp,
previews,
quote,
attachments,
} = contentProps;
const { direction, text, timestamp, serverTimestamp, previews } = contentProps;
const selectedMsg = useSelector(state => getMessageTextProps(state as any, props.messageId));
@ -168,30 +121,17 @@ export const MessageContent = (props: Props) => {
isDeleted = selectedMsg.isDeleted;
}
const width = getWidth({ previews, attachments });
const isShowingImage = getIsShowingImage({ attachments, imageBroken, previews, text });
const hasText = Boolean(text);
const hasQuote = !isEmpty(quote);
const hasContentAfterAttachmentAndQuote = !isEmpty(previews) || !isEmpty(text);
const bgShouldBeTransparent = isShowingImage && !hasText && !hasQuote;
const toolTipTitle = moment(serverTimestamp || timestamp).format('llll');
// tslint:disable: use-simple-attributes
return (
<StyledMessageContent
<div
className={classNames(
'module-message__container',
`module-message__container--${direction}`,
bgShouldBeTransparent
? `module-message__container--${direction}--transparent`
: `module-message__container--${direction}--opaque`,
flashGreen && 'flash-green-once'
)}
style={{
width: isShowingImage ? width : undefined,
}}
role="button"
onClick={onClickOnMessageInnerContainer}
title={toolTipTitle}
@ -204,59 +144,29 @@ export const MessageContent = (props: Props) => {
triggerOnce={false}
>
<IsMessageVisibleContext.Provider value={isMessageVisible}>
{!isDeleted && (
<>
<MessageQuote messageId={props.messageId} />
<MessageAttachment
messageId={props.messageId}
imageBroken={imageBroken}
handleImageError={handleImageError}
/>
</>
)}
{hasContentAfterAttachmentAndQuote ? (
<>
<StyledMessageOpaqueContent messageDirection={direction}>
{!isDeleted && (
<MessagePreview messageId={props.messageId} handleImageError={handleImageError} />
<>
<MessageQuote messageId={props.messageId} />
<MessageLinkPreview
messageId={props.messageId}
handleImageError={handleImageError}
/>
</>
)}
<Flex padding="7px 13px" container={true} flexDirection="column">
<MessageText messageId={props.messageId} />
</Flex>
</>
<MessageText messageId={props.messageId} />
</StyledMessageOpaqueContent>
) : null}
{!isDeleted && (
<MessageAttachment
messageId={props.messageId}
imageBroken={imageBroken}
handleImageError={handleImageError}
/>
)}
</IsMessageVisibleContext.Provider>
</InView>
</StyledMessageContent>
</div>
);
};
function getWidth(
props: Pick<MessageRenderingProps, 'attachments' | 'previews'>
): number | undefined {
const { attachments, previews } = props;
if (attachments && attachments.length) {
const dimensions = getGridDimensions(attachments);
if (dimensions) {
return dimensions.width;
}
}
if (previews && previews.length) {
const first = previews[0];
if (!first || !first.image) {
return;
}
const { width } = first.image;
if (isImageAttachment(first.image) && width && width >= MINIMUM_LINK_PREVIEW_IMAGE_WIDTH) {
const dimensions = getImageDimensionsInAttachment(first.image);
if (dimensions) {
return dimensions.width;
}
}
}
return;
}

@ -5,20 +5,23 @@ import { ImageGrid } from '../../ImageGrid';
import { Image } from '../../Image';
import { MessageRenderingProps } from '../../../../models/messageType';
import { useDispatch, useSelector } from 'react-redux';
import { getMessagePreviewProps } from '../../../../state/selectors/conversations';
import { getMessageLinkPreviewProps } from '../../../../state/selectors/conversations';
import { SessionIcon } from '../../../icon';
import { MINIMUM_LINK_PREVIEW_IMAGE_WIDTH } from '../message-item/Message';
import { showLinkVisitWarningDialog } from '../../../dialog/SessionConfirm';
export type MessagePreviewSelectorProps = Pick<MessageRenderingProps, 'attachments' | 'previews'>;
export type MessageLinkPreviewSelectorProps = Pick<
MessageRenderingProps,
'attachments' | 'previews'
>;
type Props = {
handleImageError: () => void;
messageId: string;
};
export const MessagePreview = (props: Props) => {
const selected = useSelector(state => getMessagePreviewProps(state as any, props.messageId));
export const MessageLinkPreview = (props: Props) => {
const selected = useSelector(state => getMessageLinkPreviewProps(state as any, props.messageId));
const dispatch = useDispatch();
if (!selected) {

@ -38,14 +38,7 @@ export const MessageText = (props: Props) => {
}
return (
<div
dir="auto"
className={classNames(
'module-message__text',
`module-message__text--${direction}`,
status === 'error' && direction === 'incoming' ? 'module-message__text--error' : null
)}
>
<div dir="auto" className={classNames('module-message__text')}>
{isDeleted && <SessionIcon iconType="delete" iconSize="small" />}
<MessageBody
text={contents || ''}

@ -5,9 +5,10 @@ import { v4 as uuidv4 } from 'uuid';
import { useSelector } from 'react-redux';
import { getGenericReadableMessageSelectorProps } from '../../../../state/selectors/conversations';
import { GenericReadableMessage } from './GenericReadableMessage';
import { THUMBNAIL_SIDE } from '../../../../types/attachments/VisualAttachment';
// Same as MIN_WIDTH in ImageGrid.tsx
export const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = 200;
export const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = THUMBNAIL_SIDE;
type Props = {
messageId: string;

@ -115,6 +115,7 @@ const styles = {
flexDirection: 'row',
justifyContent: 'center',
padding: 10,
height: '50px', // force it so the buttons stick to the bottom
} as React.CSSProperties,
saveButton: {
marginTop: 10,
@ -122,8 +123,8 @@ const styles = {
iconButtonPlaceholder: {
// Dimensions match `.iconButton`:
display: 'inline-block',
width: 50,
height: 50,
width: 30,
height: 30,
},
};

@ -24,7 +24,7 @@ import { MessageAvatarSelectorProps } from '../../components/conversation/messag
import { MessageContentSelectorProps } from '../../components/conversation/message/message-content/MessageContent';
import { MessageContentWithStatusSelectorProps } from '../../components/conversation/message/message-content/MessageContentWithStatus';
import { MessageContextMenuSelectorProps } from '../../components/conversation/message/message-content/MessageContextMenu';
import { MessagePreviewSelectorProps } from '../../components/conversation/message/message-content/MessagePreview';
import { MessageLinkPreviewSelectorProps } from '../../components/conversation/message/message-content/MessageLinkPreview';
import { MessageQuoteSelectorProps } from '../../components/conversation/message/message-content/MessageQuote';
import { MessageStatusSelectorProps } from '../../components/conversation/message/message-content/MessageStatus';
import { MessageTextSelectorProps } from '../../components/conversation/message/message-content/MessageText';
@ -934,14 +934,14 @@ export const getMessageReactsProps = createSelector(getMessagePropsByMessageId,
return msgProps;
});
export const getMessagePreviewProps = createSelector(getMessagePropsByMessageId, (props):
| MessagePreviewSelectorProps
export const getMessageLinkPreviewProps = createSelector(getMessagePropsByMessageId, (props):
| MessageLinkPreviewSelectorProps
| undefined => {
if (!props || isEmpty(props)) {
return undefined;
}
const msgProps: MessagePreviewSelectorProps = pick(props.propsForMessage, [
const msgProps: MessageLinkPreviewSelectorProps = pick(props.propsForMessage, [
'attachments',
'previews',
]);

@ -6,11 +6,12 @@ import { saveURLAsFile } from '../util/saveURLAsFile';
import { SignalService } from '../protobuf';
import { isImageTypeSupported, isVideoTypeSupported } from '../util/GoogleChrome';
import { ATTACHMENT_DEFAULT_MAX_SIDE } from '../util/attachmentsUtil';
import { THUMBNAIL_SIDE } from './attachments/VisualAttachment';
const MAX_WIDTH = 200;
const MAX_HEIGHT = MAX_WIDTH;
const MIN_WIDTH = MAX_WIDTH;
const MIN_HEIGHT = MAX_WIDTH;
const MAX_WIDTH = THUMBNAIL_SIDE;
const MAX_HEIGHT = THUMBNAIL_SIDE;
const MIN_WIDTH = THUMBNAIL_SIDE;
const MIN_HEIGHT = THUMBNAIL_SIDE;
// Used for display
@ -217,39 +218,6 @@ export function areAllAttachmentsVisual(attachments?: Array<AttachmentType>): bo
return true;
}
export function getGridDimensions(attachments?: Array<AttachmentType>): null | DimensionsType {
if (!attachments || !attachments.length) {
return null;
}
if (!isImage(attachments) && !isVideo(attachments)) {
return null;
}
if (attachments.length === 1) {
return getImageDimensionsInAttachment(attachments[0]);
}
if (attachments.length === 2) {
return {
height: 150,
width: 300,
};
}
if (attachments.length === 4) {
return {
height: 300,
width: 300,
};
}
return {
height: 200,
width: 300,
};
}
export function getAlt(attachment: AttachmentType): string {
return isVideoAttachment(attachment)
? window.i18n('videoAttachmentAlt')

Loading…
Cancel
Save