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.
		
		
		
		
		
			
		
			
				
	
	
		
			175 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			175 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			TypeScript
		
	
import { useDispatch, useSelector } from 'react-redux';
 | 
						|
import useKey from 'react-use/lib/useKey';
 | 
						|
import styled from 'styled-components';
 | 
						|
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 { findAndFormatContact } from '../../models/message';
 | 
						|
import { getAbsoluteAttachmentPath } from '../../types/MessageAttachment';
 | 
						|
import { GoogleChrome } from '../../util';
 | 
						|
 | 
						|
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>
 | 
						|
  );
 | 
						|
};
 |