stream-chat-react-native-core 5.24.0-beta.3 → 5.24.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/Channel/Channel.js +30 -22
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +2 -0
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/commonjs/components/Message/Message.js +28 -6
- package/lib/commonjs/components/Message/Message.js.map +1 -1
- package/lib/commonjs/components/Message/MessageSimple/MessageBounce.js +84 -0
- package/lib/commonjs/components/Message/MessageSimple/MessageBounce.js.map +1 -0
- package/lib/commonjs/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useMessageActions.js.map +1 -1
- package/lib/commonjs/components/MessageInput/SendButton.js +2 -2
- package/lib/commonjs/components/MessageInput/SendButton.js.map +1 -1
- package/lib/commonjs/components/index.js +11 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js +18 -8
- package/lib/commonjs/contexts/messageInputContext/MessageInputContext.js.map +1 -1
- package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js +4 -8
- package/lib/commonjs/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/commonjs/i18n/en.json +3 -0
- package/lib/commonjs/i18n/es.json +4 -1
- package/lib/commonjs/i18n/fr.json +14 -11
- package/lib/commonjs/i18n/he.json +4 -1
- package/lib/commonjs/i18n/hi.json +14 -11
- package/lib/commonjs/i18n/it.json +14 -11
- package/lib/commonjs/i18n/ja.json +4 -1
- package/lib/commonjs/i18n/ko.json +4 -1
- package/lib/commonjs/i18n/nl.json +14 -11
- package/lib/commonjs/i18n/ru.json +14 -11
- package/lib/commonjs/i18n/tr.json +14 -11
- package/lib/commonjs/utils/removeReservedFields.js +1 -1
- package/lib/commonjs/utils/removeReservedFields.js.map +1 -1
- package/lib/commonjs/utils/utils.js +5 -1
- package/lib/commonjs/utils/utils.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Channel/Channel.js +30 -22
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +2 -0
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/module/components/Message/Message.js +28 -6
- package/lib/module/components/Message/Message.js.map +1 -1
- package/lib/module/components/Message/MessageSimple/MessageBounce.js +84 -0
- package/lib/module/components/Message/MessageSimple/MessageBounce.js.map +1 -0
- package/lib/module/components/Message/hooks/useMessageActionHandlers.js.map +1 -1
- package/lib/module/components/Message/hooks/useMessageActions.js.map +1 -1
- package/lib/module/components/MessageInput/SendButton.js +2 -2
- package/lib/module/components/MessageInput/SendButton.js.map +1 -1
- package/lib/module/components/index.js +11 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/messageInputContext/MessageInputContext.js +18 -8
- package/lib/module/contexts/messageInputContext/MessageInputContext.js.map +1 -1
- package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js +4 -8
- package/lib/module/contexts/messageInputContext/hooks/useMessageDetailsForState.js.map +1 -1
- package/lib/module/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/module/i18n/en.json +3 -0
- package/lib/module/i18n/es.json +4 -1
- package/lib/module/i18n/fr.json +14 -11
- package/lib/module/i18n/he.json +4 -1
- package/lib/module/i18n/hi.json +14 -11
- package/lib/module/i18n/it.json +14 -11
- package/lib/module/i18n/ja.json +4 -1
- package/lib/module/i18n/ko.json +4 -1
- package/lib/module/i18n/nl.json +14 -11
- package/lib/module/i18n/ru.json +14 -11
- package/lib/module/i18n/tr.json +14 -11
- package/lib/module/utils/removeReservedFields.js +1 -1
- package/lib/module/utils/removeReservedFields.js.map +1 -1
- package/lib/module/utils/utils.js +5 -1
- package/lib/module/utils/utils.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +1 -1
- package/lib/typescript/components/Message/Message.d.ts +1 -1
- package/lib/typescript/components/Message/MessageSimple/MessageBounce.d.ts +12 -0
- package/lib/typescript/components/MessageList/utils/getReadStates.d.ts +1 -0
- package/lib/typescript/components/index.d.ts +1 -0
- package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +6 -2
- package/lib/typescript/contexts/messageInputContext/hooks/useMessageDetailsForState.d.ts +1 -2
- package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +7 -2
- package/lib/typescript/i18n/en.json +3 -0
- package/lib/typescript/i18n/es.json +4 -1
- package/lib/typescript/i18n/fr.json +14 -11
- package/lib/typescript/i18n/he.json +4 -1
- package/lib/typescript/i18n/hi.json +14 -11
- package/lib/typescript/i18n/it.json +14 -11
- package/lib/typescript/i18n/ja.json +4 -1
- package/lib/typescript/i18n/ko.json +4 -1
- package/lib/typescript/i18n/nl.json +14 -11
- package/lib/typescript/i18n/ru.json +14 -11
- package/lib/typescript/i18n/tr.json +14 -11
- package/lib/typescript/utils/Streami18n.d.ts +3 -0
- package/lib/typescript/utils/removeReservedFields.d.ts +2 -1
- package/lib/typescript/utils/utils.d.ts +11 -0
- package/package.json +2 -2
- package/src/components/Channel/Channel.tsx +26 -7
- package/src/components/Channel/hooks/useCreateMessagesContext.ts +2 -0
- package/src/components/Message/Message.tsx +26 -2
- package/src/components/Message/MessageSimple/MessageBounce.tsx +119 -0
- package/src/components/Message/hooks/useMessageActionHandlers.ts +1 -2
- package/src/components/Message/hooks/useMessageActions.tsx +1 -1
- package/src/components/MessageInput/SendButton.tsx +2 -2
- package/src/components/index.ts +1 -0
- package/src/contexts/messageInputContext/MessageInputContext.tsx +24 -6
- package/src/contexts/messageInputContext/__tests__/sendMessage.test.tsx +8 -8
- package/src/contexts/messageInputContext/__tests__/updateMessage.test.tsx +1 -1
- package/src/contexts/messageInputContext/__tests__/useMessageDetailsForState.test.tsx +6 -1
- package/src/contexts/messageInputContext/hooks/useMessageDetailsForState.ts +3 -9
- package/src/contexts/messagesContext/MessagesContext.tsx +7 -2
- package/src/i18n/en.json +3 -0
- package/src/i18n/es.json +4 -1
- package/src/i18n/fr.json +14 -11
- package/src/i18n/he.json +4 -1
- package/src/i18n/hi.json +14 -11
- package/src/i18n/it.json +14 -11
- package/src/i18n/ja.json +4 -1
- package/src/i18n/ko.json +4 -1
- package/src/i18n/nl.json +14 -11
- package/src/i18n/ru.json +14 -11
- package/src/i18n/tr.json +14 -11
- package/src/utils/removeReservedFields.ts +5 -2
- package/src/utils/utils.ts +16 -0
- package/src/version.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
2
|
import { GestureResponderEvent, Keyboard, StyleProp, View, ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import type { Attachment, UserResponse } from 'stream-chat';
|
|
@@ -44,7 +44,12 @@ import {
|
|
|
44
44
|
|
|
45
45
|
import { isVideoPackageAvailable, triggerHaptic } from '../../native';
|
|
46
46
|
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
47
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
hasOnlyEmojis,
|
|
49
|
+
isBlockedMessage,
|
|
50
|
+
isBouncedMessage,
|
|
51
|
+
MessageStatusTypes,
|
|
52
|
+
} from '../../utils/utils';
|
|
48
53
|
|
|
49
54
|
import {
|
|
50
55
|
isMessageWithStylesReadByAndDateSeparator,
|
|
@@ -141,6 +146,7 @@ export type MessagePropsWithContext<
|
|
|
141
146
|
| 'isAttachmentEqual'
|
|
142
147
|
| 'messageActions'
|
|
143
148
|
| 'messageContentOrder'
|
|
149
|
+
| 'MessageBounce'
|
|
144
150
|
| 'MessageSimple'
|
|
145
151
|
| 'onLongPressMessage'
|
|
146
152
|
| 'onPressInMessage'
|
|
@@ -217,6 +223,7 @@ const MessageWithContext = <
|
|
|
217
223
|
>(
|
|
218
224
|
props: MessagePropsWithContext<StreamChatGenerics>,
|
|
219
225
|
) => {
|
|
226
|
+
const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false);
|
|
220
227
|
const isMessageTypeDeleted = props.message.type === 'deleted';
|
|
221
228
|
|
|
222
229
|
const {
|
|
@@ -249,6 +256,7 @@ const MessageWithContext = <
|
|
|
249
256
|
messageActions: messageActionsProp = defaultMessageActions,
|
|
250
257
|
messageContentOrder: messageContentOrderProp,
|
|
251
258
|
messagesContext,
|
|
259
|
+
MessageBounce,
|
|
252
260
|
MessageSimple,
|
|
253
261
|
onLongPress: onLongPressProp,
|
|
254
262
|
onLongPressMessage: onLongPressMessageProp,
|
|
@@ -319,9 +327,19 @@ const MessageWithContext = <
|
|
|
319
327
|
}
|
|
320
328
|
const quotedMessage = message.quoted_message as MessageType<StreamChatGenerics>;
|
|
321
329
|
if (error) {
|
|
330
|
+
/**
|
|
331
|
+
* If its a Blocked message, we don't do anything as per specs.
|
|
332
|
+
*/
|
|
322
333
|
if (isBlockedMessage(message)) {
|
|
323
334
|
return;
|
|
324
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* If its a Bounced message, we open the message bounced options modal.
|
|
338
|
+
*/
|
|
339
|
+
if (isBouncedMessage(message)) {
|
|
340
|
+
setIsBounceDialogOpen(true);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
325
343
|
showMessageOverlay(false, true);
|
|
326
344
|
} else if (quotedMessage) {
|
|
327
345
|
onPressQuotedMessage(quotedMessage);
|
|
@@ -622,6 +640,11 @@ const MessageWithContext = <
|
|
|
622
640
|
})
|
|
623
641
|
: enableLongPress
|
|
624
642
|
? () => {
|
|
643
|
+
// If a message is bounced, on long press the message bounce options modal should open.
|
|
644
|
+
if (isBouncedMessage(message)) {
|
|
645
|
+
setIsBounceDialogOpen(true);
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
625
648
|
triggerHaptic('impactMedium');
|
|
626
649
|
showMessageOverlay(false);
|
|
627
650
|
}
|
|
@@ -730,6 +753,7 @@ const MessageWithContext = <
|
|
|
730
753
|
>
|
|
731
754
|
<MessageProvider value={messageContext}>
|
|
732
755
|
<MessageSimple />
|
|
756
|
+
{isBounceDialogOpen && <MessageBounce setIsBounceDialogOpen={setIsBounceDialogOpen} />}
|
|
733
757
|
</MessageProvider>
|
|
734
758
|
</View>
|
|
735
759
|
</View>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Alert } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
MessageContextValue,
|
|
6
|
+
useMessageContext,
|
|
7
|
+
} from '../../../contexts/messageContext/MessageContext';
|
|
8
|
+
import {
|
|
9
|
+
MessagesContextValue,
|
|
10
|
+
useMessagesContext,
|
|
11
|
+
} from '../../../contexts/messagesContext/MessagesContext';
|
|
12
|
+
import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
|
|
13
|
+
|
|
14
|
+
import type { DefaultStreamChatGenerics } from '../../../types/types';
|
|
15
|
+
|
|
16
|
+
export type MessageBouncePropsWithContext<
|
|
17
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
18
|
+
> = Pick<
|
|
19
|
+
MessagesContextValue<StreamChatGenerics>,
|
|
20
|
+
'setEditingState' | 'removeMessage' | 'retrySendMessage'
|
|
21
|
+
> &
|
|
22
|
+
Pick<MessageContextValue<StreamChatGenerics>, 'message'> & {
|
|
23
|
+
setIsBounceDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const MessageBounceWithContext = <
|
|
27
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
28
|
+
>(
|
|
29
|
+
props: MessageBouncePropsWithContext<StreamChatGenerics>,
|
|
30
|
+
) => {
|
|
31
|
+
const { t } = useTranslationContext();
|
|
32
|
+
const { message, removeMessage, retrySendMessage, setEditingState, setIsBounceDialogOpen } =
|
|
33
|
+
props;
|
|
34
|
+
|
|
35
|
+
const handleEditMessage = () => {
|
|
36
|
+
setEditingState(message);
|
|
37
|
+
if (setIsBounceDialogOpen) {
|
|
38
|
+
setIsBounceDialogOpen(false);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleResend = () => {
|
|
43
|
+
retrySendMessage(message);
|
|
44
|
+
if (setIsBounceDialogOpen) {
|
|
45
|
+
setIsBounceDialogOpen(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handleRemoveMessage = () => {
|
|
50
|
+
removeMessage(message);
|
|
51
|
+
if (setIsBounceDialogOpen) {
|
|
52
|
+
setIsBounceDialogOpen(false);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<>
|
|
58
|
+
{Alert.alert(
|
|
59
|
+
t('Are you sure?'),
|
|
60
|
+
t(
|
|
61
|
+
'Consider how your comment might make others feel and be sure to follow our Community Guidelines',
|
|
62
|
+
),
|
|
63
|
+
[
|
|
64
|
+
{ onPress: handleResend, text: t('Send Anyway') },
|
|
65
|
+
{ onPress: handleEditMessage, text: t('Edit Message') },
|
|
66
|
+
{ onPress: handleRemoveMessage, text: t('Delete Message') },
|
|
67
|
+
],
|
|
68
|
+
{ cancelable: true },
|
|
69
|
+
)}
|
|
70
|
+
</>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(
|
|
75
|
+
prevProps: MessageBouncePropsWithContext<StreamChatGenerics>,
|
|
76
|
+
nextProps: MessageBouncePropsWithContext<StreamChatGenerics>,
|
|
77
|
+
) => {
|
|
78
|
+
const { message: prevMessage } = prevProps;
|
|
79
|
+
const { message: nextMessage } = nextProps;
|
|
80
|
+
const messageEqual =
|
|
81
|
+
prevMessage.cid === nextMessage.cid &&
|
|
82
|
+
prevMessage.type === nextMessage.type &&
|
|
83
|
+
prevMessage.text === nextMessage.text;
|
|
84
|
+
if (!messageEqual) return false;
|
|
85
|
+
|
|
86
|
+
return true;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const MemoizedMessageBounce = React.memo(
|
|
90
|
+
MessageBounceWithContext,
|
|
91
|
+
areEqual,
|
|
92
|
+
) as typeof MessageBounceWithContext;
|
|
93
|
+
|
|
94
|
+
export type MessageBounceProps<
|
|
95
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
96
|
+
> = Partial<MessageBouncePropsWithContext<StreamChatGenerics>> & {
|
|
97
|
+
setIsBounceDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const MessageBounce = <
|
|
101
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
102
|
+
>(
|
|
103
|
+
props: MessageBounceProps<StreamChatGenerics>,
|
|
104
|
+
) => {
|
|
105
|
+
const { message } = useMessageContext<StreamChatGenerics>();
|
|
106
|
+
const { removeMessage, retrySendMessage, setEditingState } =
|
|
107
|
+
useMessagesContext<StreamChatGenerics>();
|
|
108
|
+
return (
|
|
109
|
+
<MemoizedMessageBounce<StreamChatGenerics>
|
|
110
|
+
{...{
|
|
111
|
+
message,
|
|
112
|
+
removeMessage,
|
|
113
|
+
retrySendMessage,
|
|
114
|
+
setEditingState,
|
|
115
|
+
}}
|
|
116
|
+
{...props}
|
|
117
|
+
/>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
@@ -32,8 +32,7 @@ export const useMessageActionHandlers = <
|
|
|
32
32
|
Pick<ChannelContextValue<StreamChatGenerics>, 'channel' | 'enforceUniqueReaction'> &
|
|
33
33
|
Pick<ChatContextValue<StreamChatGenerics>, 'client'> &
|
|
34
34
|
Pick<MessageContextValue<StreamChatGenerics>, 'message'>) => {
|
|
35
|
-
const handleResendMessage = () =>
|
|
36
|
-
retrySendMessage(message as MessageResponse<StreamChatGenerics>);
|
|
35
|
+
const handleResendMessage = () => retrySendMessage(message);
|
|
37
36
|
|
|
38
37
|
const handleQuotedReplyMessage = () => {
|
|
39
38
|
setQuotedMessageState(message);
|
|
@@ -339,7 +339,7 @@ export const useMessageActions = <
|
|
|
339
339
|
setOverlay('none');
|
|
340
340
|
const messageWithoutReservedFields = removeReservedFields(message);
|
|
341
341
|
if (handleRetry) {
|
|
342
|
-
handleRetry(messageWithoutReservedFields);
|
|
342
|
+
handleRetry(messageWithoutReservedFields as MessageType<StreamChatGenerics>);
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
await handleResendMessage();
|
|
@@ -40,8 +40,8 @@ const SendButtonWithContext = <
|
|
|
40
40
|
testID='send-button'
|
|
41
41
|
>
|
|
42
42
|
{giphyActive && <Search pathFill={disabled ? grey_gainsboro : accent_blue} {...searchIcon} />}
|
|
43
|
-
{!giphyActive && disabled && <SendRight pathFill={grey_gainsboro} {...
|
|
44
|
-
{!giphyActive && !disabled && <SendUp pathFill={accent_blue} {...
|
|
43
|
+
{!giphyActive && disabled && <SendRight pathFill={grey_gainsboro} {...sendRightIcon} />}
|
|
44
|
+
{!giphyActive && !disabled && <SendUp pathFill={accent_blue} {...sendUpIcon} />}
|
|
45
45
|
</Pressable>
|
|
46
46
|
);
|
|
47
47
|
};
|
package/src/components/index.ts
CHANGED
|
@@ -96,6 +96,7 @@ export * from './Message/hooks/useMessageActions';
|
|
|
96
96
|
export * from './Message/hooks/useMessageActionHandlers';
|
|
97
97
|
export * from './Message/Message';
|
|
98
98
|
export * from './Message/MessageSimple/MessageAvatar';
|
|
99
|
+
export * from './Message/MessageSimple/MessageBounce';
|
|
99
100
|
export * from './Message/MessageSimple/MessageContent';
|
|
100
101
|
export * from './Message/MessageSimple/MessageDeleted';
|
|
101
102
|
export * from './Message/MessageSimple/MessageError';
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from 'stream-chat';
|
|
19
19
|
|
|
20
20
|
import { useCreateMessageInputContext } from './hooks/useCreateMessageInputContext';
|
|
21
|
-
import {
|
|
21
|
+
import { useMessageDetailsForState } from './hooks/useMessageDetailsForState';
|
|
22
22
|
|
|
23
23
|
import { parseLinksFromText } from '../../components/Message/MessageSimple/utils/parseLinks';
|
|
24
24
|
import type { AttachButtonProps } from '../../components/MessageInput/AttachButton';
|
|
@@ -53,11 +53,13 @@ import {
|
|
|
53
53
|
FileState,
|
|
54
54
|
FileStateValue,
|
|
55
55
|
generateRandomId,
|
|
56
|
+
isBouncedMessage,
|
|
56
57
|
TriggerSettings,
|
|
57
58
|
} from '../../utils/utils';
|
|
58
59
|
import { useAttachmentPickerContext } from '../attachmentPickerContext/AttachmentPickerContext';
|
|
59
60
|
import { ChannelContextValue, useChannelContext } from '../channelContext/ChannelContext';
|
|
60
61
|
import { useChatContext } from '../chatContext/ChatContext';
|
|
62
|
+
import { useMessagesContext } from '../messagesContext/MessagesContext';
|
|
61
63
|
import { useOwnCapabilitiesContext } from '../ownCapabilitiesContext/OwnCapabilitiesContext';
|
|
62
64
|
import { useThreadContext } from '../threadContext/ThreadContext';
|
|
63
65
|
import { useTranslationContext } from '../translationContext/TranslationContext';
|
|
@@ -226,7 +228,6 @@ export type InputMessageInputContextValue<
|
|
|
226
228
|
* **default** [CooldownTimer](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/MessageInput/CooldownTimer.tsx)
|
|
227
229
|
*/
|
|
228
230
|
CooldownTimer: React.ComponentType<CooldownTimerProps>;
|
|
229
|
-
editing: boolean | MessageType<StreamChatGenerics>;
|
|
230
231
|
editMessage: StreamChat<StreamChatGenerics>['updateMessage'];
|
|
231
232
|
|
|
232
233
|
/**
|
|
@@ -331,6 +332,12 @@ export type InputMessageInputContextValue<
|
|
|
331
332
|
channel: ChannelContextValue<StreamChatGenerics>['channel'],
|
|
332
333
|
) => Promise<SendFileAPIResponse>;
|
|
333
334
|
|
|
335
|
+
/**
|
|
336
|
+
* Variable that tracks the editing state.
|
|
337
|
+
* It is defined with message type if the editing state is true, else its undefined.
|
|
338
|
+
*/
|
|
339
|
+
editing?: MessageType<StreamChatGenerics>;
|
|
340
|
+
|
|
334
341
|
/** Initial value to set on input */
|
|
335
342
|
initialValue?: string;
|
|
336
343
|
/**
|
|
@@ -398,6 +405,7 @@ export const MessageInputProvider = <
|
|
|
398
405
|
const { closePicker, openPicker, selectedPicker, setSelectedPicker } =
|
|
399
406
|
useAttachmentPickerContext();
|
|
400
407
|
const { appSettings, client, enableOfflineSupport } = useChatContext<StreamChatGenerics>();
|
|
408
|
+
const { removeMessage } = useMessagesContext();
|
|
401
409
|
|
|
402
410
|
const getFileUploadConfig = () => {
|
|
403
411
|
const fileConfig = appSettings?.app?.file_upload_config;
|
|
@@ -625,6 +633,9 @@ export const MessageInputProvider = <
|
|
|
625
633
|
(prevNumberOfUploads) => prevNumberOfUploads - (pendingAttachments?.length || 0),
|
|
626
634
|
);
|
|
627
635
|
setText('');
|
|
636
|
+
if (value.editing) {
|
|
637
|
+
value.clearEditingState();
|
|
638
|
+
}
|
|
628
639
|
};
|
|
629
640
|
|
|
630
641
|
const mapImageUploadToAttachment = (image: ImageUpload): Attachment<StreamChatGenerics> => {
|
|
@@ -771,9 +782,10 @@ export const MessageInputProvider = <
|
|
|
771
782
|
return;
|
|
772
783
|
}
|
|
773
784
|
|
|
774
|
-
|
|
785
|
+
const message = value.editing;
|
|
786
|
+
if (message && message.type !== 'error') {
|
|
775
787
|
const updatedMessage = {
|
|
776
|
-
...
|
|
788
|
+
...message,
|
|
777
789
|
attachments,
|
|
778
790
|
mentioned_users: mentionedUsers,
|
|
779
791
|
quoted_message: undefined,
|
|
@@ -795,6 +807,12 @@ export const MessageInputProvider = <
|
|
|
795
807
|
sending.current = false;
|
|
796
808
|
} else {
|
|
797
809
|
try {
|
|
810
|
+
/**
|
|
811
|
+
* If the message is bounced by moderation, we firstly remove the message from message list and then send a new message.
|
|
812
|
+
*/
|
|
813
|
+
if (message && isBouncedMessage(message as MessageType<StreamChatGenerics>)) {
|
|
814
|
+
removeMessage(message);
|
|
815
|
+
}
|
|
798
816
|
value.sendMessage({
|
|
799
817
|
attachments,
|
|
800
818
|
mentioned_users: uniq(mentionedUsers),
|
|
@@ -890,7 +908,7 @@ export const MessageInputProvider = <
|
|
|
890
908
|
|
|
891
909
|
const updateMessage = async () => {
|
|
892
910
|
try {
|
|
893
|
-
if (
|
|
911
|
+
if (value.editing) {
|
|
894
912
|
await client.updateMessage({
|
|
895
913
|
...value.editing,
|
|
896
914
|
quoted_message: undefined,
|
|
@@ -898,8 +916,8 @@ export const MessageInputProvider = <
|
|
|
898
916
|
} as Parameters<StreamChat<StreamChatGenerics>['updateMessage']>[0]);
|
|
899
917
|
}
|
|
900
918
|
|
|
901
|
-
resetInput();
|
|
902
919
|
value.clearEditingState();
|
|
920
|
+
resetInput();
|
|
903
921
|
} catch (error) {
|
|
904
922
|
console.log(error);
|
|
905
923
|
}
|
|
@@ -54,7 +54,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
54
54
|
const images = generateImageUploadPreview({ state: FileState.UPLOAD_FAILED });
|
|
55
55
|
const { result } = renderHook(() => useMessageInputContext(), {
|
|
56
56
|
initialProps: {
|
|
57
|
-
editing:
|
|
57
|
+
editing: undefined,
|
|
58
58
|
},
|
|
59
59
|
wrapper: Wrapper,
|
|
60
60
|
});
|
|
@@ -76,7 +76,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
76
76
|
|
|
77
77
|
const { rerender, result } = renderHook(() => useMessageInputContext(), {
|
|
78
78
|
initialProps: {
|
|
79
|
-
editing:
|
|
79
|
+
editing: message,
|
|
80
80
|
sendImageAsync: true,
|
|
81
81
|
},
|
|
82
82
|
wrapper: Wrapper,
|
|
@@ -92,7 +92,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
92
92
|
result.current.sendMessage();
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
rerender({ editing:
|
|
95
|
+
rerender({ editing: undefined, sendImageAsync: true });
|
|
96
96
|
|
|
97
97
|
await expect(result.current.asyncIds).toHaveLength(1);
|
|
98
98
|
await expect(result.current.sending.current).toBeFalsy();
|
|
@@ -103,7 +103,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
103
103
|
|
|
104
104
|
const { result } = renderHook(() => useMessageInputContext(), {
|
|
105
105
|
initialProps: {
|
|
106
|
-
editing:
|
|
106
|
+
editing: message,
|
|
107
107
|
},
|
|
108
108
|
wrapper: Wrapper,
|
|
109
109
|
});
|
|
@@ -125,7 +125,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
125
125
|
const files = generateFileUploadPreview({ state: FileState.UPLOADING });
|
|
126
126
|
const { result } = renderHook(() => useMessageInputContext(), {
|
|
127
127
|
initialProps: {
|
|
128
|
-
editing:
|
|
128
|
+
editing: message,
|
|
129
129
|
},
|
|
130
130
|
wrapper: Wrapper,
|
|
131
131
|
});
|
|
@@ -153,7 +153,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
153
153
|
const { result } = renderHook(() => useMessageInputContext(), {
|
|
154
154
|
initialProps: {
|
|
155
155
|
clearQuotedMessageState: clearQuotedMessageStateMock,
|
|
156
|
-
editing:
|
|
156
|
+
editing: undefined,
|
|
157
157
|
quotedMessage: false,
|
|
158
158
|
sendMessage: sendMessageMock,
|
|
159
159
|
},
|
|
@@ -189,7 +189,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
189
189
|
const { result } = renderHook(() => useMessageInputContext(), {
|
|
190
190
|
initialProps: {
|
|
191
191
|
clearQuotedMessageState: clearQuotedMessageStateMock,
|
|
192
|
-
editing:
|
|
192
|
+
editing: undefined,
|
|
193
193
|
quotedMessage: generatedQuotedMessage,
|
|
194
194
|
setQuotedMessageState: setQuotedMessageStateMock,
|
|
195
195
|
},
|
|
@@ -259,7 +259,7 @@ describe("MessageInputContext's sendMessage", () => {
|
|
|
259
259
|
const { result } = renderHook(() => useMessageInputContext(), {
|
|
260
260
|
initialProps: {
|
|
261
261
|
clearQuotedMessageState: clearQuotedMessageStateMock,
|
|
262
|
-
editing:
|
|
262
|
+
editing: undefined,
|
|
263
263
|
quotedMessage: false,
|
|
264
264
|
sendMessage: sendMessageMock,
|
|
265
265
|
},
|
|
@@ -26,7 +26,12 @@ describe('useMessageDetailsForState', () => {
|
|
|
26
26
|
it('showMoreOptions is true when initialValue and text is same', () => {
|
|
27
27
|
const { result } = renderHook(
|
|
28
28
|
({ initialValue, message }) => useMessageDetailsForState(message, initialValue),
|
|
29
|
-
{
|
|
29
|
+
{
|
|
30
|
+
initialProps: {
|
|
31
|
+
initialValue: 'Dummy text',
|
|
32
|
+
message: generateMessage({ text: 'Dummy text' }) as MessageType,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
30
35
|
);
|
|
31
36
|
|
|
32
37
|
expect(result.current.showMoreOptions).toBe(true);
|
|
@@ -5,12 +5,6 @@ import { generateRandomId } from '../../../utils/utils';
|
|
|
5
5
|
|
|
6
6
|
import type { MessageInputContextValue } from '../MessageInputContext';
|
|
7
7
|
|
|
8
|
-
export const isEditingBoolean = <
|
|
9
|
-
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
10
|
-
>(
|
|
11
|
-
editing: MessageInputContextValue<StreamChatGenerics>['editing'],
|
|
12
|
-
): editing is boolean => typeof editing === 'boolean';
|
|
13
|
-
|
|
14
8
|
export const useMessageDetailsForState = <
|
|
15
9
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
16
10
|
>(
|
|
@@ -32,17 +26,17 @@ export const useMessageDetailsForState = <
|
|
|
32
26
|
}, [text]);
|
|
33
27
|
|
|
34
28
|
const messageValue =
|
|
35
|
-
|
|
29
|
+
message === undefined ? '' : `${message.id}${message.text}${message.updated_at}`;
|
|
36
30
|
|
|
37
31
|
useEffect(() => {
|
|
38
|
-
if (
|
|
32
|
+
if (message && Array.isArray(message?.mentioned_users)) {
|
|
39
33
|
const mentionedUsers = message.mentioned_users.map((user) => user.id);
|
|
40
34
|
setMentionedUsers(mentionedUsers);
|
|
41
35
|
}
|
|
42
36
|
}, [messageValue]);
|
|
43
37
|
|
|
44
38
|
useEffect(() => {
|
|
45
|
-
if (message
|
|
39
|
+
if (message) {
|
|
46
40
|
setText(message?.text || '');
|
|
47
41
|
const newFileUploads: FileUpload[] = [];
|
|
48
42
|
const newImageUploads: ImageUpload[] = [];
|
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
MessageTouchableHandlerPayload,
|
|
25
25
|
} from '../../components/Message/Message';
|
|
26
26
|
import type { MessageAvatarProps } from '../../components/Message/MessageSimple/MessageAvatar';
|
|
27
|
+
import type { MessageBounceProps } from '../../components/Message/MessageSimple/MessageBounce';
|
|
27
28
|
import type { MessageContentProps } from '../../components/Message/MessageSimple/MessageContent';
|
|
28
29
|
import type { MessageDeletedProps } from '../../components/Message/MessageSimple/MessageDeleted';
|
|
29
30
|
import type { MessageErrorProps } from '../../components/Message/MessageSimple/MessageError';
|
|
@@ -158,6 +159,10 @@ export type MessagesContextValue<
|
|
|
158
159
|
* Defaults to: [MessageAvatar](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Message/MessageSimple/MessageAvatar.tsx)
|
|
159
160
|
**/
|
|
160
161
|
MessageAvatar: React.ComponentType<MessageAvatarProps<StreamChatGenerics>>;
|
|
162
|
+
/**
|
|
163
|
+
* UI Component for MessageBounce
|
|
164
|
+
*/
|
|
165
|
+
MessageBounce: React.ComponentType<MessageBounceProps<StreamChatGenerics>>;
|
|
161
166
|
/**
|
|
162
167
|
* UI component for MessageContent
|
|
163
168
|
* Defaults to: [MessageContent](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/Message/MessageSimple/MessageContent.tsx)
|
|
@@ -227,14 +232,14 @@ export type MessagesContextValue<
|
|
|
227
232
|
/**
|
|
228
233
|
* Override the api request for retry message functionality.
|
|
229
234
|
*/
|
|
230
|
-
retrySendMessage: (message:
|
|
235
|
+
retrySendMessage: (message: MessageType<StreamChatGenerics>) => Promise<void>;
|
|
231
236
|
/**
|
|
232
237
|
* UI component for ScrollToBottomButton
|
|
233
238
|
* Defaults to: [ScrollToBottomButton](https://getstream.io/chat/docs/sdk/reactnative/ui-components/scroll-to-bottom-button/)
|
|
234
239
|
*/
|
|
235
240
|
ScrollToBottomButton: React.ComponentType<ScrollToBottomButtonProps>;
|
|
236
241
|
sendReaction: (type: string, messageId: string) => Promise<void>;
|
|
237
|
-
setEditingState: (message
|
|
242
|
+
setEditingState: (message?: MessageType<StreamChatGenerics>) => void;
|
|
238
243
|
setQuotedMessageState: (message: MessageType<StreamChatGenerics> | boolean) => void;
|
|
239
244
|
supportedReactions: ReactionData[];
|
|
240
245
|
/**
|
package/src/i18n/en.json
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
"Allow camera access in device settings": "Allow camera access in device settings",
|
|
6
6
|
"Also send to channel": "Also send to channel",
|
|
7
7
|
"Are you sure you want to permanently delete this message?": "Are you sure you want to permanently delete this message?",
|
|
8
|
+
"Are you sure?": "Are you sure?",
|
|
8
9
|
"Block User": "Block User",
|
|
9
10
|
"Cancel": "Cancel",
|
|
10
11
|
"Cannot Flag Message": "Cannot Flag Message",
|
|
12
|
+
"Consider how your comment might make others feel and be sure to follow our Community Guidelines": "Consider how your comment might make others feel and be sure to follow our Community Guidelines",
|
|
11
13
|
"Copy Message": "Copy Message",
|
|
12
14
|
"Delete": "Delete",
|
|
13
15
|
"Delete Message": "Delete Message",
|
|
@@ -54,6 +56,7 @@
|
|
|
54
56
|
"Resend": "Resend",
|
|
55
57
|
"Search GIFs": "Search GIFs",
|
|
56
58
|
"Select More Photos": "Select More Photos",
|
|
59
|
+
"Send Anyway": "Send Anyway",
|
|
57
60
|
"Send a message": "Send a message",
|
|
58
61
|
"Sending links is not allowed in this conversation": "Sending links is not allowed in this conversation",
|
|
59
62
|
"Slow mode ON": "Slow mode ON",
|
package/src/i18n/es.json
CHANGED
|
@@ -73,5 +73,8 @@
|
|
|
73
73
|
"How about sending your first message to a friend?": "¿Qué tal enviar tu primer mensaje a un amigo?",
|
|
74
74
|
"Allow camera access in device settings": "Permitir el acceso a la cámara en la configuración del dispositivo",
|
|
75
75
|
"Device camera is used to take photos or videos.": "La cámara del dispositivo se utiliza para tomar fotografías o vídeos.",
|
|
76
|
-
"Open Settings": "Configuración abierta"
|
|
76
|
+
"Open Settings": "Configuración abierta",
|
|
77
|
+
"Send Anyway": "Enviar de todos modos",
|
|
78
|
+
"Are you sure?": "¿Estás seguro?",
|
|
79
|
+
"Consider how your comment might make others feel and be sure to follow our Community Guidelines": "Considera cómo tu comentario podría hacer sentir a los demás y asegúrate de seguir nuestras Normas de la Comunidad"
|
|
77
80
|
}
|
package/src/i18n/fr.json
CHANGED
|
@@ -5,33 +5,35 @@
|
|
|
5
5
|
"Allow camera access in device settings": "Autoriser l'accès à la caméra dans les paramètres de l'appareil",
|
|
6
6
|
"Also send to channel": "",
|
|
7
7
|
"Are you sure you want to permanently delete this message?": "",
|
|
8
|
+
"Are you sure?": "",
|
|
8
9
|
"Block User": "",
|
|
9
10
|
"Cancel": "",
|
|
10
11
|
"Cannot Flag Message": "",
|
|
12
|
+
"Consider how your comment might make others feel and be sure to follow our Community Guidelines": "",
|
|
11
13
|
"Copy Message": "",
|
|
12
14
|
"Delete": "",
|
|
13
15
|
"Delete Message": "",
|
|
14
16
|
"Device camera is used to take photos or videos.": "L'appareil photo de l'appareil est utilisé pour prendre des photos ou des vidéos.",
|
|
15
17
|
"Do you want to send a copy of this message to a moderator for further investigation?": "",
|
|
16
18
|
"Edit Message": "",
|
|
17
|
-
"Editing Message": "",
|
|
18
|
-
"Emoji matching": "",
|
|
19
|
+
"Editing Message": "Édite un message",
|
|
20
|
+
"Emoji matching": "Correspondance Emoji",
|
|
19
21
|
"Empty message...": "",
|
|
20
22
|
"Error loading": "",
|
|
21
23
|
"Error loading channel list...": "",
|
|
22
24
|
"Error loading messages for this channel...": "",
|
|
23
25
|
"Error while loading, please reload/refresh": "",
|
|
24
|
-
"File type not supported": "
|
|
26
|
+
"File type not supported": "",
|
|
25
27
|
"Flag": "",
|
|
26
28
|
"Flag Message": "",
|
|
27
29
|
"Flag action failed either due to a network issue or the message is already flagged": "",
|
|
28
30
|
"How about sending your first message to a friend?": "",
|
|
29
|
-
"Instant Commands": "",
|
|
31
|
+
"Instant Commands": "Commandes Instantanées",
|
|
30
32
|
"Let's start chatting!": "",
|
|
31
|
-
"Links are disabled": "
|
|
32
|
-
"Loading channels...": "",
|
|
33
|
-
"Loading messages...": "",
|
|
34
|
-
"Loading...": "",
|
|
33
|
+
"Links are disabled": "",
|
|
34
|
+
"Loading channels...": "Chargement des canaux...",
|
|
35
|
+
"Loading messages...": "Chargement des messages...",
|
|
36
|
+
"Loading...": "Chargement...",
|
|
35
37
|
"Maximum file size upload limit reached. Please upload a file below {{MAX_FILE_SIZE_TO_UPLOAD_IN_MB}} MB.": "",
|
|
36
38
|
"Message Reactions": "",
|
|
37
39
|
"Message deleted": "",
|
|
@@ -40,12 +42,12 @@
|
|
|
40
42
|
"Not supported": "Non pris en charge",
|
|
41
43
|
"Nothing yet...": "",
|
|
42
44
|
"Ok": "",
|
|
43
|
-
"Only visible to you": "
|
|
45
|
+
"Only visible to you": "",
|
|
44
46
|
"Open Settings": "Ouvrir les paramètres",
|
|
45
47
|
"Photo": "",
|
|
46
48
|
"Photos and Videos": "Photos et vidéos",
|
|
47
49
|
"Pin to Conversation": "",
|
|
48
|
-
"Pinned by": "
|
|
50
|
+
"Pinned by": "",
|
|
49
51
|
"Please enable access to your photos and videos so you can share them.": "Veuillez autoriser l'accès à vos photos et vidéos afin de pouvoir les partager.",
|
|
50
52
|
"Please select a channel first": "Veuillez d'abord selectionnez un canal",
|
|
51
53
|
"Reconnecting...": "",
|
|
@@ -54,8 +56,9 @@
|
|
|
54
56
|
"Resend": "",
|
|
55
57
|
"Search GIFs": "Rechercher des GIF",
|
|
56
58
|
"Select More Photos": "Sélectionner plus de photos",
|
|
59
|
+
"Send Anyway": "",
|
|
57
60
|
"Send a message": "Envoyer un message",
|
|
58
|
-
"Sending links is not allowed in this conversation": "
|
|
61
|
+
"Sending links is not allowed in this conversation": "",
|
|
59
62
|
"Slow mode ON": "Mode lent activé",
|
|
60
63
|
"The message has been reported to a moderator.": "",
|
|
61
64
|
"Thread Reply": "",
|
package/src/i18n/he.json
CHANGED
|
@@ -73,5 +73,8 @@
|
|
|
73
73
|
"How about sending your first message to a friend?": "מה דעתך לשלוח את ההודעה הראשונה שלך לחבר?",
|
|
74
74
|
"Allow camera access in device settings": "אפשר גישה למצלמה בהגדרות המכשיר",
|
|
75
75
|
"Device camera is used to take photos or videos.": "מצלמת המכשיר משמשת לצילום תמונות או סרטונים.",
|
|
76
|
-
"Open Settings": "פתח את ההגדרות"
|
|
76
|
+
"Open Settings": "פתח את ההגדרות",
|
|
77
|
+
"Send Anyway": "שלח בכל זאת",
|
|
78
|
+
"Are you sure?": "האם אתה בטוח?",
|
|
79
|
+
"Consider how your comment might make others feel and be sure to follow our Community Guidelines": "שקול איך התגובה שלך עשויה להשפיע על אחרים ווודא שאתה עוקב אחר ההנחיות של הקהילה שלנו"
|
|
77
80
|
}
|