Skip to content

Commit 7388456

Browse files
committed
feat: show message blocked component for blocked messages
1 parent 658b372 commit 7388456

File tree

9 files changed

+114
-24
lines changed

9 files changed

+114
-24
lines changed

package/src/components/Channel/Channel.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ import { LoadingIndicator as LoadingIndicatorDefault } from '../Indicators/Loadi
149149
import { KeyboardCompatibleView as KeyboardCompatibleViewDefault } from '../KeyboardCompatibleView/KeyboardCompatibleView';
150150
import { Message as MessageDefault } from '../Message/Message';
151151
import { MessageAvatar as MessageAvatarDefault } from '../Message/MessageSimple/MessageAvatar';
152+
import { MessageBlocked as MessageBlockedDefault } from '../Message/MessageSimple/MessageBlocked';
152153
import { MessageBounce as MessageBounceDefault } from '../Message/MessageSimple/MessageBounce';
153154
import { MessageContent as MessageContentDefault } from '../Message/MessageSimple/MessageContent';
154155
import { MessageDeleted as MessageDeletedDefault } from '../Message/MessageSimple/MessageDeleted';
@@ -354,6 +355,7 @@ export type ChannelPropsWithContext = Pick<ChannelContextValue, 'channel'> &
354355
| 'messageActions'
355356
| 'MessageAvatar'
356357
| 'MessageBounce'
358+
| 'MessageBlocked'
357359
| 'MessageContent'
358360
| 'messageContentOrder'
359361
| 'MessageDeleted'
@@ -674,6 +676,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
674676
MessageActionListItem = MessageActionListItemDefault,
675677
messageActions,
676678
MessageAvatar = MessageAvatarDefault,
679+
MessageBlocked = MessageBlockedDefault,
677680
MessageBounce = MessageBounceDefault,
678681
MessageContent = MessageContentDefault,
679682
messageContentOrder = [
@@ -1951,6 +1954,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
19511954
MessageActionListItem,
19521955
messageActions,
19531956
MessageAvatar,
1957+
MessageBlocked,
19541958
MessageBounce,
19551959
MessageContent,
19561960
messageContentOrder,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export const useCreateMessagesContext = ({
5959
MessageActionListItem,
6060
messageActions,
6161
MessageAvatar,
62+
MessageBlocked,
6263
MessageBounce,
6364
MessageContent,
6465
messageContentOrder,
@@ -177,6 +178,7 @@ export const useCreateMessagesContext = ({
177178
MessageActionListItem,
178179
messageActions,
179180
MessageAvatar,
181+
MessageBlocked,
180182
MessageBounce,
181183
MessageContent,
182184
messageContentOrder,

package/src/components/Message/Message.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export type MessagePropsWithContext = Pick<
180180
| 'messageActions'
181181
| 'messageContentOrder'
182182
| 'MessageBounce'
183+
| 'MessageBlocked'
183184
| 'MessageSimple'
184185
| 'onLongPressMessage'
185186
| 'onPressInMessage'
@@ -256,6 +257,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
256257
members,
257258
message,
258259
messageActions: messageActionsProp = defaultMessageActions,
260+
MessageBlocked,
259261
MessageBounce,
260262
messageContentOrder: messageContentOrderProp,
261263
MessageMenu,
@@ -348,12 +350,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
348350
const quotedMessage = message.quoted_message;
349351
if (error) {
350352
setIsErrorInMessage(true);
351-
/**
352-
* If its a Blocked message, we don't do anything as per specs.
353-
*/
354-
if (isBlockedMessage(message)) {
355-
return;
356-
}
357353
/**
358354
* If its a Bounced message, we open the message bounced options modal.
359355
*/
@@ -620,7 +616,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
620616
};
621617

622618
const onLongPress = () => {
623-
if (hasAttachmentActions || isBlockedMessage(message) || !enableLongPress) {
619+
if (hasAttachmentActions || !enableLongPress) {
624620
return;
625621
}
626622
// If a message is bounced, on long press the message bounce options modal should open.
@@ -732,6 +728,10 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
732728
return null;
733729
}
734730

731+
if (isBlockedMessage(message)) {
732+
return <MessageBlocked message={message} />;
733+
}
734+
735735
return (
736736
<MessageProvider value={messageContext}>
737737
<View
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React from 'react';
2+
import { StyleProp, StyleSheet, Text, View, ViewStyle } from 'react-native';
3+
4+
import { LocalMessage } from 'stream-chat';
5+
6+
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
7+
8+
export type MessageBlockedProps = {
9+
/** Current [message object](https://getstream.io/chat/docs/#message_format) */
10+
message: LocalMessage;
11+
/**
12+
* Additional styles for the system message container.
13+
*/
14+
style?: StyleProp<ViewStyle>;
15+
};
16+
17+
/**
18+
* A component to display blocked message. e.g, when a message is blocked by moderation policies.
19+
*/
20+
export const MessageBlocked = (props: MessageBlockedProps) => {
21+
const { message, style } = props;
22+
23+
const {
24+
theme: {
25+
colors: { grey, grey_whisper },
26+
messageSimple: {
27+
messageBlocked: { container, line, text, textContainer },
28+
},
29+
},
30+
} = useTheme();
31+
32+
return (
33+
<View style={[styles.container, style, container]} testID='message-system'>
34+
<View style={[styles.line, { backgroundColor: grey_whisper }, line]} />
35+
<View style={[styles.textContainer, textContainer]}>
36+
<Text style={[styles.text, { color: grey }, text]}>
37+
{message.text?.toUpperCase() || ''}
38+
</Text>
39+
</View>
40+
<View style={[styles.line, { backgroundColor: grey_whisper }, line]} />
41+
</View>
42+
);
43+
};
44+
45+
MessageBlocked.displayName = 'MessageBlocked{messageList{messageBlocked}}';
46+
47+
const styles = StyleSheet.create({
48+
container: {
49+
alignItems: 'center',
50+
flexDirection: 'row',
51+
justifyContent: 'center',
52+
marginBottom: 10,
53+
},
54+
line: {
55+
flex: 1,
56+
height: 0.5,
57+
},
58+
text: {
59+
fontSize: 10,
60+
fontWeight: 'bold',
61+
textAlign: 'center',
62+
},
63+
textContainer: {
64+
flex: 3,
65+
marginTop: 10,
66+
},
67+
});

package/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export * from './Message/hooks/useMessageReadData';
9999
export * from './Message/Message';
100100
export * from './Message/MessageSimple/MessageAvatar';
101101
export * from './Message/MessageSimple/MessageBounce';
102+
export * from './Message/MessageSimple/MessageBlocked';
102103
export * from './Message/MessageSimple/MessageContent';
103104
export * from './Message/MessageSimple/MessageDeleted';
104105
export * from './Message/MessageSimple/MessageEditedTimestamp';

package/src/contexts/messagesContext/MessagesContext.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import type {
3131
MessageProps,
3232
} from '../../components/Message/Message';
3333
import type { MessageAvatarProps } from '../../components/Message/MessageSimple/MessageAvatar';
34+
import type { MessageBlockedProps } from '../../components/Message/MessageSimple/MessageBlocked';
3435
import type { MessageBounceProps } from '../../components/Message/MessageSimple/MessageBounce';
3536
import type { MessageContentProps } from '../../components/Message/MessageSimple/MessageContent';
3637
import type { MessageDeletedProps } from '../../components/Message/MessageSimple/MessageDeleted';
@@ -206,6 +207,11 @@ export type MessagesContextValue = Pick<MessageContextValue, 'isMessageAIGenerat
206207
* Defaults to: [MessageAvatar](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Message/MessageSimple/MessageAvatar.tsx)
207208
**/
208209
MessageAvatar: React.ComponentType<MessageAvatarProps>;
210+
/**
211+
* UI component for MessageBlocked
212+
* Defaults to: [MessageBlocked](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Message/MessageSimple/MessageBlocked.tsx)
213+
*/
214+
MessageBlocked: React.ComponentType<MessageBlockedProps>;
209215
/**
210216
* UI Component for MessageBounce
211217
*/

package/src/contexts/themeContext/utils/theme.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,12 @@ export type Theme = {
655655
};
656656
messageGroupedSingleOrBottomContainer: ViewStyle;
657657
messageGroupedTopContainer: ViewStyle;
658+
messageBlocked: {
659+
container: ViewStyle;
660+
line: ViewStyle;
661+
text: TextStyle;
662+
textContainer: ViewStyle;
663+
};
658664
pinnedHeader: {
659665
container: ViewStyle;
660666
label: TextStyle;
@@ -1469,6 +1475,12 @@ export const defaultTheme: Theme = {
14691475
container: {},
14701476
roundedView: {},
14711477
},
1478+
messageBlocked: {
1479+
container: {},
1480+
line: {},
1481+
text: {},
1482+
textContainer: {},
1483+
},
14721484
messageGroupedSingleOrBottomContainer: {},
14731485
messageGroupedTopContainer: {},
14741486
pinnedHeader: {

package/src/store/apis/getChannelMessages.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { selectMessagesForChannels } from './queries/selectMessagesForChannels';
44

55
import { selectReactionsForMessages } from './queries/selectReactionsForMessages';
66

7-
import { isBlockedMessage } from '../../utils/utils';
87
import { mapStorableToMessage } from '../mappers/mapStorableToMessage';
98
import { createSelectQuery } from '../sqlite-utils/createSelectQuery';
109
import { SqliteClient } from '../SqliteClient';
@@ -82,17 +81,15 @@ export const getChannelMessages = async ({
8281
cidVsMessages[m.cid] = [];
8382
}
8483

85-
if (!isBlockedMessage(m)) {
86-
cidVsMessages[m.cid].push(
87-
mapStorableToMessage({
88-
currentUserId,
89-
messageRow: m,
90-
pollRow: messageIdsVsPolls[m.poll_id],
91-
reactionRows: messageIdVsReactions[m.id],
92-
reminderRow: messageIdsVsReminders[m.id],
93-
}),
94-
);
95-
}
84+
cidVsMessages[m.cid].push(
85+
mapStorableToMessage({
86+
currentUserId,
87+
messageRow: m,
88+
pollRow: messageIdsVsPolls[m.poll_id],
89+
reactionRows: messageIdVsReactions[m.id],
90+
reminderRow: messageIdsVsReminders[m.id],
91+
}),
92+
);
9693
});
9794

9895
return cidVsMessages;

package/src/utils/utils.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import type {
1010
} from 'stream-chat';
1111

1212
import { IconProps } from '../../src/icons/utils/base';
13-
import type { TableRowJoinedUser } from '../store/types';
1413
import { ValueOf } from '../types/types';
1514

1615
export type ReactionData = {
@@ -74,10 +73,12 @@ export const getIndicatorTypeForFileState = (
7473
* @param message
7574
* @returns boolean
7675
*/
77-
export const isBlockedMessage = (message: LocalMessage | TableRowJoinedUser<'messages'>) => {
78-
// The only indicator for the blocked message is its message type is error and that the message text contains "Message was blocked by moderation policies".
79-
const pattern = /\bMessage was blocked by moderation policies\b/;
80-
return message.type === 'error' && message.text && pattern.test(message.text);
76+
export const isBlockedMessage = (message: LocalMessage) => {
77+
return (
78+
message.type === 'error' &&
79+
(message.moderation_details?.action === 'MESSAGE_RESPONSE_ACTION_REMOVE' ||
80+
message.moderation?.action === 'remove')
81+
);
8182
};
8283

8384
/**

0 commit comments

Comments
 (0)