You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/components/conversation/SessionQuotedMessageComposi...

176 lines
5.1 KiB
TypeScript

import React from 'react';
import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux';
import useKey from 'react-use/lib/useKey';
import { SessionIcon, SessionIconButton } from '../icon';
import { quoteMessage } from '../../state/ducks/conversations';
import { getQuotedMessage } from '../../state/selectors/conversations';
import { getAlt, isAudio } from '../../types/Attachment';
import { AUDIO_MP3 } from '../../types/MIME';
import { Flex } from '../basic/Flex';
import { Image } from './Image';
import { getAbsoluteAttachmentPath } from '../../types/MessageAttachment';
import { GoogleChrome } from '../../util';
import { findAndFormatContact } from '../../models/message';
const QuotedMessageComposition = styled(Flex)`
border-top: 1px solid var(--border-color);
`;
const QuotedMessageCompositionReply = styled(Flex)<{ hasAttachments: boolean }>`
${props => !props.hasAttachments && 'border-left: 3px solid var(--primary-color);'}
`;
const Subtle = styled.div`
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
display: -webkit-box;
color: var(--text-primary-color);
`;
const StyledImage = styled.div`
div {
border-radius: 4px;
overflow: hidden;
}
`;
const StyledText = styled(Flex)`
margin: 0 0 0 var(--margins-sm);
p {
font-weight: bold;
margin: 0;
}
`;
function checkHasAttachments(attachments: Array<any> | undefined) {
const hasAttachments = attachments && attachments.length > 0 && attachments[0];
// NOTE could be a video as well which will load a thumbnail
const firstImageLikeAttachment =
hasAttachments && attachments[0].contentType !== AUDIO_MP3 && attachments[0].thumbnail
? attachments[0]
: undefined;
return { hasAttachments, firstImageLikeAttachment };
}
function renderSubtitleText(
quoteText: string | undefined,
hasAudioAttachment: boolean,
isGenericFile: boolean,
isVideo: boolean,
isImage: boolean
): string | null {
return quoteText && quoteText !== ''
? quoteText
: hasAudioAttachment
? window.i18n('audio')
: isGenericFile
? window.i18n('document')
: isVideo
? window.i18n('video')
: isImage
? window.i18n('image')
: null;
}
export const SessionQuotedMessageComposition = () => {
const dispatch = useDispatch();
const quotedMessageProps = useSelector(getQuotedMessage);
const { author, attachments, text: quoteText } = quotedMessageProps || {};
const removeQuotedMessage = () => {
dispatch(quoteMessage(undefined));
};
useKey('Escape', removeQuotedMessage, undefined, []);
if (!author || !quotedMessageProps?.id) {
return null;
}
const contact = findAndFormatContact(author);
const authorName = contact?.profileName || contact?.name || author || window.i18n('unknown');
const { hasAttachments, firstImageLikeAttachment } = checkHasAttachments(attachments);
const isImage = Boolean(
firstImageLikeAttachment &&
GoogleChrome.isImageTypeSupported(firstImageLikeAttachment.contentType)
);
const isVideo = Boolean(
firstImageLikeAttachment &&
GoogleChrome.isVideoTypeSupported(firstImageLikeAttachment.contentType)
);
const hasAudioAttachment = Boolean(hasAttachments && isAudio(attachments));
const isGenericFile = !hasAudioAttachment && !isVideo && !isImage;
const subtitleText = renderSubtitleText(
quoteText,
hasAudioAttachment,
isGenericFile,
isVideo,
isImage
);
return (
<QuotedMessageComposition
container={true}
justifyContent="space-between"
alignItems="center"
width={'100%'}
flexGrow={1}
padding={'var(--margins-md)'}
>
<QuotedMessageCompositionReply
container={true}
justifyContent="flex-start"
alignItems={'center'}
hasAttachments={hasAttachments}
>
{hasAttachments && (
<StyledImage>
{firstImageLikeAttachment ? (
<Image
alt={getAlt(firstImageLikeAttachment)}
attachment={firstImageLikeAttachment}
height={100}
width={100}
url={getAbsoluteAttachmentPath((firstImageLikeAttachment as any).thumbnail.path)}
softCorners={true}
/>
) : hasAudioAttachment ? (
<div style={{ margin: '0 var(--margins-xs) 0 0' }}>
<SessionIcon iconType="microphone" iconSize="huge" />
</div>
) : null}
</StyledImage>
)}
<StyledText
container={true}
flexDirection="column"
justifyContent={'center'}
alignItems={'flex-start'}
>
<p>{authorName}</p>
{subtitleText && <Subtle>{subtitleText}</Subtle>}
</StyledText>
</QuotedMessageCompositionReply>
<SessionIconButton
iconType="exit"
iconColor="var(--chat-buttons-icon-color)"
iconSize="small"
onClick={removeQuotedMessage}
margin={'0 var(--margins-sm) 0 0'}
aria-label={window.i18n('close')}
/>
</QuotedMessageComposition>
);
};