Skip to content

Commit a39ceda

Browse files
Merge branch 'release-v11'
2 parents 0e4a6f1 + 153bd75 commit a39ceda

File tree

7 files changed

+113
-67
lines changed

7 files changed

+113
-67
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1+
## [11.23.9](https://github.com/GetStream/stream-chat-react/compare/v11.23.8...v11.23.9) (2024-09-04)
2+
3+
4+
* MessageActions adjustments ([#2472](https://github.com/GetStream/stream-chat-react/issues/2472)) ([fbd1b6f](https://github.com/GetStream/stream-chat-react/commit/fbd1b6fd0843d94f250de4158b144ee65eb9bdaf))
5+
16
## [12.0.0-rc.10](https://github.com/GetStream/stream-chat-react/compare/v12.0.0-rc.9...v12.0.0-rc.10) (2024-08-30)
27

38

49
### Bug Fixes
510

611
* address the circular dependencies among TranslationContext and Streami18n ([#2483](https://github.com/GetStream/stream-chat-react/issues/2483)) ([b91fd9a](https://github.com/GetStream/stream-chat-react/commit/b91fd9aa6fcdbdd9ec1fe7342c58011a0d34116d))
712

13+
## [11.23.8](https://github.com/GetStream/stream-chat-react/compare/v11.23.7...v11.23.8) (2024-08-28)
14+
15+
16+
### Chores
17+
18+
* **deps:** bump version of stream-chat in peerDeps ([#2481](https://github.com/GetStream/stream-chat-react/issues/2481)) ([466385d](https://github.com/GetStream/stream-chat-react/commit/466385daeb4eeb2fb22964738e533c177a5ef29f))
19+
820
## [12.0.0-rc.9](https://github.com/GetStream/stream-chat-react/compare/v12.0.0-rc.8...v12.0.0-rc.9) (2024-08-22)
921

1022

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
"emoji-mart": "^5.4.0",
131131
"react": "^18.0.0 || ^17.0.0 || ^16.8.0",
132132
"react-dom": "^18.0.0 || ^17.0.0 || ^16.8.0",
133-
"stream-chat": "^8.33.1"
133+
"stream-chat": "^8.39.0"
134134
},
135135
"peerDependenciesMeta": {
136136
"@breezystack/lamejs": {

src/components/Message/MessageOptions.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
ReactionIcon as DefaultReactionIcon,
66
ThreadIcon as DefaultThreadIcon,
77
} from './icons';
8-
import { MESSAGE_ACTIONS, showMessageActionsBox } from './utils';
8+
import { MESSAGE_ACTIONS } from './utils';
99

1010
import { MessageActions } from '../MessageActions';
1111

@@ -47,7 +47,6 @@ const UnMemoizedMessageOptions = <
4747
} = props;
4848

4949
const {
50-
customMessageActions,
5150
getMessageActions,
5251
handleOpenThread: contextHandleOpenThread,
5352
initialMessage,
@@ -62,8 +61,6 @@ const UnMemoizedMessageOptions = <
6261
const handleOpenThread = propHandleOpenThread || contextHandleOpenThread;
6362

6463
const messageActions = getMessageActions();
65-
const showActionsBox =
66-
showMessageActionsBox(messageActions, threadList) || !!customMessageActions;
6764

6865
const shouldShowReactions = messageActions.indexOf(MESSAGE_ACTIONS.react) > -1;
6966
const shouldShowReplies =
@@ -85,9 +82,7 @@ const UnMemoizedMessageOptions = <
8582

8683
return (
8784
<div className={rootClassName} data-testid='message-options'>
88-
{showActionsBox && (
89-
<MessageActions ActionsIcon={ActionsIcon} messageWrapperRef={messageWrapperRef} />
90-
)}
85+
<MessageActions ActionsIcon={ActionsIcon} messageWrapperRef={messageWrapperRef} />
9186
{shouldShowReplies && (
9287
<button
9388
aria-label={t('aria/Open Thread')}

src/components/Message/__tests__/MessageOptions.test.js

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { MessageSimple } from '../MessageSimple';
99
import { ACTIONS_NOT_WORKING_IN_THREAD, MESSAGE_ACTIONS } from '../utils';
1010

1111
import { Attachment } from '../../Attachment';
12-
import { MessageActions as MessageActionsMock } from '../../MessageActions';
1312

1413
import { ChannelActionProvider } from '../../../context/ChannelActionContext';
1514
import { ChannelStateProvider } from '../../../context/ChannelStateContext';
@@ -23,9 +22,7 @@ import {
2322
getTestClientWithUser,
2423
} from '../../../mock-builders';
2524

26-
jest.mock('../../MessageActions', () => ({
27-
MessageActions: jest.fn(() => <div />),
28-
}));
25+
const MESSAGE_ACTIONS_TEST_ID = 'message-actions';
2926

3027
const minimumCapabilitiesToRenderMessageActions = { 'delete-any-message': true };
3128
const alice = generateUser({ name: 'alice' });
@@ -185,122 +182,122 @@ describe('<MessageOptions />', () => {
185182
});
186183

187184
it('should render message actions', async () => {
188-
await renderMessageOptions({
185+
const { queryByTestId } = await renderMessageOptions({
189186
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
190187
});
191-
// eslint-disable-next-line jest/prefer-called-with
192-
expect(MessageActionsMock).toHaveBeenCalled();
188+
189+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
193190
});
194191

195192
it('should not show message actions button if actions are disabled', async () => {
196-
await renderMessageOptions({
193+
const { queryByTestId } = await renderMessageOptions({
197194
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
198195
customMessageProps: { messageActions: [] },
199196
});
200-
expect(MessageActionsMock).not.toHaveBeenCalled();
197+
198+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
201199
});
202200

203201
it('should not show actions box for message in thread if only non-thread actions are available', async () => {
204-
await renderMessageOptions({
202+
const { queryByTestId } = await renderMessageOptions({
205203
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
206204
customMessageProps: { messageActions: ACTIONS_NOT_WORKING_IN_THREAD, threadList: true },
207205
});
208-
expect(MessageActionsMock).not.toHaveBeenCalled();
206+
207+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
209208
});
210209

211210
it('should show actions box for message in thread if not only non-thread actions are available', async () => {
212-
await renderMessageOptions({
211+
const { queryByTestId } = await renderMessageOptions({
213212
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
214213
customMessageProps: {
215214
messageActions: [...ACTIONS_NOT_WORKING_IN_THREAD, MESSAGE_ACTIONS.delete],
216215
threadList: true,
217216
},
218217
});
219-
// eslint-disable-next-line jest/prefer-called-with
220-
expect(MessageActionsMock).toHaveBeenCalled();
218+
219+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
221220
});
222221

223222
it('should show actions box for a message in thread if custom actions provided are non-thread', async () => {
224-
await renderMessageOptions({
223+
const { queryByTestId } = await renderMessageOptions({
225224
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
226225
customMessageProps: {
227226
customMessageActions: ACTIONS_NOT_WORKING_IN_THREAD,
228227
messageActions: ACTIONS_NOT_WORKING_IN_THREAD,
229228
threadList: true,
230229
},
231230
});
232-
// eslint-disable-next-line jest/prefer-called-with
233-
expect(MessageActionsMock).toHaveBeenCalled();
231+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
234232
});
235233

236234
it('should not show actions box for message outside thread with single action "react"', async () => {
237-
await renderMessageOptions({
235+
const { queryByTestId } = await renderMessageOptions({
238236
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
239237
customMessageProps: {
240238
messageActions: [MESSAGE_ACTIONS.react],
241239
},
242240
});
243-
// eslint-disable-next-line jest/prefer-called-with
244-
expect(MessageActionsMock).not.toHaveBeenCalled();
241+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
245242
});
246243

247244
it('should show actions box for message outside thread with single action "react" if custom actions available', async () => {
248-
await renderMessageOptions({
245+
const { queryByTestId } = await renderMessageOptions({
249246
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
250247
customMessageProps: {
251248
customMessageActions: [MESSAGE_ACTIONS.react],
252249
messageActions: [MESSAGE_ACTIONS.react],
253250
},
254251
});
255-
// eslint-disable-next-line jest/prefer-called-with
256-
expect(MessageActionsMock).toHaveBeenCalled();
252+
253+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
257254
});
258255

259256
it('should not show actions box for message outside thread with single action "reply"', async () => {
260-
await renderMessageOptions({
257+
const { queryByTestId } = await renderMessageOptions({
261258
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
262259
customMessageProps: {
263260
messageActions: [MESSAGE_ACTIONS.reply],
264261
},
265262
});
266-
// eslint-disable-next-line jest/prefer-called-with
267-
expect(MessageActionsMock).not.toHaveBeenCalled();
263+
264+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
268265
});
269266

270267
it('should show actions box for message outside thread with single action "reply" if custom actions available', async () => {
271-
await renderMessageOptions({
268+
const { queryByTestId } = await renderMessageOptions({
272269
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
273270
customMessageProps: {
274271
customMessageActions: [MESSAGE_ACTIONS.reply],
275272
messageActions: [MESSAGE_ACTIONS.reply],
276273
},
277274
});
278-
// eslint-disable-next-line jest/prefer-called-with
279-
expect(MessageActionsMock).toHaveBeenCalled();
275+
276+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
280277
});
281278

282279
it('should not show actions box for message outside thread with two actions "react" & "reply"', async () => {
283280
const actions = [MESSAGE_ACTIONS.react, MESSAGE_ACTIONS.reply];
284-
await renderMessageOptions({
281+
const { queryByTestId } = await renderMessageOptions({
285282
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
286283
customMessageProps: {
287284
messageActions: actions,
288285
},
289286
});
290-
// eslint-disable-next-line jest/prefer-called-with
291-
expect(MessageActionsMock).not.toHaveBeenCalled();
287+
288+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
292289
});
293290

294291
it('should show actions box for message outside thread with single actions "react" & "reply" if custom actions available', async () => {
295292
const actions = [MESSAGE_ACTIONS.react, MESSAGE_ACTIONS.reply];
296-
await renderMessageOptions({
293+
const { queryByTestId } = await renderMessageOptions({
297294
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
298295
customMessageProps: {
299296
customMessageActions: actions,
300297
messageActions: actions,
301298
},
302299
});
303-
// eslint-disable-next-line jest/prefer-called-with
304-
expect(MessageActionsMock).toHaveBeenCalled();
300+
301+
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
305302
});
306303
});

src/components/Message/utils.tsx

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ import type { TFunction } from 'i18next';
55
import type { MessageResponse, Mute, StreamChat, UserResponse } from 'stream-chat';
66
import type { PinPermissions } from './hooks';
77
import type { MessageProps } from './types';
8-
import type { MessageContextValue, StreamMessage } from '../../context';
8+
import type {
9+
ComponentContextValue,
10+
CustomMessageActions,
11+
MessageContextValue,
12+
StreamMessage,
13+
} from '../../context';
914
import type { DefaultStreamChatGenerics } from '../../types/types';
1015

1116
/**
@@ -206,26 +211,55 @@ export const ACTIONS_NOT_WORKING_IN_THREAD = [
206211
MESSAGE_ACTIONS.markUnread,
207212
];
208213

214+
/**
215+
* @deprecated use `shouldRenderMessageActions` instead
216+
*/
209217
export const showMessageActionsBox = (
210218
actions: MessageActionsArray,
211219
inThread?: boolean | undefined,
212-
) => {
213-
if (actions.length === 0) {
214-
return false;
215-
}
220+
) => shouldRenderMessageActions({ inThread, messageActions: actions });
221+
222+
export const shouldRenderMessageActions = <
223+
SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
224+
>({
225+
customMessageActions,
226+
CustomMessageActionsList,
227+
inThread,
228+
messageActions,
229+
}: {
230+
messageActions: MessageActionsArray;
231+
customMessageActions?: CustomMessageActions<SCG>;
232+
CustomMessageActionsList?: ComponentContextValue<SCG>['CustomMessageActionsList'];
233+
inThread?: boolean;
234+
}) => {
235+
if (
236+
typeof CustomMessageActionsList !== 'undefined' ||
237+
typeof customMessageActions !== 'undefined'
238+
)
239+
return true;
240+
241+
if (!messageActions.length) return false;
216242

217243
if (
218244
inThread &&
219-
actions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0
245+
messageActions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0
220246
) {
221247
return false;
222248
}
223249

224-
if (actions.length === 1 && (actions.includes('react') || actions.includes('reply'))) {
250+
if (
251+
messageActions.length === 1 &&
252+
(messageActions.includes(MESSAGE_ACTIONS.react) ||
253+
messageActions.includes(MESSAGE_ACTIONS.reply))
254+
) {
225255
return false;
226256
}
227257

228-
if (actions.length === 2 && actions.includes('react') && actions.includes('reply')) {
258+
if (
259+
messageActions.length === 2 &&
260+
messageActions.includes(MESSAGE_ACTIONS.react) &&
261+
messageActions.includes(MESSAGE_ACTIONS.reply)
262+
) {
229263
return false;
230264
}
231265

0 commit comments

Comments
 (0)