diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss index 0e5f5753e..6d24c81e7 100644 --- a/stylesheets/_conversation.scss +++ b/stylesheets/_conversation.scss @@ -27,7 +27,7 @@ margin: 4px 16px; padding: 4px; - border-radius: $border-radius-message-box; + border-radius: var(--border-radius-message-box); align-self: flex-start; diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index aed9529b2..89c28db7b 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -62,6 +62,17 @@ flex-direction: row; align-items: center; padding: 10px; + border-radius: var(--border-radius-message-box); + + .module-message__container--outgoing & { + color: var(--color-sent-message-text); + background: var(--color-sent-message-background); + } + + .module-message__container--incoming & { + color: var(--color-received-message-text); + background: var(--color-received-message-background); + } } .module-message__generic-attachment__icon-container { @@ -88,7 +99,7 @@ } .module-message__generic-attachment__icon__extension { - font-size: 10px; + font-size: 9px; line-height: 13px; letter-spacing: 0.1px; text-transform: uppercase; @@ -115,7 +126,6 @@ } .module-message__generic-attachment__file-name { - color: $color-gray-90; font-size: 14px; line-height: 18px; font-weight: 300; @@ -127,14 +137,6 @@ text-overflow: ellipsis; } -.module-message__generic-attachment__file-size, -.module-message__generic-attachment__file-name--outgoing, -.module-message__generic-attachment__file-size--incoming, -.module-message__generic-attachment__file-size--outgoing, -.module-message__generic-attachment__file-name--incoming { - color: var(--color-text); -} - .module-message__generic-attachment__file-size { font-size: 11px; line-height: 16px; @@ -148,7 +150,7 @@ } .module-message__link-preview__content { - padding: 8px; + padding: 0 0 5px 0; display: flex; flex-direction: row; align-items: flex-start; @@ -781,20 +783,7 @@ } .module-image--soft-corners { - border-radius: $border-radius-message-box; -} - -.module-image__border-overlay { - position: absolute; - top: 0; - bottom: 0; - z-index: 1; - left: 0; - right: 0; -} - -.module-image__border-overlay--dark { - background-color: $color-black-02; + border-radius: var(--border-radius-message-box); } .module-image__loading-placeholder { @@ -858,8 +847,8 @@ position: absolute; top: 5px; right: 5px; - width: 16px; - height: 16px; + width: 20px; + height: 20px; z-index: 2; background-image: url('../images/x-shadow-16.svg'); } diff --git a/stylesheets/_quote.scss b/stylesheets/_quote.scss index c25200f0c..f1da65e46 100644 --- a/stylesheets/_quote.scss +++ b/stylesheets/_quote.scss @@ -89,8 +89,8 @@ .module-quote-container { margin-bottom: 5px; - margin-top: 10px; - padding-left: 10px; + margin-top: var(--margins-xs); + min-width: 300px; // just because even with the quoted content is small it doesn't look very good } .module-quote--no-click { diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index aa85702c5..6ed6ab91f 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -323,29 +323,18 @@ textarea { margin-inline-start: auto; } -pre { - backdrop-filter: brightness(0.8); - padding: $session-margin-xs; -} - .module-message__container { position: relative; display: inline-block; overflow: hidden; min-width: 30px; // To limit messages with things forcing them wider, like long attachment names - max-width: calc(100vw - 380px - 100px); + max-width: calc(100vw - 380px - 50px); align-items: center; } label { user-select: none; } -.module-message__attachment-container { - // Entirely to ensure that images are centered if they aren't full width of bubble - text-align: center; - position: relative; - overflow: hidden; -} .conversation-header { .module-avatar img { diff --git a/stylesheets/_session_constants.scss b/stylesheets/_session_constants.scss index d733ec863..846d16421 100644 --- a/stylesheets/_session_constants.scss +++ b/stylesheets/_session_constants.scss @@ -239,6 +239,3 @@ $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 diff --git a/stylesheets/_session_conversation.scss b/stylesheets/_session_conversation.scss index adf22e3ce..bb212ea13 100644 --- a/stylesheets/_session_conversation.scss +++ b/stylesheets/_session_conversation.scss @@ -349,8 +349,8 @@ $rhap_font-family: inherit !default; background-color: transparent; box-shadow: none; background: var(--color-accent); - padding: $padding-message-content; - border-radius: $border-radius-message-box; + padding: var(--padding-message-content); + border-radius: var(--border-radius-message-box); svg { transition: fill $session-transition-duration; diff --git a/stylesheets/_session_theme.scss b/stylesheets/_session_theme.scss index 855b7e2f5..3b5c77e9d 100644 --- a/stylesheets/_session_theme.scss +++ b/stylesheets/_session_theme.scss @@ -27,7 +27,11 @@ display: inline-flex; flex-direction: row; align-items: center; - max-width: 65%; + max-width: 95%; + + @media (min-width: 1200px) { + max-width: 65%; + } &__text-error { font-style: italic; @@ -42,8 +46,8 @@ word-break: break-word; white-space: pre-wrap; - padding: $padding-message-content; - border-radius: $border-radius-message-box; + padding: var(--padding-message-content); + border-radius: var(--border-radius-message-box); a { text-decoration: underline; diff --git a/ts/components/conversation/Image.tsx b/ts/components/conversation/Image.tsx index b6fcb3776..5e6df5d3a 100644 --- a/ts/components/conversation/Image.tsx +++ b/ts/components/conversation/Image.tsx @@ -5,6 +5,7 @@ import { Spinner } from '../basic/Spinner'; import { AttachmentType, AttachmentTypeWithPath } from '../../types/Attachment'; import { useEncryptedFileFetch } from '../../hooks/useEncryptedFileFetch'; import { useDisableDrag } from '../../hooks/useDisableDrag'; +import styled from 'styled-components'; type Props = { alt: string; @@ -20,7 +21,7 @@ type Props = { darkOverlay?: boolean; playIconOverlay?: boolean; - softCorners?: boolean; + softCorners: boolean; forceSquare?: boolean; attachmentIndex?: number; @@ -29,6 +30,16 @@ type Props = { onError?: () => void; }; +const StyledOverlay = styled.div<Pick<Props, 'darkOverlay' | 'softCorners'>>` + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + left: 0; + right: 0; + background-color: ${props => (props.darkOverlay ? '#0008' : 'unset')}; +`; + export const Image = (props: Props) => { // tslint:disable-next-line max-func-body-length cyclomatic-complexity const { @@ -133,12 +144,10 @@ export const Image = (props: Props) => { onDragStart={disableDrag} /> ) : null} - <div - className={classNames( - 'module-image__border-overlay', - softCorners ? 'module-image--soft-corners' : null, - darkOverlay ? 'module-image__border-overlay--dark' : null - )} + <StyledOverlay + className={classNames(softCorners ? 'module-image--soft-corners' : null)} + darkOverlay={darkOverlay} + softCorners={softCorners} /> {closeButton ? ( <div diff --git a/ts/components/conversation/SessionQuotedMessageComposition.tsx b/ts/components/conversation/SessionQuotedMessageComposition.tsx index 41d8ded6d..5b728f349 100644 --- a/ts/components/conversation/SessionQuotedMessageComposition.tsx +++ b/ts/components/conversation/SessionQuotedMessageComposition.tsx @@ -92,6 +92,7 @@ export const SessionQuotedMessageComposition = () => { height={100} width={100} url={firstImageAttachment.thumbnail.objectUrl} + softCorners={false} /> )} diff --git a/ts/components/conversation/message/message-content/ClickToTrustSender.tsx b/ts/components/conversation/message/message-content/ClickToTrustSender.tsx index 668b04510..455dd5dff 100644 --- a/ts/components/conversation/message/message-content/ClickToTrustSender.tsx +++ b/ts/components/conversation/message/message-content/ClickToTrustSender.tsx @@ -11,6 +11,10 @@ const StyledTrustSenderUI = styled.div` padding-inline: var(--margins-sm); display: flex; align-items: center; + width: fit-content; + + border-radius: var(--border-radius-message-box); + background: var(--color-received-message-background); `; const ClickToDownload = styled.div` diff --git a/ts/components/conversation/message/message-content/MessageAttachment.tsx b/ts/components/conversation/message/message-content/MessageAttachment.tsx index 25ce21674..8d6968fb3 100644 --- a/ts/components/conversation/message/message-content/MessageAttachment.tsx +++ b/ts/components/conversation/message/message-content/MessageAttachment.tsx @@ -1,9 +1,8 @@ -import classNames from 'classnames'; import React, { useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { clone } from 'lodash'; import { Data } from '../../../../data/data'; -import { MessageRenderingProps } from '../../../../models/messageType'; +import { MessageModelType, MessageRenderingProps } from '../../../../models/messageType'; import { PropsForAttachment, showLightBox, @@ -30,6 +29,7 @@ import { AudioPlayerWithEncryptedFile } from '../../H5AudioPlayer'; import { ImageGrid } from '../../ImageGrid'; import { LightBoxOptions } from '../../SessionConversation'; import { ClickToTrustSender } from './ClickToTrustSender'; +import styled from 'styled-components'; export type MessageAttachmentSelectorProps = Pick< MessageRenderingProps, @@ -50,6 +50,14 @@ type Props = { }; // tslint:disable: use-simple-attributes +const StyledAttachmentContainer = styled.div<{ messageDirection: MessageModelType }>` + text-align: center; + position: relative; + overflow: hidden; + display: flex; + justify-content: ${props => (props.messageDirection === 'incoming' ? 'flex-start' : 'flex-end')}; +`; + // tslint:disable-next-line max-func-body-length cyclomatic-complexity export const MessageAttachment = (props: Props) => { const { messageId, imageBroken, handleImageError } = props; @@ -121,15 +129,16 @@ export const MessageAttachment = (props: Props) => { (isVideo(attachments) && hasVideoScreenshot(attachments))) ) { return ( - <div className={classNames('module-message__attachment-container')}> + <StyledAttachmentContainer messageDirection={direction}> <ImageGrid attachments={attachments} onError={handleImageError} onClickAttachment={onClickOnImageGrid} /> - </div> + </StyledAttachmentContainer> ); - } else if (!firstAttachment.pending && !firstAttachment.error && isAudio(attachments)) { + } + if (!firstAttachment.pending && !firstAttachment.error && isAudio(attachments)) { return ( <div role="main" @@ -149,52 +158,35 @@ export const MessageAttachment = (props: Props) => { /> </div> ); - } else { - const { pending, fileName, fileSize, contentType } = firstAttachment; - const extension = getExtensionForDisplay({ contentType, fileName }); - - return ( - <div className={classNames('module-message__generic-attachment')}> - {pending ? ( - <div className="module-message__generic-attachment__spinner-container"> - <Spinner size="small" /> - </div> - ) : ( - <div className="module-message__generic-attachment__icon-container"> - <div - role="button" - className="module-message__generic-attachment__icon" - onClick={onClickOnGenericAttachment} - > - {extension ? ( - <div className="module-message__generic-attachment__icon__extension"> - {extension} - </div> - ) : null} - </div> - </div> - )} - <div className="module-message__generic-attachment__text"> - <div - className={classNames( - 'module-message__generic-attachment__file-name', - `module-message__generic-attachment__file-name--${direction}` - )} - > - {fileName} - </div> + } + const { pending, fileName, fileSize, contentType } = firstAttachment; + const extension = getExtensionForDisplay({ contentType, fileName }); + + return ( + <div className="module-message__generic-attachment"> + {pending ? ( + <div className="module-message__generic-attachment__spinner-container"> + <Spinner size="small" /> + </div> + ) : ( + <div className="module-message__generic-attachment__icon-container"> <div - className={classNames( - 'module-message__generic-attachment__file-size', - `module-message__generic-attachment__file-size--${direction}` - )} + role="button" + className="module-message__generic-attachment__icon" + onClick={onClickOnGenericAttachment} > - {fileSize} + {extension ? ( + <div className="module-message__generic-attachment__icon__extension">{extension}</div> + ) : null} </div> </div> + )} + <div className="module-message__generic-attachment__text"> + <div className="module-message__generic-attachment__file-name">{fileName}</div> + <div className="module-message__generic-attachment__file-size">{fileSize}</div> </div> - ); - } + </div> + ); }; function attachmentIsAttachmentTypeWithPath(attac: any): attac is AttachmentTypeWithPath { diff --git a/ts/components/conversation/message/message-content/MessageBody.tsx b/ts/components/conversation/message/message-content/MessageBody.tsx index 4a76370e6..0fd3c0a07 100644 --- a/ts/components/conversation/message/message-content/MessageBody.tsx +++ b/ts/components/conversation/message/message-content/MessageBody.tsx @@ -9,6 +9,7 @@ import { AddNewLines } from '../../AddNewLines'; import { Emojify } from '../../Emojify'; import { LinkPreviews } from '../../../../util/linkPreviews'; import { showLinkVisitWarningDialog } from '../../../dialog/SessionConfirm'; +import styled from 'styled-components'; const linkify = LinkifyIt(); @@ -88,6 +89,12 @@ const JsxSelectable = (jsx: JSX.Element): JSX.Element => { ); }; +const StyledPre = styled.pre` + backdrop-filter: brightness(0.8); + padding: var(--margins-xs); + user-select: text; +`; + export const MessageBody = (props: Props) => { const { text, disableJumbomoji, disableLinks, isGroup } = props; const sizeClass: SizeClassType = disableJumbomoji ? 'default' : getEmojiSizeClass(text); @@ -105,7 +112,7 @@ export const MessageBody = (props: Props) => { } if (text && text.startsWith('```') && text.endsWith('```') && text.length > 6) { - return <pre className="text-selectable">{text.substring(4, text.length - 3)}</pre>; + return <StyledPre>{text.substring(4, text.length - 3)}</StyledPre>; } return JsxSelectable( diff --git a/ts/components/conversation/message/message-content/MessageContent.tsx b/ts/components/conversation/message/message-content/MessageContent.tsx index ee0745bec..ccbbe6769 100644 --- a/ts/components/conversation/message/message-content/MessageContent.tsx +++ b/ts/components/conversation/message/message-content/MessageContent.tsx @@ -48,6 +48,8 @@ const StyledMessageOpaqueContent = styled.div<{ messageDirection: MessageModelTy props.messageDirection === 'incoming' ? 'var(--color-received-message-background)' : 'var(--color-sent-message-background)'}; + align-self: ${props => (props.messageDirection === 'incoming' ? 'flex-start' : 'flex-end')}; + padding: 7px 13px; // FIXME border-radius: 16px; //FIXME `; @@ -142,6 +144,11 @@ export const MessageContent = (props: Props) => { threshold={0} rootMargin="500px 0px 500px 0px" triggerOnce={false} + style={{ + display: 'flex', + flexDirection: 'column', + gap: 'var(--margins-xs)', + }} > <IsMessageVisibleContext.Provider value={isMessageVisible}> {hasContentAfterAttachmentAndQuote ? ( diff --git a/ts/components/conversation/message/message-content/MessageContentWithStatus.tsx b/ts/components/conversation/message/message-content/MessageContentWithStatus.tsx index a069e5983..99ca186c6 100644 --- a/ts/components/conversation/message/message-content/MessageContentWithStatus.tsx +++ b/ts/components/conversation/message/message-content/MessageContentWithStatus.tsx @@ -20,8 +20,8 @@ import { MessageStatus } from './MessageStatus'; export type MessageContentWithStatusSelectorProps = Pick< MessageRenderingProps, - 'direction' | 'isDeleted' | 'isTrustedForAttachmentDownload' -> & { hasAttachments: boolean }; + 'direction' | 'isDeleted' +>; type Props = { messageId: string; @@ -87,7 +87,7 @@ export const MessageContentWithStatuses = (props: Props) => { if (!contentProps) { return null; } - const { direction, isDeleted, hasAttachments, isTrustedForAttachmentDownload } = contentProps; + const { direction, isDeleted } = contentProps; const isIncoming = direction === 'incoming'; const [popupReaction, setPopupReaction] = useState(''); @@ -112,9 +112,6 @@ export const MessageContentWithStatuses = (props: Props) => { role="button" onClick={onClickOnMessageOuterContainer} onDoubleClickCapture={onDoubleClickReplyToMessage} - style={{ - width: hasAttachments && isTrustedForAttachmentDownload ? 'min-content' : 'auto', - }} data-testid={dataTestId} > <MessageStatus diff --git a/ts/state/ducks/SessionTheme.tsx b/ts/state/ducks/SessionTheme.tsx index 7322028b5..6be30151b 100644 --- a/ts/state/ducks/SessionTheme.tsx +++ b/ts/state/ducks/SessionTheme.tsx @@ -334,10 +334,16 @@ export const SessionGlobalStyles = createGlobalStyle` --margins-md: 15px; --margins-lg: 20px; + /* PADDING */ + --padding-message-content: 7px 13px; + --border-radius-message-box: 16px; + /* ANIMATIONS */ --default-duration: '0.25s'; + /* FILTERS */ --filter-session-text: ${lightFilterSessionText}; + /* BORDERS */ --border-unread: ${lightUnreadBorder}; --border-session: ${lightColorSessionBorder}; @@ -348,6 +354,7 @@ export const SessionGlobalStyles = createGlobalStyle` /* COLORS NOT CHANGING BETWEEN THEMES */ --color-warning: ${warning}; --color-destructive: ${destructive}; + /* COLORS */ --color-accent: ${lightColorAccent}; --color-accent-button: ${lightColorAccentButton}; @@ -360,7 +367,6 @@ export const SessionGlobalStyles = createGlobalStyle` --color-session-shadow: ${lightColorSessionShadow}; --color-compose-view-button-background: ${lightColorComposeViewBg}; --color-sent-message-background: ${lightColorSentMessageBg}; - // TODO: this might be wrong text colour. Something happened during merge. --color-sent-message-text: ${black}; --color-clickable-hovered: ${lightColorClickableHovered}; --color-session-border: ${lightColorSessionBorderColor}; diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index deafbcf69..0658d5991 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -1111,8 +1111,7 @@ export const getMessageContentWithStatusesSelectorProps = createSelector( } const msgProps: MessageContentWithStatusSelectorProps = { - hasAttachments: Boolean(props.propsForMessage.attachments?.length) || false, - ...pick(props.propsForMessage, ['direction', 'isDeleted', 'isTrustedForAttachmentDownload']), + ...pick(props.propsForMessage, ['direction', 'isDeleted']), }; return msgProps;