Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/theme/client/imports/general/base_old.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
}

.rc-old code {
display: block;

margin: 5px 0;
padding: 0.5em;

Expand Down
6 changes: 3 additions & 3 deletions client/components/Message/Attachments/Attachment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ const Download: FC<ButtonProps & { href: string }> = (props) => {
return <Action icon='download' title={t('Download')} is='a' target='_blank' {...props} />;
};

const Content: FC<BoxProps> = ({ ...props }) => <Box mb='x4' {...props} />;
const Details: FC<BoxProps> = ({ ...props }) => <Box fontScale='p1' color='info' bg='neutral-100' pi='x16' pb='x16' {...props}/>;
const Inner: FC<BoxProps> = ({ ...props }) => <Box mis='x16' {...props}/>;
const Content: FC<BoxProps> = ({ ...props }) => <Box rcx-attachment__content width='full' mb='x4' {...props} />;
const Details: FC<BoxProps> = ({ ...props }) => <Box rcx-attachment__details fontScale='p1' color='info' bg='neutral-100' pi='x16' pb='x16' {...props}/>;
const Inner: FC<BoxProps> = ({ ...props }) => <Box {...props}/>;

const Block: FC<{ pre?: JSX.Element | string; color?: string }> = ({ pre, color = 'neutral-600', children }) => <Attachment>{pre}<Box display='flex' flexDirection='row' pis='x16' borderRadius='x2' borderInlineStartStyle='solid' borderInlineStartWidth='x2' borderInlineStartColor={color} children={children}></Box></Attachment>;

Expand Down
68 changes: 68 additions & 0 deletions client/components/Message/Attachments/DefaultAttachment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { FC } from 'react';

import { FieldsAttachment, FieldsAttachmentProps } from './FieldsAttachment';
import MarkdownText from '../../MarkdownText';
import { ActionAttachment, ActionAttachmentProps } from './ActionAttachtment';
import { Dimensions } from './components/Image';
import { Attachment } from './Attachment';
import { useCollapse } from './hooks/useCollapse';

import { AttachmentProps } from '.';

type MarkdownFields = 'text' | 'pretext' | 'fields';

export type DefaultAttachmentProps = {
collapsed?: true;

author_icon?: string;
author_link?: string;
author_name?: string;

fields: FieldsAttachmentProps;

// footer
// footer_icon

image_url?: string;
image_dimensions?: Dimensions;

mrkdwn_in?: Array<MarkdownFields>;
pretext?: string;
text? : string;

thumb_url?: string;

title?: string;
title_link?: string;

ts?: Date;

color?: string;
};

const isActionAttachment = (attachment: AttachmentProps): attachment is ActionAttachmentProps => 'actions' in attachment;

const applyMarkdownIfRequires = (list: DefaultAttachmentProps['mrkdwn_in']) => (key: MarkdownFields, text: string): JSX.Element | string => (list?.includes(key) ? <MarkdownText withRichContent={undefined} content={text}/> : text);

export const DefaultAttachment: FC<DefaultAttachmentProps> = (attachment) => {
const applyMardownFor = applyMarkdownIfRequires(attachment.mrkdwn_in);
const [collapsed, collapse] = useCollapse(!!attachment.collapsed);
return <Attachment.Block color={attachment.color} pre={attachment.pretext && <Attachment.Text>{applyMardownFor('pretext', attachment.pretext)}</Attachment.Text>}>
<Attachment.Content>
{attachment.author_name && <Attachment.Author>
{ attachment.author_icon && <Attachment.AuthorAvatar url={attachment.author_icon } />}
<Attachment.AuthorName {...attachment.author_link && { is: 'a', href: attachment.author_link, target: '_blank', color: undefined }}>{attachment.author_name}</Attachment.AuthorName>
</Attachment.Author> }
{attachment.title && <Attachment.Row><Attachment.Title {...attachment.title_link && { is: 'a', href: attachment.title_link, target: '_blank', color: undefined }}>{attachment.title}</Attachment.Title> {collapse}</Attachment.Row>}
{!collapsed && <>
{attachment.text && <Attachment.Text>{applyMardownFor('text', attachment.text)}</Attachment.Text>}
{/* {attachment.fields && <FieldsAttachment fields={attachment.mrkdwn_in?.includes('fields') ? attachment.fields.map(({ value, ...rest }) => ({ ...rest, value: <MarkdownText withRichContent={null} content={value} /> })) : attachment.fields} />} */}
{attachment.fields && <FieldsAttachment fields={attachment.fields.map(({ value, ...rest }) => ({ ...rest, value: <MarkdownText withRichContent={undefined} content={value} /> }))} />}
{attachment.image_url && <Attachment.Image {...attachment.image_dimensions as any} src={attachment.image_url} />}
{/* DEPRECATED */}
{isActionAttachment(attachment) && <ActionAttachment {...attachment} />}
</>}
</Attachment.Content>
{attachment.thumb_url && <Attachment.Thumb url={attachment.thumb_url} /> }
</Attachment.Block>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type AudioAttachmentProps = {
audio_url: string;
audio_type: string;
audio_size?: number;
file: FileProp;
file?: FileProp;
} & AttachmentPropsBase;

export const AudioAttachment: FC<AudioAttachmentProps> = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type ImageAttachmentProps = {
image_url: string;
image_type: string;
image_size?: number;
file: FileProp;
file?: FileProp;
} & AttachmentPropsBase;

export const ImageAttachment: FC<ImageAttachmentProps> = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type VideoAttachmentProps = {
video_url: string;
video_type: string;
video_size: number;
file: FileProp;
file?: FileProp;
} & AttachmentPropsBase;

export const VideoAttachment: FC<VideoAttachmentProps> = ({ title,
Expand Down
9 changes: 6 additions & 3 deletions client/components/Message/Attachments/Files/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React, { FC } from 'react';

import { AttachmentPropsGeneric, FileProp } from '..';
import { AttachmentProps, FileProp } from '..';
import { AudioAttachment, AudioAttachmentProps } from './AudioAttachment';
import { GenericFileAttachment } from './GenericFileAttachment';
import { ImageAttachment, ImageAttachmentProps } from './ImageAttachment';
// import { PDFAttachment } from './PDFAttachment';
import { VideoAttachment, VideoAttachmentProps } from './VideoAttachment';

export type FileAttachmentProps = { type: 'file'; file: FileProp } & (VideoAttachmentProps | ImageAttachmentProps | AudioAttachmentProps);
export type FileAttachmentProps = {
type: 'file';
file?: FileProp;
} & (VideoAttachmentProps | ImageAttachmentProps | AudioAttachmentProps);

const isFileImageAttachment = (attachment: FileAttachmentProps): attachment is ImageAttachmentProps & { type: 'file' } => 'image_url' in attachment;
const isFileAudioAttachment = (attachment: FileAttachmentProps): attachment is AudioAttachmentProps & { type: 'file' } => 'audio_url' in attachment;
Expand All @@ -23,4 +26,4 @@ export const FileAttachment: FC<FileAttachmentProps> = (attachment) => {
return <GenericFileAttachment {...attachment}/>;
};

export const isFileAttachment = (attachment: AttachmentPropsGeneric): attachment is FileAttachmentProps => 'type' in attachment && attachment.type === 'file';
export const isFileAttachment = (attachment: AttachmentProps): attachment is FileAttachmentProps => 'type' in attachment && attachment.type === 'file';
19 changes: 16 additions & 3 deletions client/components/Message/Attachments/QuoteAttachment.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Box } from '@rocket.chat/fuselage';
import React, { FC } from 'react';
import { css } from '@rocket.chat/css-in-js';
import colors from '@rocket.chat/fuselage-tokens/colors';

import { Attachment, AttachmentPropsBase } from './Attachment';
import { useTimeAgo } from '../../../hooks/useTimeAgo';
Expand All @@ -16,17 +18,28 @@ export type QuoteAttachmentProps = {
attachments?: Array<QuoteAttachmentProps>;
} & AttachmentPropsBase;

const hover = css`
&:hover,
&:focus {
.rcx-attachment__details {
background: ${ colors.n200 } !important;
border-color: ${ colors.n300 } !important;
border-inline-start-color: ${ colors.n600 } !important;
}
}
`;

export const QuoteAttachment: FC<QuoteAttachmentProps> = ({ author_icon: url, author_name: name, author_link: authorLink, message_link: messageLink, ts, text, attachments }) => {
const format = useTimeAgo();
return <>
<Attachment.Content maxWidth='480px' width='full' borderRadius='x2' borderWidth='x2' borderStyle='solid' borderColor='neutral-200' >
<Attachment.Details is='blockquote'>
<Attachment.Content className={hover} width='full'>
<Attachment.Details is='blockquote' borderRadius='x2' borderWidth='x2' borderStyle='solid' borderColor='neutral-200' borderInlineStartColor='neutral-600'>
<Attachment.Author>
<Attachment.AuthorAvatar url={url} />
<Attachment.AuthorName {...authorLink && { is: 'a', href: authorLink, target: '_blank', color: undefined }}>{name}</Attachment.AuthorName>
<Box fontScale='c1' {...messageLink ? { is: 'a', href: messageLink } : { color: 'hint' }}>{format(ts)}</Box>
</Attachment.Author>
<MarkdownText content={text} />
<MarkdownText mb='neg-x16' content={text} />
{attachments && <Attachment.Inner><Attachments attachments={attachments} /></Attachment.Inner>}
</Attachment.Details>
</Attachment.Content>
Expand Down
68 changes: 7 additions & 61 deletions client/components/Message/Attachments/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import React, { FC, memo } from 'react';

import { FieldsAttachment, FieldsAttachmentProps } from './FieldsAttachment';
import { QuoteAttachment, QuoteAttachmentProps } from './QuoteAttachment';
import { Attachment } from './Attachment';
import { FileAttachmentProps, isFileAttachment, FileAttachment } from './Files';
import MarkdownText from '../../MarkdownText';
import { Dimensions } from './components/Image';
import { ActionAttachment, ActionAttachmentProps } from './ActionAttachtment';

type PossibleMarkdownFields = 'text' | 'pretext' | 'fields';
import { DefaultAttachment, DefaultAttachmentProps } from './DefaultAttachment';

export type FileProp = {
_id: string;
Expand All @@ -18,70 +12,22 @@ export type FileProp = {
size: number;
};

export type AttachmentProps = DefaultAttachmentProps | FileAttachmentProps | QuoteAttachmentProps;

export type AttachmentProps = {
author_icon?: string;
author_link?: string;
author_name?: string;

fields: FieldsAttachmentProps;

// footer
// footer_icon

image_url?: string;
image_dimensions?: Dimensions;

mrkdwn_in?: Array<PossibleMarkdownFields>;
pretext?: string;
text? : string;

thumb_url?: string;

title?: string;
title_link?: string;
const isQuoteAttachment = (attachment: AttachmentProps): attachment is QuoteAttachmentProps => 'message_link' in attachment;

ts?: Date;

color?: string;
}

export type AttachmentPropsGeneric = AttachmentProps | FileAttachmentProps | QuoteAttachmentProps | ActionAttachmentProps;

const isQuoteAttachment = (attachment: AttachmentPropsGeneric): attachment is QuoteAttachmentProps => 'message_link' in attachment;

const isActionAttachment = (attachment: AttachmentPropsGeneric): attachment is ActionAttachmentProps => 'actions' in attachment;

const applyMarkdownIfRequires = (list: AttachmentProps['mrkdwn_in']) => (key: PossibleMarkdownFields, text: string): JSX.Element | string => (list?.includes(key) ? <MarkdownText withRichContent={undefined} content={text}/> : text);

const Item: FC<{attachment: AttachmentPropsGeneric; file?: FileProp }> = memo(({ attachment, file = null }) => {
const Item: FC<{attachment: AttachmentProps; file?: FileProp }> = memo(({ attachment, file }) => {
if (isFileAttachment(attachment)) {
return file && <FileAttachment {...attachment} file={file}/>;
return <FileAttachment {...attachment} file={file}/>;
}

if (isQuoteAttachment(attachment)) {
return <QuoteAttachment {...attachment}/>;
}

const applyMardownFor = applyMarkdownIfRequires(attachment.mrkdwn_in);

return <Attachment.Block color={attachment.color} pre={attachment.pretext && <Attachment.Text>{applyMardownFor('pretext', attachment.pretext)}</Attachment.Text>}>
<Attachment.Content>
{attachment.author_name && <Attachment.Author>
{ attachment.author_icon && <Attachment.AuthorAvatar url={attachment.author_icon } />}
<Attachment.AuthorName {...attachment.author_link && { is: 'a', href: attachment.author_link, target: '_blank', color: undefined }}>{attachment.author_name}</Attachment.AuthorName>
</Attachment.Author> }
{attachment.title && <Attachment.Title {...attachment.title_link && { is: 'a', href: attachment.title_link, target: '_blank', color: undefined }}>{attachment.title}</Attachment.Title> }
{attachment.text && <Attachment.Text>{applyMardownFor('text', attachment.text)}</Attachment.Text>}
{attachment.fields && <FieldsAttachment fields={attachment.mrkdwn_in?.includes('fields') ? attachment.fields.map(({ value, ...rest }) => ({ ...rest, value: <MarkdownText withRichContent={undefined} content={value} /> })) : attachment.fields} />}
{attachment.image_url && <Attachment.Image {...attachment.image_dimensions as any} src={attachment.image_url} />}
{/* DEPRECATED */}
{isActionAttachment(attachment) && <ActionAttachment {...attachment} />}
</Attachment.Content>
{attachment.thumb_url && <Attachment.Thumb url={attachment.thumb_url} /> }
</Attachment.Block>;
return <DefaultAttachment {...attachment as any}/>;
});

const Attachments: FC<{ attachments: Array<AttachmentPropsGeneric>; file?: FileProp}> = ({ attachments = null, file }): any => attachments && attachments.map((attachment, index) => <Item key={index} file={file} attachment={attachment} />);
const Attachments: FC<{ attachments: Array<AttachmentProps>; file?: FileProp}> = ({ attachments = null, file }): any => attachments && attachments.map((attachment, index) => <Item key={index} file={file} attachment={attachment} />);

export default Attachments;