Skip to content

Commit 79542d8

Browse files
authored
fix: add factory fn to determine whether a msg is ai generated (#2829)
* fix: add factory fn to determine whether a msg is ai generated * chore: move prop to Chat component * fix: memoize integration provided fn
1 parent b52c1df commit 79542d8

File tree

17 files changed

+83
-42
lines changed

17 files changed

+83
-42
lines changed

examples/SampleApp/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { createStackNavigator } from '@react-navigation/stack';
66
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
77
import {
88
Chat,
9+
MessageType,
910
OverlayProvider,
1011
QuickSqliteClient,
1112
ThemeProvider,
@@ -182,6 +183,7 @@ const DrawerNavigatorWrapper: React.FC<{
182183
enableOfflineSupport
183184
// @ts-expect-error
184185
ImageComponent={FastImage}
186+
isMessageAIGenerated={(message: MessageType) => message.ai_generated}
185187
>
186188
<AppOverlayProvider>
187189
<UserSearchProvider>

examples/SampleApp/yarn.lock

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6837,10 +6837,10 @@ statuses@~1.5.0:
68376837
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
68386838
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
68396839

6840-
stream-chat-react-native-core@5.43.2:
6841-
version "5.43.2"
6842-
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.43.2.tgz#b16add60d231509f864d7301ae281c4b4681ff7a"
6843-
integrity sha512-pdSaqw1aPHtxH0md7nnw/TLWPIqsb5TKFzGoWYd/cKRAw4pVDvxolSlha8vYSCwz7MmlarfsJPB0TlS9WcGsDQ==
6840+
stream-chat-react-native-core@5.44.0:
6841+
version "5.44.0"
6842+
resolved "https://registry.yarnpkg.com/stream-chat-react-native-core/-/stream-chat-react-native-core-5.44.0.tgz#2d3f8b8ca8a15b6f15fa03bea099e706e4c88e79"
6843+
integrity sha512-gN7/aaDvESPc2s7d6xyCTu4vpiok1HCwcNiHxvNC2NlvL0O5xd/7240L+eoSPhECXTPZvCgVJVEra9CWMM4pXw==
68446844
dependencies:
68456845
"@gorhom/bottom-sheet" "^4.6.4"
68466846
dayjs "1.10.5"
@@ -6853,7 +6853,7 @@ [email protected]:
68536853
path "0.12.7"
68546854
react-native-markdown-package "1.8.2"
68556855
react-native-url-polyfill "^1.3.0"
6856-
stream-chat "8.45.1"
6856+
stream-chat "8.46.0"
68576857

68586858
"stream-chat-react-native-core@link:../../package":
68596859
version "0.0.0"
@@ -6863,21 +6863,6 @@ [email protected]:
68636863
version "0.0.0"
68646864
uid ""
68656865

6866-
6867-
version "8.45.1"
6868-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-8.45.1.tgz#001f452520602ebffe45f1634b5f5dd1ff036ec5"
6869-
integrity sha512-7OMpL2RHUd+PXSWzhTUAIjjXlI9Oqc4HhUBRfc5i6dK+Ug9S5ertb7RvyzGL5N4ITpq/6ZUAwXtTqRaN9+UUkw==
6870-
dependencies:
6871-
"@babel/runtime" "^7.16.3"
6872-
"@types/jsonwebtoken" "~9.0.0"
6873-
"@types/ws" "^7.4.0"
6874-
axios "^1.6.0"
6875-
base64-js "^1.5.1"
6876-
form-data "^4.0.0"
6877-
isomorphic-ws "^4.0.1"
6878-
jsonwebtoken "~9.0.0"
6879-
ws "^7.5.10"
6880-
68816866
68826867
version "8.46.0"
68836868
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-8.46.0.tgz#416b325e05b144d0937a3527d1e622463113d605"

package/src/components/Channel/Channel.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { useCreateTypingContext } from './hooks/useCreateTypingContext';
3636

3737
import { useTargetedMessage } from './hooks/useTargetedMessage';
3838

39+
import { MessageContextValue } from '../../contexts';
3940
import { ChannelContextValue, ChannelProvider } from '../../contexts/channelContext/ChannelContext';
4041
import type { UseChannelStateValue } from '../../contexts/channelsStateContext/useChannelState';
4142
import { useChannelState } from '../../contexts/channelsStateContext/useChannelState';
@@ -338,6 +339,7 @@ export type ChannelPropsWithContext<
338339
| 'StreamingMessageView'
339340
>
340341
> &
342+
Partial<Pick<MessageContextValue<StreamChatGenerics>, 'isMessageAIGenerated'>> &
341343
Partial<Pick<ThreadContextValue<StreamChatGenerics>, 'allowThreadMessagesInChannel'>> & {
342344
shouldSyncChannel: boolean;
343345
thread: ThreadType<StreamChatGenerics>;
@@ -532,6 +534,7 @@ const ChannelWithContext = <
532534
InputGiphySearch = InputGiphyCommandInputDefault,
533535
InputReplyStateHeader = InputReplyStateHeaderDefault,
534536
isAttachmentEqual,
537+
isMessageAIGenerated = () => false,
535538
keyboardBehavior,
536539
KeyboardCompatibleView = KeyboardCompatibleViewDefault,
537540
keyboardVerticalOffset,
@@ -2424,6 +2427,7 @@ const ChannelWithContext = <
24242427
InlineDateSeparator,
24252428
InlineUnreadIndicator,
24262429
isAttachmentEqual,
2430+
isMessageAIGenerated,
24272431
legacyImageViewerSwipeBehaviour,
24282432
markdownRules,
24292433
Message,
@@ -2559,7 +2563,8 @@ export const Channel = <
25592563
>(
25602564
props: PropsWithChildren<ChannelProps<StreamChatGenerics>>,
25612565
) => {
2562-
const { client, enableOfflineSupport } = useChatContext<StreamChatGenerics>();
2566+
const { client, enableOfflineSupport, isMessageAIGenerated } =
2567+
useChatContext<StreamChatGenerics>();
25632568
const { t } = useTranslationContext();
25642569

25652570
const threadFromProps = props?.thread;
@@ -2605,6 +2610,7 @@ export const Channel = <
26052610
{...props}
26062611
shouldSyncChannel={shouldSyncChannel}
26072612
{...{
2613+
isMessageAIGenerated,
26082614
members,
26092615
messages: props.messages || messages,
26102616
read,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const useCreateMessagesContext = <
5050
InlineDateSeparator,
5151
InlineUnreadIndicator,
5252
isAttachmentEqual,
53+
isMessageAIGenerated,
5354
legacyImageViewerSwipeBehaviour,
5455
markdownRules,
5556
Message,
@@ -152,6 +153,7 @@ export const useCreateMessagesContext = <
152153
InlineDateSeparator,
153154
InlineUnreadIndicator,
154155
isAttachmentEqual,
156+
isMessageAIGenerated,
155157
legacyImageViewerSwipeBehaviour,
156158
markdownRules,
157159
Message,

package/src/components/Chat/Chat.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ init();
3636
export type ChatProps<
3737
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
3838
> = Pick<ChatContextValue<StreamChatGenerics>, 'client'> &
39-
Partial<Pick<ChatContextValue<StreamChatGenerics>, 'ImageComponent' | 'resizableCDNHosts'>> & {
39+
Partial<
40+
Pick<
41+
ChatContextValue<StreamChatGenerics>,
42+
'ImageComponent' | 'resizableCDNHosts' | 'isMessageAIGenerated'
43+
>
44+
> & {
4045
/**
4146
* When false, ws connection won't be disconnection upon backgrounding the app.
4247
* To receive push notifications, its necessary that user doesn't have active
@@ -149,6 +154,7 @@ const ChatWithContext = <
149154
enableOfflineSupport = false,
150155
i18nInstance,
151156
ImageComponent = Image,
157+
isMessageAIGenerated,
152158
LoadingIndicator = null,
153159
resizableCDNHosts = ['.stream-io-cdn.com'],
154160
style,
@@ -250,6 +256,7 @@ const ChatWithContext = <
250256
connectionRecovering,
251257
enableOfflineSupport,
252258
ImageComponent,
259+
isMessageAIGenerated,
253260
isOnline,
254261
mutedUsers,
255262
resizableCDNHosts,

package/src/components/Chat/hooks/useCreateChatContext.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const useCreateChatContext = <
1212
connectionRecovering,
1313
enableOfflineSupport,
1414
ImageComponent,
15+
isMessageAIGenerated,
1516
isOnline,
1617
mutedUsers,
1718
resizableCDNHosts,
@@ -33,6 +34,7 @@ export const useCreateChatContext = <
3334
connectionRecovering,
3435
enableOfflineSupport,
3536
ImageComponent,
37+
isMessageAIGenerated,
3638
isOnline,
3739
mutedUsers,
3840
resizableCDNHosts,

package/src/components/Message/Message.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,16 @@ export type MessagePropsWithContext<
139139
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
140140
> = Pick<ChannelContextValue<StreamChatGenerics>, 'channel' | 'enforceUniqueReaction' | 'members'> &
141141
Pick<KeyboardContextValue, 'dismissKeyboard'> &
142-
Partial<Omit<MessageContextValue<StreamChatGenerics>, 'groupStyles' | 'message'>> &
143-
Pick<MessageContextValue<StreamChatGenerics>, 'groupStyles' | 'message'> &
142+
Partial<
143+
Omit<
144+
MessageContextValue<StreamChatGenerics>,
145+
'groupStyles' | 'message' | 'isMessageAIGenerated'
146+
>
147+
> &
148+
Pick<
149+
MessageContextValue<StreamChatGenerics>,
150+
'groupStyles' | 'message' | 'isMessageAIGenerated'
151+
> &
144152
Pick<
145153
MessagesContextValue<StreamChatGenerics>,
146154
| 'sendReaction'
@@ -305,6 +313,11 @@ const MessageWithContext = <
305313
threadList = false,
306314
updateMessage,
307315
} = props;
316+
const isMessageAIGenerated = messagesContext.isMessageAIGenerated;
317+
const isAIGenerated = useMemo(
318+
() => isMessageAIGenerated(message),
319+
[message, isMessageAIGenerated],
320+
);
308321
const { client } = chatContext;
309322
const {
310323
theme: {
@@ -457,7 +470,7 @@ const MessageWithContext = <
457470
case 'poll':
458471
return !!message.poll_id;
459472
case 'ai_text':
460-
return !!message.ai_generated;
473+
return isAIGenerated;
461474
case 'text':
462475
default:
463476
return !!message.text;
@@ -704,6 +717,7 @@ const MessageWithContext = <
704717
hasReactions,
705718
images: attachments.images,
706719
isEditedMessageOpen,
720+
isMessageAIGenerated,
707721
isMyMessage,
708722
lastGroupMessage: groupStyles?.[0] === 'single' || groupStyles?.[0] === 'bottom',
709723
lastReceivedId,
@@ -865,8 +879,7 @@ const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = Default
865879
prevMessage.text === nextMessage.text &&
866880
prevMessage.pinned === nextMessage.pinned &&
867881
`${prevMessage?.updated_at}` === `${nextMessage?.updated_at}` &&
868-
prevMessage.i18n === nextMessage.i18n &&
869-
prevMessage.ai_generated === nextMessage.ai_generated;
882+
prevMessage.i18n === nextMessage.i18n;
870883

871884
if (!messageEqual) return false;
872885

package/src/components/Message/MessageSimple/MessageContent.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import {
33
AnimatableNumericValue,
44
LayoutChangeEvent,
@@ -82,6 +82,7 @@ export type MessageContentPropsWithContext<
8282
| 'preventPress'
8383
| 'showMessageStatus'
8484
| 'threadList'
85+
| 'isMessageAIGenerated'
8586
> &
8687
Pick<
8788
MessagesContextValue<StreamChatGenerics>,
@@ -122,6 +123,7 @@ const MessageContentWithContext = <
122123
Gallery,
123124
groupStyles,
124125
hasReactions,
126+
isMessageAIGenerated,
125127
isMyMessage,
126128
lastGroupMessage,
127129
members,
@@ -186,6 +188,11 @@ const MessageContentWithContext = <
186188
setMessageContentWidth(width);
187189
};
188190

191+
const isAIGenerated = useMemo(
192+
() => isMessageAIGenerated(message),
193+
[message, isMessageAIGenerated],
194+
);
195+
189196
const error = message.type === 'error' || message.status === MessageStatusTypes.FAILED;
190197

191198
const groupStyle = `${alignment}_${groupStyles?.[0]?.toLowerCase?.()}`;
@@ -396,15 +403,15 @@ const MessageContentWithContext = <
396403
) : null;
397404
}
398405
case 'ai_text':
399-
return message.ai_generated ? (
406+
return isAIGenerated ? (
400407
<StreamingMessageView
401408
key={`ai_message_text_container_${messageContentOrderIndex}`}
402409
/>
403410
) : null;
404411
case 'text':
405412
default:
406413
return (otherAttachments.length && otherAttachments[0].actions) ||
407-
message.ai_generated ? null : (
414+
isAIGenerated ? null : (
408415
<MessageTextContainer<StreamChatGenerics>
409416
key={`message_text_container_${messageContentOrderIndex}`}
410417
/>
@@ -493,8 +500,7 @@ const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = Default
493500
prevMessage.type === nextMessage.type &&
494501
prevMessage.text === nextMessage.text &&
495502
prevMessage.pinned === nextMessage.pinned &&
496-
prevMessage.i18n === nextMessage.i18n &&
497-
prevMessage.ai_generated === nextMessage.ai_generated;
503+
prevMessage.i18n === nextMessage.i18n;
498504
if (!messageEqual) return false;
499505

500506
const isPrevQuotedMessageTypeDeleted = prevMessage.quoted_message?.type === 'deleted';
@@ -577,6 +583,7 @@ export const MessageContent = <
577583
groupStyles,
578584
hasReactions,
579585
isEditedMessageOpen,
586+
isMessageAIGenerated,
580587
isMyMessage,
581588
lastGroupMessage,
582589
lastReceivedId,
@@ -624,6 +631,7 @@ export const MessageContent = <
624631
hasReactions,
625632
isAttachmentEqual,
626633
isEditedMessageOpen,
634+
isMessageAIGenerated,
627635
isMyMessage,
628636
lastGroupMessage,
629637
lastReceivedId,

package/src/components/Message/MessageSimple/MessageFooter.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import { StyleSheet, Text, View } from 'react-native';
33

44
import type { Attachment } from 'stream-chat';
@@ -41,6 +41,7 @@ type MessageFooterPropsWithContext<
4141
| 'otherAttachments'
4242
| 'showMessageStatus'
4343
| 'lastGroupMessage'
44+
| 'isMessageAIGenerated'
4445
> &
4546
Pick<
4647
MessagesContextValue<StreamChatGenerics>,
@@ -94,6 +95,7 @@ const MessageFooterWithContext = <
9495
formattedDate,
9596
isDeleted,
9697
isEditedMessageOpen,
98+
isMessageAIGenerated,
9799
lastGroupMessage,
98100
members,
99101
message,
@@ -114,6 +116,11 @@ const MessageFooterWithContext = <
114116
} = useTheme();
115117
const { t } = useTranslationContext();
116118

119+
const isAIGenerated = useMemo(
120+
() => isMessageAIGenerated(message),
121+
[message, isMessageAIGenerated],
122+
);
123+
117124
if (isDeleted) {
118125
return (
119126
<View style={[styles.container, metaContainer]} testID='message-deleted'>
@@ -129,7 +136,7 @@ const MessageFooterWithContext = <
129136
return null;
130137
}
131138

132-
const isEdited = isEditedMessage(message);
139+
const isEdited = isEditedMessage(message) && !isAIGenerated;
133140

134141
return (
135142
<>
@@ -267,6 +274,7 @@ export const MessageFooter = <
267274
const {
268275
alignment,
269276
isEditedMessageOpen,
277+
isMessageAIGenerated,
270278
lastGroupMessage,
271279
members,
272280
message,
@@ -283,6 +291,7 @@ export const MessageFooter = <
283291
alignment,
284292
deletedMessagesVisibilityType,
285293
isEditedMessageOpen,
294+
isMessageAIGenerated,
286295
lastGroupMessage,
287296
members,
288297
message,

package/src/components/Message/MessageSimple/MessageSimple.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = Default
155155
prevMessage.type === nextMessage.type &&
156156
prevMessage.text === nextMessage.text &&
157157
prevMessage.i18n === nextMessage.i18n &&
158-
prevMessage.pinned === nextMessage.pinned &&
159-
prevMessage.ai_generated === nextMessage.ai_generated;
158+
prevMessage.pinned === nextMessage.pinned;
160159
if (!messageEqual) return false;
161160

162161
const isPrevQuotedMessageTypeDeleted = prevMessage.quoted_message?.type === 'deleted';

0 commit comments

Comments
 (0)