Skip to content

Commit

Permalink
Merge branch 'release-v11'
Browse files Browse the repository at this point in the history
  • Loading branch information
arnautov-anton committed Sep 4, 2024
2 parents 0e4a6f1 + 153bd75 commit a39ceda
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 67 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
## [11.23.9](https://github.com/GetStream/stream-chat-react/compare/v11.23.8...v11.23.9) (2024-09-04)


* MessageActions adjustments ([#2472](https://github.com/GetStream/stream-chat-react/issues/2472)) ([fbd1b6f](https://github.com/GetStream/stream-chat-react/commit/fbd1b6fd0843d94f250de4158b144ee65eb9bdaf))

## [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)


### Bug Fixes

* 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))

## [11.23.8](https://github.com/GetStream/stream-chat-react/compare/v11.23.7...v11.23.8) (2024-08-28)


### Chores

* **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))

## [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)


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
"emoji-mart": "^5.4.0",
"react": "^18.0.0 || ^17.0.0 || ^16.8.0",
"react-dom": "^18.0.0 || ^17.0.0 || ^16.8.0",
"stream-chat": "^8.33.1"
"stream-chat": "^8.39.0"
},
"peerDependenciesMeta": {
"@breezystack/lamejs": {
Expand Down
9 changes: 2 additions & 7 deletions src/components/Message/MessageOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ReactionIcon as DefaultReactionIcon,
ThreadIcon as DefaultThreadIcon,
} from './icons';
import { MESSAGE_ACTIONS, showMessageActionsBox } from './utils';
import { MESSAGE_ACTIONS } from './utils';

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

Expand Down Expand Up @@ -47,7 +47,6 @@ const UnMemoizedMessageOptions = <
} = props;

const {
customMessageActions,
getMessageActions,
handleOpenThread: contextHandleOpenThread,
initialMessage,
Expand All @@ -62,8 +61,6 @@ const UnMemoizedMessageOptions = <
const handleOpenThread = propHandleOpenThread || contextHandleOpenThread;

const messageActions = getMessageActions();
const showActionsBox =
showMessageActionsBox(messageActions, threadList) || !!customMessageActions;

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

return (
<div className={rootClassName} data-testid='message-options'>
{showActionsBox && (
<MessageActions ActionsIcon={ActionsIcon} messageWrapperRef={messageWrapperRef} />
)}
<MessageActions ActionsIcon={ActionsIcon} messageWrapperRef={messageWrapperRef} />
{shouldShowReplies && (
<button
aria-label={t('aria/Open Thread')}
Expand Down
67 changes: 32 additions & 35 deletions src/components/Message/__tests__/MessageOptions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { MessageSimple } from '../MessageSimple';
import { ACTIONS_NOT_WORKING_IN_THREAD, MESSAGE_ACTIONS } from '../utils';

import { Attachment } from '../../Attachment';
import { MessageActions as MessageActionsMock } from '../../MessageActions';

import { ChannelActionProvider } from '../../../context/ChannelActionContext';
import { ChannelStateProvider } from '../../../context/ChannelStateContext';
Expand All @@ -23,9 +22,7 @@ import {
getTestClientWithUser,
} from '../../../mock-builders';

jest.mock('../../MessageActions', () => ({
MessageActions: jest.fn(() => <div />),
}));
const MESSAGE_ACTIONS_TEST_ID = 'message-actions';

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

it('should render message actions', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
});

it('should not show message actions button if actions are disabled', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: { messageActions: [] },
});
expect(MessageActionsMock).not.toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
});

it('should not show actions box for message in thread if only non-thread actions are available', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: { messageActions: ACTIONS_NOT_WORKING_IN_THREAD, threadList: true },
});
expect(MessageActionsMock).not.toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
});

it('should show actions box for message in thread if not only non-thread actions are available', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
messageActions: [...ACTIONS_NOT_WORKING_IN_THREAD, MESSAGE_ACTIONS.delete],
threadList: true,
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
});

it('should show actions box for a message in thread if custom actions provided are non-thread', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
customMessageActions: ACTIONS_NOT_WORKING_IN_THREAD,
messageActions: ACTIONS_NOT_WORKING_IN_THREAD,
threadList: true,
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).toHaveBeenCalled();
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
});

it('should not show actions box for message outside thread with single action "react"', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
messageActions: [MESSAGE_ACTIONS.react],
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).not.toHaveBeenCalled();
expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
});

it('should show actions box for message outside thread with single action "react" if custom actions available', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
customMessageActions: [MESSAGE_ACTIONS.react],
messageActions: [MESSAGE_ACTIONS.react],
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
});

it('should not show actions box for message outside thread with single action "reply"', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
messageActions: [MESSAGE_ACTIONS.reply],
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).not.toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
});

it('should show actions box for message outside thread with single action "reply" if custom actions available', async () => {
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
customMessageActions: [MESSAGE_ACTIONS.reply],
messageActions: [MESSAGE_ACTIONS.reply],
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
});

it('should not show actions box for message outside thread with two actions "react" & "reply"', async () => {
const actions = [MESSAGE_ACTIONS.react, MESSAGE_ACTIONS.reply];
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
messageActions: actions,
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).not.toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).not.toBeInTheDocument();
});

it('should show actions box for message outside thread with single actions "react" & "reply" if custom actions available', async () => {
const actions = [MESSAGE_ACTIONS.react, MESSAGE_ACTIONS.reply];
await renderMessageOptions({
const { queryByTestId } = await renderMessageOptions({
channelStateOpts: { channelCapabilities: minimumCapabilitiesToRenderMessageActions },
customMessageProps: {
customMessageActions: actions,
messageActions: actions,
},
});
// eslint-disable-next-line jest/prefer-called-with
expect(MessageActionsMock).toHaveBeenCalled();

expect(queryByTestId(MESSAGE_ACTIONS_TEST_ID)).toBeInTheDocument();
});
});
50 changes: 42 additions & 8 deletions src/components/Message/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import type { TFunction } from 'i18next';
import type { MessageResponse, Mute, StreamChat, UserResponse } from 'stream-chat';
import type { PinPermissions } from './hooks';
import type { MessageProps } from './types';
import type { MessageContextValue, StreamMessage } from '../../context';
import type {
ComponentContextValue,
CustomMessageActions,
MessageContextValue,
StreamMessage,
} from '../../context';
import type { DefaultStreamChatGenerics } from '../../types/types';

/**
Expand Down Expand Up @@ -206,26 +211,55 @@ export const ACTIONS_NOT_WORKING_IN_THREAD = [
MESSAGE_ACTIONS.markUnread,
];

/**
* @deprecated use `shouldRenderMessageActions` instead
*/
export const showMessageActionsBox = (
actions: MessageActionsArray,
inThread?: boolean | undefined,
) => {
if (actions.length === 0) {
return false;
}
) => shouldRenderMessageActions({ inThread, messageActions: actions });

export const shouldRenderMessageActions = <
SCG extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
>({
customMessageActions,
CustomMessageActionsList,
inThread,
messageActions,
}: {
messageActions: MessageActionsArray;
customMessageActions?: CustomMessageActions<SCG>;
CustomMessageActionsList?: ComponentContextValue<SCG>['CustomMessageActionsList'];
inThread?: boolean;
}) => {
if (
typeof CustomMessageActionsList !== 'undefined' ||
typeof customMessageActions !== 'undefined'
)
return true;

if (!messageActions.length) return false;

if (
inThread &&
actions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0
messageActions.filter((action) => !ACTIONS_NOT_WORKING_IN_THREAD.includes(action)).length === 0
) {
return false;
}

if (actions.length === 1 && (actions.includes('react') || actions.includes('reply'))) {
if (
messageActions.length === 1 &&
(messageActions.includes(MESSAGE_ACTIONS.react) ||
messageActions.includes(MESSAGE_ACTIONS.reply))
) {
return false;
}

if (actions.length === 2 && actions.includes('react') && actions.includes('reply')) {
if (
messageActions.length === 2 &&
messageActions.includes(MESSAGE_ACTIONS.react) &&
messageActions.includes(MESSAGE_ACTIONS.reply)
) {
return false;
}

Expand Down
Loading

0 comments on commit a39ceda

Please sign in to comment.