Skip to content

Commit eac76dc

Browse files
authored
fix: recognize async moderated shadow blocked messages as blocked (#3131)
### 🎯 Goal https://linear.app/stream/issue/REACT-945/handle-shadow-blocked-images-in-react-chat-sdk `isMessageBlocked` method decides if we should display the `MessageBlocked` placeholder for a message. This method didn't categorize `shadowed` messages as blocked (probably because these messages are not displayed in message list, except when they change from `shadowed: false` to `shadowed: true`) ### 🛠 Implementation details _Provide a description of the implementation_ ### 🎨 UI Changes _Add relevant screenshots_
1 parent fbb3556 commit eac76dc

File tree

4 files changed

+44
-10
lines changed

4 files changed

+44
-10
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
"react-dom": "^19.0.0",
171171
"sass": "^1.97.2",
172172
"semantic-release": "^25.0.2",
173-
"stream-chat": "^9.41.0",
173+
"stream-chat": "^9.41.1",
174174
"typescript": "^5.4.5",
175175
"typescript-eslint": "^8.17.0",
176176
"vite": "^7.3.1",

src/components/Message/__tests__/utils.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { generateMessage, generateReaction, generateUser } from 'mock-builders';
22
import { fromPartial } from '@total-typescript/shoehorn';
33
import type { TFunction } from 'i18next';
4-
import type { ChannelConfigWithInfo, MessageResponse, Mute } from 'stream-chat';
4+
import type {
5+
ChannelConfigWithInfo,
6+
LocalMessage,
7+
MessageResponse,
8+
Mute,
9+
} from 'stream-chat';
510
import type { StreamChat } from 'stream-chat';
611
import {
712
countReactions,
@@ -15,6 +20,7 @@ import {
1520
getMessageActions,
1621
getNonImageAttachments,
1722
getReadByTooltipText,
23+
isMessageBlocked,
1824
isUserMuted,
1925
mapToUserNameOrId,
2026
MESSAGE_ACTIONS,
@@ -543,4 +549,31 @@ describe('Message utils', () => {
543549
);
544550
});
545551
});
552+
553+
describe('isMessageBlocked function', () => {
554+
it('returns true when message.shadowed is true', () => {
555+
const message = fromPartial<LocalMessage>({
556+
shadowed: true,
557+
type: 'regular',
558+
});
559+
expect(isMessageBlocked(message)).toBe(true);
560+
});
561+
562+
it('returns true for moderation remove error messages when not shadowed', () => {
563+
const message = fromPartial<LocalMessage>({
564+
moderation: { action: 'remove' },
565+
shadowed: false,
566+
type: 'error',
567+
});
568+
expect(isMessageBlocked(message)).toBe(true);
569+
});
570+
571+
it('returns false when message is not shadowed and not a moderation remove error', () => {
572+
const message = fromPartial<LocalMessage>({
573+
shadowed: false,
574+
type: 'regular',
575+
});
576+
expect(isMessageBlocked(message)).toBe(false);
577+
});
578+
});
546579
});

src/components/Message/utils.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,12 @@ export const isMessageBounced = (
404404
message.moderation?.action === 'bounce');
405405

406406
export const isMessageBlocked = (
407-
message: Pick<LocalMessage, 'type' | 'moderation' | 'moderation_details'>,
407+
message: Pick<LocalMessage, 'type' | 'moderation' | 'moderation_details' | 'shadowed'>,
408408
) =>
409-
message.type === 'error' &&
410-
(message.moderation_details?.action === 'MESSAGE_RESPONSE_ACTION_REMOVE' ||
411-
message.moderation?.action === 'remove');
409+
message.shadowed ||
410+
(message.type === 'error' &&
411+
(message.moderation_details?.action === 'MESSAGE_RESPONSE_ACTION_REMOVE' ||
412+
message.moderation?.action === 'remove'));
412413

413414
export const isMessageDeleted = (message: LocalMessage): boolean =>
414415
Boolean(message.deleted_at || message.type === 'deleted' || message.deleted_for_me);

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7753,10 +7753,10 @@ stdin-discarder@^0.2.2:
77537753
resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.2.2.tgz#390037f44c4ae1a1ae535c5fe38dc3aba8d997be"
77547754
integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==
77557755

7756-
stream-chat@^9.41.0:
7757-
version "9.41.0"
7758-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.41.0.tgz#ad88d7919aaf1d3c35b4a431a8cd464cb640f146"
7759-
integrity sha512-Rgp3vULGKYxHZ/aCeundly6ngdBGttTPz+YknmWhbqvNlEhPB/RM61CpQPHgPyfkSm+osJT3tEV9fKd+I/S77g==
7756+
stream-chat@^9.41.1:
7757+
version "9.41.1"
7758+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.41.1.tgz#a877c8aa800d78b497eec2fad636345d4422309c"
7759+
integrity sha512-W8zjfINYol2UtdRMz2t/NN2GyjDrvb4pJgKmhtuRYzCY1u0Cjezcsu5OCNgyAM0QsenlY6tRqnvAU8Qam5R49Q==
77607760
dependencies:
77617761
"@types/jsonwebtoken" "^9.0.8"
77627762
"@types/ws" "^8.5.14"

0 commit comments

Comments
 (0)