Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(emoji-mart): simplify EmojiPicker & emojiSearchIndex #2117

Merged
merged 20 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1c797bd
Remove EmojiPicker & related code
arnautov-anton Oct 6, 2023
ebd2c3d
[WIP] Adjust tests, return CooldownTimer
arnautov-anton Oct 9, 2023
bc67a60
[WIP] Add new EmojiPicker, adjust message inputs
arnautov-anton Oct 10, 2023
727f15d
Re-generate translations
arnautov-anton Oct 11, 2023
e393067
Remove EmojiContext & adjust components
arnautov-anton Oct 11, 2023
b3a841b
Remove emoji-mart re-exports
arnautov-anton Oct 13, 2023
36835de
Adjust types, fix compatibility issues, move EmojiPicker
arnautov-anton Oct 24, 2023
dda9c43
Add "exports" field to the package.json, fix UMD build, add Emojis CJS
arnautov-anton Oct 24, 2023
81e0098
Adjust release guide, add emojiSearchIndex guide
arnautov-anton Oct 24, 2023
4d0131a
Extend on emojiSearchIndex documentation, add to ComponentContext
arnautov-anton Oct 26, 2023
85f62ea
Adjust documentation
arnautov-anton Oct 27, 2023
f978dc0
Fix item Item and List click handlers
arnautov-anton Oct 27, 2023
96d83a1
Remove unused EmojiContext mocks and tests
arnautov-anton Oct 27, 2023
dd0bbb9
Adjust documentation, add review suggestions
arnautov-anton Nov 7, 2023
d240064
Make EmojiPicker load data async
arnautov-anton Nov 8, 2023
c9ca96a
Bump @stream-io/stream-chat-css to v4-rc (#2153)
arnautov-anton Nov 8, 2023
cc86ba5
Reduce emoji-mart peer-dep req., add "node" mod. resolution support
arnautov-anton Nov 9, 2023
7546c7a
Adjust documentation
arnautov-anton Nov 13, 2023
98d5735
Refactor default EmojiPicker, add pickerProps & popperOptions
arnautov-anton Nov 14, 2023
f875a4a
Bump @stream-io/stream-chat-css to v4
arnautov-anton Nov 27, 2023
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
14 changes: 13 additions & 1 deletion docusaurus/docs/React/basics/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,14 @@ const { client } = useChatContext();
The [`Channel`](../components/core-components/channel.mdx) component is a React Context provider that wraps all of the logic, functionality, and UI for an individual chat channel.
It provides five separate contexts to its children:

:::caution
`EmojiContext` has been removed in version `11.0.0`, see related release guides (["Reactions 11.0.0"](../release-guides/reactions-v11.mdx), ["EmojiPicker 11.0.0"](../release-guides/emoji-picker-v11.mdx) and ["emojiSearchIndex 11.0.0"](../release-guides/emoji-search-index-v11.mdx)) to adjust your integration to this new change.
:::

- [`ChannelStateContext`](../components/contexts/channel-state-context.mdx) - stateful data (ex: `messages` or `members`)
- [`ChannelActionContext`](../components/contexts/channel-action-context.mdx) - action handlers (ex: `sendMessage` or `openThread`)
- [`ComponentContext`](../components/contexts/component-context.mdx) - custom component UI overrides (ex: `Avatar` or `Message`)
- [`EmojiContext`](../components/contexts/emoji-context.mdx) - emoji UI components and data (ex: `EmojiPicker` or `emojiConfig`)
- [`EmojiContext`](../components/contexts/emoji-context.mdx) - emoji UI components and data (ex: `EmojiPicker` or `emojiConfig`) - removed in `11.0.0`
- [`TypingContext`](../components/contexts/typing-context.mdx) - object of currently typing users (i.e., `typing`)

### ChannelList
Expand Down Expand Up @@ -172,6 +176,14 @@ The [`MessageInput`](../components/message-input-components/message-input.mdx) c

The [`Thread`](../components/core-components/thread.mdx) component renders a list of replies tied to a single parent message in a channel's main message list. A `Thread` maintains its own state and renders its own `MessageList` and `MessageInput` components.

### Emojis (picker & autocomplete)

The SDK is equipped with features designed to facilitate seamless integration, enabling developers to effortlessly incorporate emoji picker and emoji autocomplete (built on top of [`emoji-mart`](https://github.com/missive/emoji-mart)) functionalities for a comprehensive chat experience.

Starting from version `11.0.0`, these features are entirely optional, requiring integrators to opt-in manually. The decision was made in conjunction with enhanced architecture, aiming to reduce the overall size of the final bundles of our integrators.

Make sure to read ["EmojiPicker 11.0.0"](../release-guides/emoji-picker-v11.mdx) and ["emojiSearchIndex 11.0.0"](../release-guides/emoji-search-index-v11.mdx) release guides for more information.

## Summary

In addition to the above referenced UI components, client instantiation, and user connection, you need little other code to get a fully functioning chat application up and running. See below for an example of the complete code.
Expand Down
4 changes: 4 additions & 0 deletions docusaurus/docs/React/components/contexts/emoji-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ sidebar_position: 5
title: EmojiContext
---

:::caution
`EmojiContext` has been removed in version `11.0.0`, see related release guides (["Reactions 11.0.0"](../release-guides/reactions-v11.mdx), ["EmojiPicker 11.0.0"](../release-guides/emoji-picker-v11.mdx) and ["emojiSearchIndex 11.0.0"](../release-guides/emoji-search-index-v11.mdx)) to adjust your integration to this new change.
:::

The `EmojiContext` is established by the `Channel` component and exposes the `useEmojiContext` hook. This context holds
the UI components and stateful data necessary to render emoji selector functionality.

Expand Down
103 changes: 57 additions & 46 deletions docusaurus/docs/React/components/core-components/channel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -296,45 +296,54 @@ Custom UI component to override default edit message input.
| --------- | ---------------------------------------------------------------------------------- |
| component | <GHComponentLink text='EditMessageForm' path='/MessageInput/EditMessageForm.tsx'/> |

### Emoji
### Emoji (removed in `11.0.0`)

Custom UI component to override default `NimbleEmoji` from `emoji-mart`.

| Type |
| --------- |
| component |

### emojiData
### emojiData (removed in `11.0.0`)

Custom prop to override default `facebook.json` emoji data set from `emoji-mart`.

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

### EmojiIcon
### EmojiIcon (removed in `11.0.0`)

Custom UI component for emoji button in input.

| Type | Default |
| --------- | ----------------------------------------------------------------------- |
| component | <GHComponentLink text='EmojiIconSmall' path='/MessageInput/icons.tsx'/> |

### EmojiIndex
### EmojiIndex (removed in `11.0.0`)

Custom UI component to override default `NimbleEmojiIndex` from `emoji-mart`.
Custom search mechanism class to override default `NimbleEmojiIndex` class from `emoji-mart`.

| Type |
| --------- |
| component |
| Type | Default |
| ----- | ----------------------------------------------------------------------------------------------------------------- |
| class | [NimbleEmojiIndex](https://github.com/missive/emoji-mart/blob/v3.0.1/src/utils/emoji-index/nimble-emoji-index.js) |

### EmojiPicker
### emojiSearchIndex (available since `11.0.0`)

Custom UI component to override default `NimblePicker` from `emoji-mart`.
Custom search mechanism instance or object to enable emoji autocomplete. See ["emojiSearchIndex 11.0.0"](../../release-guides/emoji-search-index-v11.mdx) release guide for more information.

| Type |
| --------- |
| component |
| Type | Default |
| ------ | --------- |
| object | undefined |

### EmojiPicker (changed in `11.0.0`)

Custom UI component to override default `NimblePicker` from `emoji-mart`. Markup structure changed in `11.0.0`, see ["EmojiPicker 11.0.0"](../../release-guides/emoji-picker-v11.mdx) release guide for more information.

| Version | Type | Default |
| ------- | --------- | -------------------------------------------------------------------------------------------------------- |
| >=4.0.0 | component | [NimblePicker](https://github.com/missive/emoji-mart/blob/v3.0.1/src/components/picker/nimble-picker.js) |
| ^11.0.0 | component | undefined |

### EmptyPlaceholder

Expand Down Expand Up @@ -414,48 +423,50 @@ A custom function to provide size configuration for image attachments
Allows to prevent triggering the `channel.watch()` (triggers channel query HTTP request) call when mounting the `Channel` component (the default behavior) with uninitialized (`channel.initialized`) `Channel` instance. That means that no channel data from the back-end will be received neither channel WS events will be delivered to the client. Preventing to initialize the channel on mount allows us to postpone the channel creation in the Stream's DB to a later point in time, for example, when a first message is sent:

```typescript jsx
import {useCallback} from "react";
import { useCallback } from 'react';
import {
getChannel,
MessageInput as StreamMessageInput,
MessageInputProps, MessageToSend,
MessageInputProps,
MessageToSend,
useChannelActionContext,
useChatContext
} from "stream-chat-react";
import {Message, SendMessageOptions} from "stream-chat";
useChatContext,
} from 'stream-chat-react';
import { Message, SendMessageOptions } from 'stream-chat';

import {useChannelInitContext} from "../../context/ChannelInitProvider";
import type { MyStreamChatGenerics } from "../../types";
import { useChannelInitContext } from '../../context/ChannelInitProvider';
import type { MyStreamChatGenerics } from '../../types';

export const MessageInput = (props: MessageInputProps) => {
const {client} = useChatContext();
const {sendMessage} = useChannelActionContext();
const { setInitializedChannelOnMount} = useChannelInitContext();

const submitHandler: MessageInputProps['overrideSubmitHandler'] = useCallback(async (
message: MessageToSend<MyStreamChatGenerics>,
channelCid: string,
customMessageData?: Partial<Message<MyStreamChatGenerics>>,
options?: SendMessageOptions,
) => {
const [channelType, channelId] = channelCid.split(":");
const channel = client.channel(channelType, channelId);
if (!channel.initialized) {
await getChannel({channel, client});
setInitializedChannelOnMount(true);
}

await sendMessage(message, customMessageData, options);
}, [client, sendMessage, setInitializedChannelOnMount]);

return (
<StreamMessageInput {...props} overrideSubmitHandler={submitHandler} />
const { client } = useChatContext();
const { sendMessage } = useChannelActionContext();
const { setInitializedChannelOnMount } = useChannelInitContext();

const submitHandler: MessageInputProps['overrideSubmitHandler'] = useCallback(
async (
message: MessageToSend<MyStreamChatGenerics>,
channelCid: string,
customMessageData?: Partial<Message<MyStreamChatGenerics>>,
options?: SendMessageOptions,
) => {
const [channelType, channelId] = channelCid.split(':');
const channel = client.channel(channelType, channelId);
if (!channel.initialized) {
await getChannel({ channel, client });
setInitializedChannelOnMount(true);
}

await sendMessage(message, customMessageData, options);
},
[client, sendMessage, setInitializedChannelOnMount],
);

return <StreamMessageInput {...props} overrideSubmitHandler={submitHandler} />;
};
```

| Type | Default |
|---------|---------|
| ------- | ------- |
| boolean | true |

### Input
Expand Down Expand Up @@ -662,9 +673,9 @@ Custom UI component for send button.

You can turn on/off thumbnail generation for video attachments

| Type |
| --------- |
| `boolean` |
| Type |
| ------- |
| boolean |

### skipMessageDataMemoization

Expand Down
8 changes: 6 additions & 2 deletions docusaurus/docs/React/components/core-components/chat.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ const i18nInstance = new Streami18n({
});

<Chat client={client} i18nInstance={i18nInstance}>
{// children of Chat component}
</Chat>
{/* children of Chat component */}
</Chat>;
```

| Type |
Expand Down Expand Up @@ -123,6 +123,10 @@ Windows 10 does not support country flag emojis out of the box. It chooses to re
Stream Chat can override this behavior by loading a custom web font that will render images instead (PNGs or SVGs depending
on the platform). Set this prop to true if you want to use these custom emojis for Windows users.

:::caution
If you're moving from older versions to `11.0.0` then make sure to import related stylesheet from `stream-chat-react/css/v2/emoji-replacement.css` as it has been removed from our main stylesheet to reduce final bundle size for integrators who do not wish to use this feature.
:::

| Type | Default |
| ------- | ------- |
| boolean | false |
21 changes: 10 additions & 11 deletions docusaurus/docs/React/guides/channel-list-infinite-scroll.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,19 @@ import { ChannelList, InfiniteScroll } from 'stream-chat-react';
If you would like to adjust the configuration parameters like `threshold`, `reverse` (`PaginatorProps`) or `useCapture`, etc. (`InfiniteScrollProps`), you can create a wrapper component where these props can be set:

```tsx
import {
ChannelList,
InfiniteScroll,
InfiniteScrollProps
} from 'stream-chat-react';

import { ChannelList, InfiniteScroll, InfiniteScrollProps } from 'stream-chat-react';

const Paginator = (props: InfiniteScrollProps) => <InfiniteScroll {...props} threshold={50} />;

...
<ChannelList filters={filters} sort={sort} options={options}
Paginator={Paginator}
showChannelSearch
/>
// ...

<ChannelList
filters={filters}
sort={sort}
options={options}
Paginator={Paginator}
showChannelSearch
/>;
```

Especially the `threshold` prop may need to be set as the default is 250px. That may be too soon to load more channels.
Expand Down
19 changes: 8 additions & 11 deletions docusaurus/docs/React/guides/customization/emoji-picker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ title: Emoji Picker

import CustomEmojiPicker from '../../assets/CustomEmojiPicker.png';

In this example, we will demonstrate how to create a custom Emoji Picker component that can be used in the `MessageInput`.
This component will replace the default [`EmojiPicker`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/EmojiPicker.tsx)
with only breakfast food emojis.
:::caution
Note that this guide is for versions lower than `11.0.0`, the new API has slightly changed. See the ["EmojiPicker 11.0.0"](../../release-guides/emoji-picker-v11.mdx) release guide to help you transition smoothly to the new API.
:::

In this example, we will demonstrate how to create a custom Emoji Picker component that can be used in the `MessageInput`. This component will replace the default [`EmojiPicker`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/EmojiPicker.tsx) with only breakfast food emojis.

## Choose Your Emojis

The default `EmojiPicker` renders individual emoji objects using the [`NimbleEmoji`](https://github.com/missive/emoji-mart/blob/master/src/components/emoji/nimble-emoji.js)
component from [emoji-mart](https://www.npmjs.com/package/emoji-mart). Our custom set of emojis will need to follow the same `NimbleEmoji` props.
`NimbleEmoji` accepts an `emoji` prop, which pertains to either an object mapping of the emoji data or simply the ID (for IDs already existing
in `emoji-mart`). The object mapping of the `emoji` prop has the following type:
The default `EmojiPicker` renders individual emoji objects using the [`NimbleEmoji`](https://github.com/missive/emoji-mart/blob/v3.0.1/src/components/emoji/nimble-emoji.js) component from [emoji-mart](https://www.npmjs.com/package/emoji-mart). Our custom set of emojis will need to follow the same `NimbleEmoji` props. `NimbleEmoji` accepts an `emoji` prop, which pertains to either an object mapping of the emoji data or simply the ID (for IDs already existing in `emoji-mart`). The object mapping of the `emoji` prop has the following type:

```tsx
export interface BaseEmoji {
Expand All @@ -29,8 +28,7 @@ export interface BaseEmoji {
}
```

In this example we will use only the ID and select existing emojis. For a more detailed example of how to construct these emoji objects, please see the
[Reactions Selector and List](../theming/reactions.mdx) section. Below is the array of breakfast emojis we will use:
In this example we will use only the ID and select existing emojis. For a more detailed example of how to construct these emoji objects, please see the [Reactions Selector and List](../theming/reactions.mdx) section. Below is the array of breakfast emojis we will use:

```tsx
const customEmojis = ['fried_egg', 'croissant', 'bacon', 'waffle', 'pancakes', 'doughnut'];
Expand All @@ -43,8 +41,7 @@ loaded into the component library.

## Create the Custom Component

To construct our component, we will utilize the `EmojiContext` to get our `emojiConfig` data. This config object contains the `emojiData` we need for the
`data` prop on the `Emoji` component. Using the `onSelectEmoji` method from the `MessageInputContext`, we can add the onClick functionality to our custom picker.
To construct our component, we will utilize the `EmojiContext` to get our `emojiConfig` data. This config object contains the `emojiData` we need for the `data` prop on the `Emoji` component. Using the `onSelectEmoji` method from the `MessageInputContext`, we can add the onClick functionality to our custom picker.

:::note
The `Emoji` component needs to be wrapped in React's `Suspense` component because it is lazy loaded.
Expand Down
84 changes: 84 additions & 0 deletions docusaurus/docs/React/release-guides/emoji-picker-v11.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
id: emoji-picker-v11
sidebar_position: 3
title: EmojiPicker 11.0.0
keywords: [migration guide, upgrade, emoji picker, breaking changes, v11]
---

import GHComponentLink from '../_docusaurus-components/GHComponentLink';

## Dropping support for built-in `EmojiPicker`

By default - our SDK would ship with `emoji-mart` dependency on top of which our `EmojiPicker` component is built. And since the SDK is using `emoji-mart` for this component - it was also reused for reactions (`ReactionsList` and `ReactionSelector`) and suggestion list (`MessageInput`). This solution proved to be very uncomfortable to work with when it came to replacing either of the mentioned components (or disabling them completely) and the final applications using our SDK would still bundle certain `emoji-mart` parts which weren't needed (or seemingly "disabled") resulting in sub-optimal load times. Maintaining such architecture became a burden so we're switching things a bit.

## Changes to the default component composition (architecture)

SDK's `EmojiPicker` component now comes as two-part "bundle" - a button and an actual picker element. The component now holds its own `open` state which is handled by clicking the button (or anywhere else to close it).

## Switching to opt-in mechanism (BREAKING CHANGE)

We made `emoji-mart` package in our SDK completely optional which means that `EmojiPicker` component is now disabled by default.

### Reinstate the `EmojiPicker` component

To reinstate the previous behavior you'll have to add `emoji-mart` to your packages and make sure the packages come with versions that fit our peer-dependency requirements:

```bash
yarn add emoji-mart @emoji-mart/data @emoji-mart/react
```

Import `EmojiPicker` component from the `stream-chat-react` package:

```tsx
import { Channel } from 'stream-chat-react';
import { EmojiPicker } from 'stream-chat-react/emojis';

// and apply it to the Channel (component context)

const WrappedChannel = ({ children }) => {
return <Channel EmojiPicker={EmojiPicker}>{children}</Channel>;
};
```

### Build your custom `EmojiPicker` (with example)

If `emoji-mart` is too heavy for your use-case and you'd like to build your own you can certainly do so, here's a very simple `EmojiPicker` example built using `emoji-picker-react` package:

```tsx
import EmojiPicker from 'emoji-picker-react';
import { useMessageInputContext } from 'stream-chat-react';

export const CustomEmojiPicker = () => {
const [open, setOpen] = useState(false);

const { insertText, textareaRef } = useMessageInputContext();

return (
<>
<button onClick={() => setOpen((isOpen) => !isOpen)}>Open EmojiPicker</button>

{open && (
<EmojiPicker
onEmojiClick={(emoji, event) => {
insertText(emoji.native);
textareaRef.current?.focus(); // returns focus back to the message input element
}}
/>
)}
</>
);
};

// and pass it down to the `Channel` component
```

You can make the component slightly better using [`FloatingUI`](https://floating-ui.com/) by wrapping the actual picker element to make it float perfectly positioned above the button. See the source of the <GHComponentLink text="EmojiPicker" branch="feat/emoji-picker-delete" as="code" path="/Emojis/EmojiPicker.tsx" /> component which comes with the SDK for inspiration.

## Old `emoji-mart` (v3.0.1)

Even though it's not explicitly provided by our SDK anymore, it's still possible for our integrators to use older version of the `emoji-mart` - specifically version `3.0.1` on top of which our old components were built. We don't recommend using old version of the `emoji-mart` but if you really need to, follow the [`3.0.1` documentation](https://github.com/missive/emoji-mart/tree/v3.0.1#picker) in combination with the previous guide to build your own `EmojiPicker` component with the old `emoji-mart` API. Beware though, if you wish to use slightly modified `emoji-mart` CSS previously supplied by our SDK by default in the main `index.css` file, you'll now have to explicitly import it:

```tsx
import 'stream-chat-react/css/v2/index.css';
import 'stream-chat-react/css/v2/emoji-mart.css';
```
Loading
Loading