Skip to content

Commit 5a3d9c2

Browse files
committed
perf: remove editing state from channel ctx and add composer ctx
1 parent 4aa4dd0 commit 5a3d9c2

File tree

7 files changed

+69
-19
lines changed

7 files changed

+69
-19
lines changed

package/src/components/Channel/Channel.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { ChannelContextValue, ChannelProvider } from '../../contexts/channelCont
4646
import type { UseChannelStateValue } from '../../contexts/channelsStateContext/useChannelState';
4747
import { useChannelState } from '../../contexts/channelsStateContext/useChannelState';
4848
import { ChatContextValue, useChatContext } from '../../contexts/chatContext/ChatContext';
49+
import { MessageComposerProvider } from '../../contexts/messageComposerContext/MessageComposerContext';
4950
import {
5051
InputMessageInputContextValue,
5152
MessageInputProvider,
@@ -1597,7 +1598,6 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
15971598
channel,
15981599
channelUnreadState,
15991600
disabled: !!channel?.data?.frozen,
1600-
editing,
16011601
EmptyStateIndicator,
16021602
enableMessageGroupingByUser,
16031603
enforceUniqueReaction,
@@ -1838,6 +1838,11 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
18381838
typing: channelState.typing ?? {},
18391839
});
18401840

1841+
const messageComposerContext = useMemo(
1842+
() => ({ channel, editing, thread, threadInstance }),
1843+
[channel, editing, thread, threadInstance],
1844+
);
1845+
18411846
// TODO: replace the null view with appropriate message. Currently this is waiting a design decision.
18421847
if (deleted) {
18431848
return null;
@@ -1868,9 +1873,11 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
18681873
<PaginatedMessageListProvider value={messageListContext}>
18691874
<MessagesProvider value={messagesContext}>
18701875
<ThreadProvider value={threadContext}>
1871-
<MessageInputProvider value={inputMessageInputContext}>
1872-
<View style={{ height: '100%' }}>{children}</View>
1873-
</MessageInputProvider>
1876+
<MessageComposerProvider value={messageComposerContext}>
1877+
<MessageInputProvider value={inputMessageInputContext}>
1878+
<View style={{ height: '100%' }}>{children}</View>
1879+
</MessageInputProvider>
1880+
</MessageComposerProvider>
18741881
</ThreadProvider>
18751882
</MessagesProvider>
18761883
</PaginatedMessageListProvider>

package/src/components/Channel/hooks/useCreateChannelContext.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ export const useCreateChannelContext = ({
66
channel,
77
channelUnreadState,
88
disabled,
9-
editing,
109
EmptyStateIndicator,
1110
enableMessageGroupingByUser,
1211
enforceUniqueReaction,
@@ -46,14 +45,12 @@ export const useCreateChannelContext = ({
4645
const readUsersLength = readUsers.length;
4746
const readUsersLastReads = readUsers.map(({ last_read }) => last_read.toISOString()).join();
4847
const stringifiedChannelUnreadState = JSON.stringify(channelUnreadState);
49-
const editingDep = editing ? editing.id : '';
5048

5149
const channelContext: ChannelContextValue = useMemo(
5250
() => ({
5351
channel,
5452
channelUnreadState,
5553
disabled,
56-
editing,
5754
EmptyStateIndicator,
5855
enableMessageGroupingByUser,
5956
enforceUniqueReaction,
@@ -89,7 +86,6 @@ export const useCreateChannelContext = ({
8986
[
9087
channelId,
9188
disabled,
92-
editingDep,
9389
error,
9490
isChannelActive,
9591
highlightedMessageId,

package/src/components/MessageInput/MessageInput.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ import {
3636
ChannelContextValue,
3737
useChannelContext,
3838
} from '../../contexts/channelContext/ChannelContext';
39+
import {
40+
MessageComposerContextValue,
41+
useMessageComposerContext,
42+
} from '../../contexts/messageComposerContext/MessageComposerContext';
3943
import { useAttachmentManagerState } from '../../contexts/messageInputContext/hooks/useAttachmentManagerState';
4044
import { useMessageComposer } from '../../contexts/messageInputContext/hooks/useMessageComposer';
4145
import { useMessageComposerHasSendableData } from '../../contexts/messageInputContext/hooks/useMessageComposerHasSendableData';
@@ -107,7 +111,7 @@ type MessageInputPropsWithContext = Pick<
107111
'AttachmentPickerSelectionBar'
108112
> &
109113
Pick<ChatContextValue, 'isOnline'> &
110-
Pick<ChannelContextValue, 'channel' | 'editing' | 'members' | 'threadList' | 'watchers'> &
114+
Pick<ChannelContextValue, 'channel' | 'members' | 'threadList' | 'watchers'> &
111115
Pick<
112116
MessageInputContextValue,
113117
| 'additionalTextInputProps'
@@ -149,7 +153,8 @@ type MessageInputPropsWithContext = Pick<
149153
| 'StopMessageStreamingButton'
150154
> &
151155
Pick<MessagesContextValue, 'Reply'> &
152-
Pick<TranslationContextValue, 't'>;
156+
Pick<TranslationContextValue, 't'> &
157+
Pick<MessageComposerContextValue, 'editing'>;
153158

154159
const textComposerStateSelector = (state: TextComposerState) => ({
155160
command: state.command,
@@ -937,7 +942,8 @@ export const MessageInput = (props: MessageInputProps) => {
937942
const { isOnline } = useChatContext();
938943
const ownCapabilities = useOwnCapabilitiesContext();
939944

940-
const { channel, editing, members, threadList, watchers } = useChannelContext();
945+
const { channel, members, threadList, watchers } = useChannelContext();
946+
const { editing } = useMessageComposerContext();
941947

942948
const {
943949
additionalTextInputProps,

package/src/components/MessageInput/__tests__/AttachButton.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react';
22

3-
import { act, render, renderHook, screen, userEvent, waitFor } from '@testing-library/react-native';
3+
import { act, render, screen, userEvent, waitFor } from '@testing-library/react-native';
44

5-
import { OverlayProvider, useMessageInputContext } from '../../../contexts';
5+
import { OverlayProvider } from '../../../contexts';
66

77
import { initiateClientWithChannels } from '../../../mock-builders/api/initiateClientWithChannels';
88
import * as NativeHandler from '../../../native';

package/src/contexts/channelContext/ChannelContext.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { PropsWithChildren, useContext } from 'react';
22

3-
import type { Channel, ChannelState, LocalMessage } from 'stream-chat';
3+
import type { Channel, ChannelState } from 'stream-chat';
44

55
import { MarkReadFunctionOptions } from '../../components/Channel/Channel';
66
import type { EmptyStateProps } from '../../components/Indicators/EmptyStateIndicator';
@@ -35,7 +35,6 @@ export type ChannelContextValue = {
3535
* @overrideType Channel
3636
*/
3737
channel: Channel;
38-
editing?: LocalMessage;
3938
/**
4039
* Custom UI component to display empty state when channel has no messages.
4140
*
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React, { useContext } from 'react';
2+
3+
import { LocalMessage } from 'stream-chat';
4+
5+
import { ChannelProps } from '../../components';
6+
import { ThreadContextValue } from '../threadContext/ThreadContext';
7+
import { DEFAULT_BASE_CONTEXT_VALUE } from '../utils/defaultBaseContextValue';
8+
import { isTestEnvironment } from '../utils/isTestEnvironment';
9+
10+
export type MessageComposerContextValue = {
11+
channel: ChannelProps['channel'];
12+
thread: ThreadContextValue['thread'];
13+
threadInstance: ThreadContextValue['threadInstance'];
14+
editing?: LocalMessage;
15+
};
16+
17+
export const MessageComposerContext = React.createContext(
18+
DEFAULT_BASE_CONTEXT_VALUE as MessageComposerContextValue,
19+
);
20+
21+
type Props = React.PropsWithChildren<{
22+
value: MessageComposerContextValue;
23+
}>;
24+
25+
export const MessageComposerProvider = ({ children, value }: Props) => (
26+
<MessageComposerContext.Provider value={value}>{children}</MessageComposerContext.Provider>
27+
);
28+
29+
export const useMessageComposerContext = () => {
30+
const contextValue = useContext(MessageComposerContext) as unknown as MessageComposerContextValue;
31+
32+
if (contextValue === DEFAULT_BASE_CONTEXT_VALUE && !isTestEnvironment()) {
33+
throw new Error(
34+
'The useMessageComposerContext hook was called outside of the MessageComposerContext provider.',
35+
);
36+
}
37+
38+
return contextValue;
39+
};

package/src/contexts/messageInputContext/hooks/useMessageComposer.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import { useEffect, useMemo } from 'react';
22

33
import { FixedSizeQueueCache, MessageComposer } from 'stream-chat';
44

5-
import { useChannelContext } from '../../../contexts/channelContext/ChannelContext';
65
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
7-
import { useThreadContext } from '../../../contexts/threadContext/ThreadContext';
6+
import { useMessageComposerContext } from '../../messageComposerContext/MessageComposerContext';
87

98
const queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);
109

1110
export const useMessageComposer = () => {
1211
const { client } = useChatContext();
13-
const { channel, editing: editedMessage } = useChannelContext();
12+
const {
13+
channel,
14+
editing: editedMessage,
15+
thread: parentMessage,
16+
threadInstance,
17+
} = useMessageComposerContext();
1418

1519
// legacy thread will receive new composer
16-
const { thread: parentMessage, threadInstance } = useThreadContext();
1720

1821
const cachedEditedMessage = useMemo(() => {
1922
if (!editedMessage) return undefined;

0 commit comments

Comments
 (0)