Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
70cbfcb
feat: add themeVersion flag to ChatProps & ChatContext
MartinCupela Jun 24, 2022
3421087
feat: compute the themeVersion value, remove themeVersion Chat prop
MartinCupela Jun 27, 2022
695f30a
feat: add ThemeVersion type to ChatContext
MartinCupela Jun 27, 2022
50c8271
chore(deps): added package clsx
arnautov-anton Jun 22, 2022
bff3f86
chore: upgrade typescript version
MartinCupela Jul 5, 2022
c4f7520
feat: add "str-chat__message--error-message" class to message error div
MartinCupela Jul 5, 2022
9323edb
feat: wrap ThreadHead content in a div to enable styling for class st…
MartinCupela Jul 5, 2022
ecd0b4b
feat: add class "str-chat__message-sender-avatar" to Avatar root to d…
MartinCupela Jul 5, 2022
88a5f7c
feat: change the close icon for modal and remove Close text
MartinCupela Jul 5, 2022
97e8047
feat: add Attachment icons for theming v2
MartinCupela Jul 5, 2022
52acd80
feat: add FileAttachment component for theming v2
MartinCupela Jul 5, 2022
3ff89bb
feat: add common IconProps type
MartinCupela Jul 5, 2022
9ff9034
feat: add Message icons for theming v2 - MessageDeliveredIcon, Messag…
MartinCupela Jul 5, 2022
a5b0fae
feat: adapt MessageStatus to theming v2
MartinCupela Jul 5, 2022
23c2d93
feat: adapt MessageOptions to theming v2
MartinCupela Jul 5, 2022
aeee078
feat: convert attachment render functions into components, group atta…
MartinCupela Jul 6, 2022
d62e04a
feat: add theming v2 classes to MessageActions elements
MartinCupela Jul 6, 2022
f08c6f5
feat: adjust Audio widget for theming v2
MartinCupela Jul 6, 2022
f84d22c
style: order File.test.js imports
MartinCupela Jul 6, 2022
27e149a
feat: add ModalGallery to the ComponentContext
MartinCupela Jul 6, 2022
de29a73
feat: adjust Gallery and Image widget for theming v2
MartinCupela Jul 7, 2022
8c5d2ff
feat: add theming v2 classes to QuotedMessage
MartinCupela Jul 7, 2022
5076fd5
feat: adjust MessageRepliesCountButton to theming v2, add classes
MartinCupela Jul 7, 2022
a9534c0
refactor: assert error type
MartinCupela Jul 7, 2022
aa1624a
feat: do not sanitize attachment scrape urls
MartinCupela Jul 7, 2022
e4c2a7b
feat: add realistic giphy attachment generator
MartinCupela Jul 8, 2022
d5480c7
test: render null if scraped attachment does not have og_scrape_url n…
MartinCupela Jul 8, 2022
0f42f62
refactor: scraped attachment has either og_scrape_url or title_link
MartinCupela Jul 8, 2022
8027908
feat: extract CardAudio and render only uploaded audio data in Audio …
MartinCupela Jul 8, 2022
2e983d0
test: render v1 icons in File v1
MartinCupela Jul 8, 2022
40342fe
fix: do not generate class names to contain string 'undefined', do no…
MartinCupela Jul 8, 2022
5f5341f
feat: add Card component for theming v2
MartinCupela Jul 8, 2022
ebd4bd7
feat: adjust MessageSimple for theming v2
MartinCupela Jul 8, 2022
14faa01
test: update Avatar snapshots
MartinCupela Jul 8, 2022
c79d8c7
refactor: use FileIcon instead of FileIconV2 in FileAttachment
MartinCupela Jul 10, 2022
4d150b1
feat: use FileIcon with version in UploadsPreview
MartinCupela Jul 10, 2022
6fd9792
Merge remote-tracking branch 'origin/theming-v2' into theming-v2-mess…
MartinCupela Jul 11, 2022
9d75fb8
feat: remove deprecated components: MessageCommerce, MessageLivestrea…
MartinCupela Jul 11, 2022
e524d0a
feat: remove translations for deprecated components: MessageCommerce,…
MartinCupela Jul 11, 2022
0234522
feat: add str-chat-react__modal__inner class to str-chat__modal__inner
MartinCupela Jul 12, 2022
c44bcd7
fix: move card caption to card content and rename to source link
MartinCupela Jul 12, 2022
25f3190
fix: add str-chat__message--other class to MessageDeleted
MartinCupela Jul 12, 2022
fbedb42
feat: add theming v2 classes to ReactionSelector & ReactionList
MartinCupela Jul 11, 2022
f6a12d0
feat: add theme v2 to Reaction components, extract shared logic React…
MartinCupela Jul 12, 2022
51e7c14
fix: sync event listener keyDown type btw the image attachment and ga…
MartinCupela Jul 13, 2022
a9ede6b
test: sync event listener keyDown type btw the image attachment and g…
MartinCupela Jul 13, 2022
ab75c2c
feat: add v2 classes to send and cancel button of EditMessageForm (#1…
MartinCupela Jul 13, 2022
037dc89
feat: add theme v2 class to CustomNotification
MartinCupela Jul 13, 2022
e643523
chore(deps): bump version react-file-utils from v1.1.12 to v1.2.0
MartinCupela Jul 22, 2022
8b853ef
refactor: use type ThemeVersion
MartinCupela Jul 22, 2022
473a869
refactor: reorganize MessageSimple & Gallery root classes
MartinCupela Jul 22, 2022
d2acd9b
test: update snapshots after reorganization of MessageSimple root cla…
MartinCupela Jul 22, 2022
21152b5
test: update snapshots for file icons
MartinCupela Jul 22, 2022
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
24 changes: 24 additions & 0 deletions docusaurus/docs/React/message-components/reactions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ If true, adds a CSS class that reverses the horizontal positioning of the select

## ReactionsList Props

### additionalEmojiProps

Additional props to be passed to the [NimbleEmoji](https://github.com/missive/emoji-mart/blob/master/src/components/emoji/nimble-emoji.js) component from `emoji-mart`.

| Type |
| ------ |
| object |

### onClick

Custom on click handler for an individual reaction in the list (overrides the function stored in `MessageContext`).
Expand All @@ -203,6 +211,14 @@ Custom on click handler for an individual reaction in the list (overrides the fu
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| (event: React.BaseSyntheticEvent) => Promise<void\> \| void | [MessageContextValue['onReactionListClick']](../contexts/message-context.mdx#onreactionlistclick) |

### own_reactions

An array of the own reaction objects to distinguish own reactions visually (overrides `message.own_reactions` from `MessageContext`).

| Type |
| ----- |
| array |

### reaction_counts

An object that keeps track of the count of each type of reaction on a message (overrides `message.reaction_counts` from `MessageContext`).
Expand Down Expand Up @@ -253,6 +269,14 @@ Function that adds/removes a reaction on a message (overrides the function store
| ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| (reactionType: string, event: React.BaseSyntheticEvent) => Promise<void\> | [MessageContextValue['handleReaction']](../contexts/message-context.mdx#handlereaction) |

### own_reactions

An array of the own reaction objects to distinguish own reactions visually (overrides `message.own_reactions` from `MessageContext`).

| Type |
| ----- |
| array |

### reaction_counts

An object that keeps track of the count of each type of reaction on a message (overrides `message.reaction_counts` from `MessageContext`).
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@braintree/sanitize-url": "6.0.0",
"@juggle/resize-observer": "^3.3.1",
"@stream-io/stream-chat-css": "^2.10.0",
"clsx": "^1.1.1",
"dayjs": "^1.10.4",
"emoji-mart": "3.0.1",
"emoji-regex": "^9.2.0",
Expand All @@ -46,7 +47,7 @@
"pretty-bytes": "^5.4.1",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.2.0",
"react-file-utils": "^1.1.12",
"react-file-utils": "^1.2.0",
"react-image-gallery": "^1.2.7",
"react-is": "^18.1.0",
"react-markdown": "^5.0.3",
Expand Down Expand Up @@ -170,7 +171,7 @@
"style-loader": "^2.0.0",
"ts-jest": "^26.5.1",
"tslib": "2.3.0",
"typescript": "4.3.5",
"typescript": "^4.7.4",
"url-loader": "^4.1.1",
"webpack": "4.44.2",
"webpack-cli": "^3.3.12",
Expand Down
170 changes: 117 additions & 53 deletions src/components/Attachment/Attachment.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import React from 'react';
import React, { useMemo } from 'react';
import { sanitizeUrl } from '@braintree/sanitize-url';
import type { ReactPlayerProps } from 'react-player';
import type { Attachment as StreamAttachment } from 'stream-chat';

import {
AttachmentComponentType,
GroupedRenderedAttachment,
isAudioAttachment,
isFileAttachment,
isGalleryAttachmentType,
isImageAttachment,
isMediaAttachment,
renderAudio,
renderCard,
renderFile,
renderGallery,
renderImage,
renderMedia,
isScrapedContent,
isUploadedImage,
} from './utils';

import type { ReactPlayerProps } from 'react-player';
import type { Attachment as StreamAttachment } from 'stream-chat';
import {
AudioContainer,
CardContainer,
FileContainer,
GalleryContainer,
ImageContainer,
MediaContainer,
} from './AttachmentContainer';

import type { AttachmentActionsProps } from './AttachmentActions';
import type { AudioProps } from './Audio';
Expand All @@ -26,6 +31,22 @@ import type { ActionHandlerReturnType } from '../Message/hooks/useActionHandler'

import type { DefaultStreamChatGenerics } from '../../types/types';

const CONTAINER_MAP = {
audio: AudioContainer,
card: CardContainer,
file: FileContainer,
media: MediaContainer,
} as const;

const ATTACHMENT_GROUPS_ORDER: AttachmentComponentType[] = [
'card',
'gallery',
'image',
'media',
'audio',
'file',
];

export type AttachmentProps<
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
> = {
Expand Down Expand Up @@ -57,54 +78,97 @@ export const Attachment = <
>(
props: AttachmentProps<StreamChatGenerics>,
) => {
const { attachments, ...rest } = props;

const gallery = {
images: attachments?.filter(
(attachment) =>
attachment.type === 'image' && !(attachment.og_scrape_url || attachment.title_link),
),
type: 'gallery',
};

const newAttachments =
gallery.images.length >= 2
? [
...attachments.filter(
(attachment) =>
!(
attachment.type === 'image' && !(attachment.og_scrape_url || attachment.title_link)
),
),
gallery,
]
: attachments;
const { attachments } = props;

const groupedAttachments = useMemo(() => renderGroupedAttachments(props), [attachments]);

return (
<>
{newAttachments.map((attachment) => {
if (isGalleryAttachmentType(attachment)) {
return renderGallery({ ...rest, attachment });
}
<div className='str-chat__attachment-list'>
{ATTACHMENT_GROUPS_ORDER.reduce(
(acc, groupName) => [...acc, ...groupedAttachments[groupName]],
[] as React.ReactNode[],
)}
</div>
);
};

if (isImageAttachment(attachment)) {
return renderImage({ ...rest, attachment });
}
const renderGroupedAttachments = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
>({
attachments,
...rest
}: AttachmentProps<StreamChatGenerics>): GroupedRenderedAttachment => {
const uploadedImages: StreamAttachment<StreamChatGenerics>[] = [];

if (isAudioAttachment(attachment)) {
return renderAudio({ ...rest, attachment });
}
const containers = attachments.reduce(
(acc, attachment) => {
if (isUploadedImage(attachment)) {
uploadedImages.push({
...attachment,
image_url: sanitizeUrl(attachment.image_url),
thumb_url: sanitizeUrl(attachment.thumb_url),
});
} else {
const attachmentType = getAttachmentType(attachment);
// allow single card attachment
if (acc.card.length === 1 && attachmentType === 'card') return acc;

if (isFileAttachment(attachment)) {
return renderFile({ ...rest, attachment });
if (attachmentType) {
const Container = CONTAINER_MAP[attachmentType];
acc[attachmentType].push(
<Container
key={`${attachmentType}-${acc[attachmentType].length}`}
{...rest}
attachment={attachment}
/>,
);
}
}
return acc;
},
{
audio: [],
card: [],
file: [],
gallery: [],
image: [],
media: [],
} as GroupedRenderedAttachment,
);

if (isMediaAttachment(attachment)) {
return renderMedia({ ...rest, attachment });
}
if (uploadedImages.length > 1) {
containers['gallery'] = [
<GalleryContainer
key='gallery-container'
{...rest}
attachment={{
images: uploadedImages,
type: 'gallery',
}}
/>,
];
} else if (uploadedImages.length === 1) {
containers['image'] = [
<ImageContainer key='image-container' {...rest} attachment={uploadedImages[0]} />,
];
}
return containers;
};

return renderCard({ ...rest, attachment });
})}
</>
);
const getAttachmentType = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
>(
attachment: AttachmentProps<StreamChatGenerics>['attachments'][number],
): keyof typeof CONTAINER_MAP | null => {
if (isScrapedContent(attachment)) {
return 'card';
} else if (isMediaAttachment(attachment)) {
return 'media';
} else if (isAudioAttachment(attachment)) {
return 'audio';
} else if (isFileAttachment(attachment)) {
return 'file';
}

return null;
};
6 changes: 1 addition & 5 deletions src/components/Attachment/AttachmentActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ const UnMemoizedAttachmentActions = <
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
name?: string,
value?: string,
) => {
if (actionHandler) {
actionHandler(name, value, event);
}
};
) => actionHandler?.(name, value, event);

return (
<div className='str-chat__message-attachment-actions'>
Expand Down
Loading