agora-appbuilder-core 4.0.30 → 4.0.31-beta-2

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.
Files changed (32) hide show
  1. package/package.json +1 -1
  2. package/template/customization-api/sub-components.ts +1 -0
  3. package/template/defaultConfig.js +2 -2
  4. package/template/package.json +1 -1
  5. package/template/src/components/ChatContext.ts +3 -0
  6. package/template/src/components/Controls.tsx +80 -18
  7. package/template/src/components/Navbar.tsx +29 -1
  8. package/template/src/components/chat/chatConfigure.native.tsx +85 -25
  9. package/template/src/components/chat/chatConfigure.tsx +99 -9
  10. package/template/src/components/chat-messages/useChatMessages.tsx +32 -39
  11. package/template/src/components/chat-ui/useChatUIControls.tsx +21 -0
  12. package/template/src/components/precall/joinWaitingRoomBtn.tsx +25 -6
  13. package/template/src/components/room-info/useRoomInfo.tsx +12 -0
  14. package/template/src/pages/Create.tsx +26 -1
  15. package/template/src/pages/video-call/VideoCallMobileView.tsx +3 -2
  16. package/template/src/pages/video-call/VideoCallScreen.tsx +3 -1
  17. package/template/src/subComponents/ChatBubble.tsx +388 -110
  18. package/template/src/subComponents/ChatContainer.tsx +76 -53
  19. package/template/src/subComponents/ChatInput.native.tsx +93 -14
  20. package/template/src/subComponents/ChatInput.tsx +41 -7
  21. package/template/src/subComponents/caption/Caption.tsx +14 -2
  22. package/template/src/subComponents/caption/CaptionContainer.tsx +24 -3
  23. package/template/src/subComponents/caption/CaptionText.tsx +13 -1
  24. package/template/src/subComponents/chat/ChatActionMenu.tsx +40 -3
  25. package/template/src/subComponents/chat/ChatAttachment.native.tsx +4 -2
  26. package/template/src/subComponents/chat/ChatEmoji.native.tsx +181 -22
  27. package/template/src/subComponents/chat/ChatEmoji.tsx +4 -3
  28. package/template/src/subComponents/chat/ChatQuickActionsMenu.tsx +70 -34
  29. package/template/src/subComponents/chat/ChatSendButton.tsx +42 -1
  30. package/template/src/subComponents/chat/PinnedMessage.tsx +207 -0
  31. package/template/src/utils/useCreateRoom.ts +23 -4
  32. package/template/src/utils/useJoinRoom.ts +76 -23
@@ -43,11 +43,12 @@ interface ExtendedChatMessage extends ChatMessage {
43
43
  attributes: {
44
44
  file_ext?: string;
45
45
  file_name?: string;
46
+ replyToMsgId?: string;
46
47
  };
47
48
  }
48
49
 
49
50
  export const ChatAttachmentButton = (props: ChatAttachmentButtonProps) => {
50
- const {privateChatUser, setUploadStatus} = useChatUIControls();
51
+ const {privateChatUser, setUploadStatus, replyToMsgId} = useChatUIControls();
51
52
  const {sendChatSDKMessage} = useChatConfigure();
52
53
  const {data} = useRoomInfo();
53
54
 
@@ -140,6 +141,7 @@ export const ChatAttachmentButton = (props: ChatAttachmentButtonProps) => {
140
141
  file_name: result[0].name,
141
142
  file_url: filePath,
142
143
  from_platform: 'native',
144
+ replyToMsgId,
143
145
  },
144
146
  };
145
147
  console.warn('chatOPtion', option);
@@ -166,8 +168,8 @@ export const ChatAttachmentButton = (props: ChatAttachmentButtonProps) => {
166
168
  url: message.body?.remotePath,
167
169
  ext: message.attributes?.file_ext,
168
170
  fileName: message.attributes?.file_name,
171
+ replyToMsgId: message.attributes?.replyToMsgId,
169
172
  };
170
- console.warn('message data', messageData);
171
173
 
172
174
  // this is local user messages
173
175
  if (message.chatType === ChatMessageChatType.PeerChat) {
@@ -1,9 +1,11 @@
1
- import {StyleSheet, Text, View} from 'react-native';
1
+ import {Button, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
2
2
  import React from 'react';
3
3
  import {useChatUIControls} from '../../components/chat-ui/useChatUIControls';
4
4
  import IconButton from '../../../src/atoms/IconButton';
5
- //import data from 'emoji-mart-native/data/google.json';
6
- import {Picker} from 'emoji-mart-native';
5
+ import {useChatConfigure} from '../../../src/components/chat/chatConfigure';
6
+ import {MoreMessageOptions} from './ChatQuickActionsMenu';
7
+ import {hexadecimalTransparency} from 'customization-api';
8
+ import EmojiPicker, {type EmojiType} from 'rn-emoji-keyboard';
7
9
 
8
10
  export interface ChatEmojiButtonProps {
9
11
  render?: (onPress: () => void) => JSX.Element;
@@ -32,7 +34,7 @@ export const ChatEmojiButton = (props: ChatEmojiButtonProps) => {
32
34
  },
33
35
  iconSize: 24,
34
36
  name: 'chat_emoji',
35
- tintColor: $config.SECONDARY_ACTION_COLOR,
37
+ tintColor: $config.SEMANTIC_NEUTRAL,
36
38
  }}
37
39
  onPress={onPress}
38
40
  />
@@ -40,28 +42,150 @@ export const ChatEmojiButton = (props: ChatEmojiButtonProps) => {
40
42
  );
41
43
  };
42
44
 
43
- export const ChatEmojiPicker = () => {
44
- const {setShowEmojiPicker, setMessage} = useChatUIControls();
45
- const handleEmojiClick = emoji => {
46
- setMessage(prev => prev + ' ' + emoji.native);
45
+ export const ChatEmojiPicker = ({
46
+ isEmojiPickerOpen,
47
+ setIsEmojiPickerOpen,
48
+ onEmojiSelect,
49
+ }) => {
50
+ const handleEmojiClick = ({emoji}) => {
51
+ onEmojiSelect(emoji);
47
52
  };
48
53
  return (
49
54
  <View style={styles.emojiContainer} testID={'emoji-container'}>
50
- <Picker
51
- //data={data}
52
- // autoFocus={true}
53
- native={true}
54
- emojiSize={28}
55
- perLine={9}
56
- onPressClose={() => setShowEmojiPicker(false)}
57
- showSkinTones={false}
58
- color={$config.PRIMARY_ACTION_BRAND_COLOR}
59
- theme={
60
- $config.INPUT_FIELD_BACKGROUND_COLOR === '#FFFFFF' ? 'light' : 'dark'
61
- }
62
- showCloseButton={true}
63
- onSelect={handleEmojiClick}
55
+ <EmojiPicker
56
+ onEmojiSelected={handleEmojiClick}
57
+ open={isEmojiPickerOpen}
58
+ categoryPosition="top" // floating' | 'top' | 'bottom'
59
+ onClose={() => setIsEmojiPickerOpen(false)}
60
+ theme={{
61
+ backdrop:
62
+ $config.HARD_CODED_BLACK_COLOR + hexadecimalTransparency['60%'], // need design input
63
+ knob: $config.SECONDARY_ACTION_COLOR,
64
+ container: $config.CARD_LAYER_3_COLOR,
65
+ header: $config.FONT_COLOR,
66
+ category: {
67
+ icon: $config.SECONDARY_ACTION_COLOR,
68
+ iconActive: $config.SECONDARY_ACTION_COLOR, // need design input
69
+ container: $config.CARD_LAYER_2_COLOR,
70
+ containerActive: $config.PRIMARY_ACTION_BRAND_COLOR, // need design input
71
+ },
72
+ }}
73
+ />
74
+ </View>
75
+ );
76
+ };
77
+
78
+ export const ReactionPicker = props => {
79
+ const {setMessage, showEmojiPicker, setShowEmojiPicker} = useChatUIControls();
80
+ const {addReaction} = useChatConfigure();
81
+ const {messageId, isLocal, userId, type, message, setIsHovered} = props;
82
+
83
+ // Controls the reactions to display in the reactions picker. Takes unified emoji ids
84
+ const reactions = [
85
+ {emoji: '❤️', unified: '2665-fe0f'},
86
+ {emoji: '👍', unified: '1f44d'},
87
+ {emoji: '🎉', unified: '1f389'},
88
+ {
89
+ emoji: '🤣',
90
+ unified: '1f923',
91
+ },
92
+ ];
93
+
94
+ const handleReactionClick = emoji => {
95
+ addReaction(messageId, emoji);
96
+ setIsHovered(false);
97
+ };
98
+
99
+ return (
100
+ <View
101
+ style={[styles.reactionsContainer, isLocal ? {right: 0} : {left: 0}]}
102
+ testID={'reaction-container'}>
103
+ {reactions.map((emojiObject, index) => (
104
+ <React.Fragment key={emojiObject.unified}>
105
+ <TouchableOpacity
106
+ style={styles.emojiWrapper}
107
+ onPress={() => handleReactionClick(emojiObject.emoji)}>
108
+ <Text style={{fontSize: 16}}>{emojiObject.emoji}</Text>
109
+ </TouchableOpacity>
110
+ {index === reactions.length - 1 && (
111
+ <>
112
+ <CustomReactionPicker
113
+ isLocal={isLocal}
114
+ messageId={messageId}
115
+ setIsHovered={setIsHovered}
116
+ />
117
+
118
+ <MoreMessageOptions
119
+ userId={userId}
120
+ isLocal={isLocal}
121
+ messageId={messageId}
122
+ type={type}
123
+ message={message}
124
+ setIsHovered={setIsHovered}
125
+ />
126
+ </>
127
+ )}
128
+ </React.Fragment>
129
+ ))}
130
+ </View>
131
+ );
132
+ };
133
+
134
+ export const CustomReactionPicker = ({isLocal, setIsHovered, messageId}) => {
135
+ const [isEmojiPickerOpen, setIsEmojiPickerOpen] = React.useState(false);
136
+ const {addReaction} = useChatConfigure();
137
+ const handleCustomReactionClick = (emoji: string) => {
138
+ addReaction(messageId, emoji);
139
+ setIsHovered(false);
140
+ };
141
+
142
+ return (
143
+ <View>
144
+ <IconButton
145
+ hoverEffect={false}
146
+ hoverEffectStyle={{
147
+ backgroundColor: $config.ICON_BG_COLOR,
148
+ borderRadius: 24,
149
+ }}
150
+ iconProps={{
151
+ iconType: 'plain',
152
+ base64: false,
153
+ iconContainerStyle: {
154
+ padding: 2,
155
+ marginHorizontal: 4,
156
+ },
157
+ iconSize: 20,
158
+ name: 'add_reaction',
159
+ tintColor:
160
+ $config.SECONDARY_ACTION_COLOR + hexadecimalTransparency['75%'],
161
+ }}
162
+ onPress={() => {
163
+ setIsEmojiPickerOpen(true);
164
+ }}
64
165
  />
166
+ {isEmojiPickerOpen ? (
167
+ <ChatEmojiPicker
168
+ isEmojiPickerOpen={isEmojiPickerOpen}
169
+ setIsEmojiPickerOpen={setIsEmojiPickerOpen}
170
+ onEmojiSelect={handleCustomReactionClick}
171
+ />
172
+ ) : (
173
+ <></>
174
+ )}
175
+ {/* {isEmojiPickerOpen && (
176
+ <CustomEmojiPicker
177
+ containerStyle={[
178
+ styles.customEmojiPickerContainer,
179
+ isLocal ? {right: 0} : {left: 0},
180
+ ]}
181
+ isReactionPicker={true}
182
+ handleEmojiClick={handleCustomReactionClick}
183
+ handleEmojiClose={() => {
184
+ setIsEmojiPickerOpen(false);
185
+ setIsHovered(false);
186
+ }}
187
+ />
188
+ )} */}
65
189
  </View>
66
190
  );
67
191
  };
@@ -72,4 +196,39 @@ const styles = StyleSheet.create({
72
196
  flexDirection: 'row',
73
197
  position: 'relative',
74
198
  },
199
+ emojiWrapper: {
200
+ width: 20,
201
+ height: 20,
202
+ marginHorizontal: 5,
203
+ justifyContent: 'center',
204
+ alignItems: 'center',
205
+ display: 'flex',
206
+ },
207
+ reactionsContainer: {
208
+ flexDirection: 'row',
209
+ position: 'absolute',
210
+ bottom: '100%',
211
+ padding: 4,
212
+ justifyContent: 'space-evenly',
213
+ alignItems: 'center',
214
+ backgroundColor: $config.CARD_LAYER_4_COLOR,
215
+ borderWidth: 1,
216
+ borderColor: $config.CARD_LAYER_5_COLOR + hexadecimalTransparency['25%'],
217
+ borderRadius: 4,
218
+ zIndex: 1,
219
+ shadowColor: $config.HARD_CODED_BLACK_COLOR,
220
+ shadowOffset: {
221
+ width: 0,
222
+ height: 4,
223
+ },
224
+ shadowOpacity: 0.35,
225
+ shadowRadius: 10,
226
+ elevation: 5,
227
+ },
228
+ customEmojiPickerContainer: {
229
+ position: 'absolute',
230
+ top: 30,
231
+ right: 0,
232
+ width: 350,
233
+ },
75
234
  });
@@ -157,7 +157,7 @@ const CustomEmojiPicker = ({
157
157
  );
158
158
  };
159
159
 
160
- const CustomReactioPicker = ({isLocal, setIsHovered, messageId}) => {
160
+ export const CustomReactionPicker = ({isLocal, setIsHovered, messageId}) => {
161
161
  const [isEmojiPickerOpen, setIsEmojiPickerOpen] = React.useState(false);
162
162
  const {addReaction} = useChatConfigure();
163
163
  const handleCustomReactionClick = (emojiObject: {
@@ -181,7 +181,7 @@ const CustomReactioPicker = ({isLocal, setIsHovered, messageId}) => {
181
181
  iconType: 'plain',
182
182
  base64: false,
183
183
  iconContainerStyle: {
184
- padding: 0,
184
+ padding: 2,
185
185
  marginHorizontal: 4,
186
186
  },
187
187
  iconSize: 20,
@@ -245,7 +245,7 @@ export const ReactionPicker = props => {
245
245
  </TouchableOpacity>
246
246
  {index === reactions.length - 1 && (
247
247
  <>
248
- <CustomReactioPicker
248
+ <CustomReactionPicker
249
249
  isLocal={isLocal}
250
250
  messageId={messageId}
251
251
  setIsHovered={setIsHovered}
@@ -256,6 +256,7 @@ export const ReactionPicker = props => {
256
256
  messageId={messageId}
257
257
  type={type}
258
258
  message={message}
259
+ setIsHovered={setIsHovered}
259
260
  />
260
261
  </>
261
262
  )}
@@ -1,7 +1,11 @@
1
1
  import {StyleSheet, Text, useWindowDimensions, View} from 'react-native';
2
2
  import React from 'react';
3
3
  import ActionMenu, {ActionMenuItem} from '../../../src/atoms/ActionMenu';
4
- import {calculatePosition, trimText} from '../../../src/utils/common';
4
+ import {
5
+ calculatePosition,
6
+ isWebInternal,
7
+ trimText,
8
+ } from '../../../src/utils/common';
5
9
  import IconButton from '../../../src/atoms/IconButton';
6
10
  import hexadecimalTransparency from '../../../src/utils/hexadecimalTransparency';
7
11
  import {
@@ -37,6 +41,8 @@ interface ChatQuickActionsMenuProps {
37
41
  messageId?: string;
38
42
  type: ChatMessageType;
39
43
  message: string;
44
+ showReplyOption?: boolean;
45
+ setIsHovered?: (isHover: boolean) => void;
40
46
  }
41
47
 
42
48
  const ChatQuickActionsMenu = (props: ChatQuickActionsMenuProps) => {
@@ -49,17 +55,28 @@ const ChatQuickActionsMenu = (props: ChatQuickActionsMenuProps) => {
49
55
  messageId,
50
56
  type,
51
57
  message: msg,
58
+ showReplyOption,
59
+ setIsHovered,
52
60
  } = props;
53
61
  const [isPosCalculated, setIsPosCalculated] = React.useState(false);
54
62
  const {width: globalWidth, height: globalHeight} = useWindowDimensions();
55
63
  const [modalPosition, setModalPosition] = React.useState({});
56
- const {setChatType, setPrivateChatUser, showEmojiPicker, privateChatUser} =
57
- useChatUIControls();
64
+ const {
65
+ setChatType,
66
+ setPrivateChatUser,
67
+ showEmojiPicker,
68
+ privateChatUser,
69
+ replyToMsgId,
70
+ pinMsgId,
71
+ setPinMsgId,
72
+ setReplyToMsgId,
73
+ pinnedByUser,
74
+ } = useChatUIControls();
58
75
  const {removeMessageFromPrivateStore, removeMessageFromStore} =
59
76
  useChatMessages();
60
77
  const [showDeleteMessageModal, setShowDeleteMessageModal] =
61
78
  React.useState(false);
62
- const {deleteAttachment} = useChatConfigure();
79
+ const {deleteAttachment, pinMessage, unPinMessage} = useChatConfigure();
63
80
 
64
81
  const actionMenuitems: ActionMenuItem[] = [];
65
82
  const {defaultContent} = useContent();
@@ -69,16 +86,21 @@ const ChatQuickActionsMenu = (props: ChatQuickActionsMenuProps) => {
69
86
  } = useRoomInfo();
70
87
 
71
88
  const groupID = chat.group_id;
89
+ const isGroupOwner = chat.is_group_owner;
90
+ const isMsgPinned = pinMsgId === messageId;
72
91
 
73
- // actionMenuitems.push({
74
- // icon: 'reply',
75
- // iconColor: $config.SECONDARY_ACTION_COLOR,
76
- // textColor: $config.FONT_COLOR,
77
- // title: 'Reply',
78
- // onPress: () => {
79
- // setActionMenuVisible(false);
80
- // },
81
- // });
92
+ showReplyOption &&
93
+ actionMenuitems.push({
94
+ icon: 'reply',
95
+ iconColor: $config.SECONDARY_ACTION_COLOR,
96
+ textColor: $config.FONT_COLOR,
97
+ title: 'Reply',
98
+ onPress: () => {
99
+ setReplyToMsgId(messageId);
100
+ setActionMenuVisible(false);
101
+ setIsHovered(false);
102
+ },
103
+ });
82
104
 
83
105
  const cancelTxt = useString(cancelText)();
84
106
  const cancelLabel =
@@ -108,9 +130,11 @@ const ChatQuickActionsMenu = (props: ChatQuickActionsMenuProps) => {
108
130
  iconSize: 14,
109
131
  title: 'Private Reply',
110
132
  onPress: () => {
133
+ setReplyToMsgId(messageId);
111
134
  setPrivateChatUser(userId);
112
135
  setChatType(ChatType.Private);
113
136
  setActionMenuVisible(false);
137
+ setIsHovered(false);
114
138
  },
115
139
  });
116
140
 
@@ -123,41 +147,50 @@ const ChatQuickActionsMenu = (props: ChatQuickActionsMenuProps) => {
123
147
  onPress: () => {
124
148
  Clipboard.setString(msg);
125
149
  setActionMenuVisible(false);
150
+ setIsHovered(false);
151
+ },
152
+ });
153
+
154
+ // native pin message to be released with 1.3.0 chat sdk
155
+ isWebInternal() &&
156
+ chatType == SDKChatType.GROUP_CHAT &&
157
+ actionMenuitems.push({
158
+ icon: isMsgPinned ? 'unpin-outlined' : 'pin-outlined',
159
+ iconColor: $config.SECONDARY_ACTION_COLOR,
160
+ textColor: $config.FONT_COLOR,
161
+ title: isMsgPinned ? 'UnPin Message' : 'Pin Message',
162
+ onPress: () => {
163
+ isMsgPinned ? unPinMessage(messageId) : pinMessage(messageId);
164
+ setActionMenuVisible(false);
165
+ setIsHovered(false);
126
166
  },
127
167
  });
128
- // actionMenuitems.push({
129
- // icon: 'pin-outlined',
130
- // iconColor: $config.SECONDARY_ACTION_COLOR,
131
- // textColor: $config.FONT_COLOR,
132
- // title: 'Pin Message',
133
- // onPress: () => {
134
- // setActionMenuVisible(false);
135
- // },
136
- // });
137
168
 
138
- // actionMenuitems.push({
139
- // icon: 'block_user',
140
- // iconColor: $config.SEMANTIC_ERROR,
141
- // textColor: $config.SEMANTIC_ERROR,
142
- // title: 'Block User',
143
- // onPress: () => {
144
- // // block user can be done only by group owner and admins
145
- // setActionMenuVisible(false);
146
- // },
147
- // });
169
+ //Only Chat Group Owner and Admin can block a user
170
+ // isGroupOwner &&
171
+ // actionMenuitems.push({
172
+ // icon: 'block_user',
173
+ // iconColor: $config.SEMANTIC_ERROR,
174
+ // textColor: $config.SEMANTIC_ERROR,
175
+ // title: 'Block User',
176
+ // onPress: () => {
177
+ // // block user can be done only by group owner and admins
178
+ // setActionMenuVisible(false);
179
+ // },
180
+ // });
148
181
 
149
182
  actionMenuitems.push({
150
183
  icon: 'delete',
151
184
  iconColor: $config.SEMANTIC_ERROR,
152
185
  textColor: $config.SEMANTIC_ERROR,
153
186
  title: 'Delete Message',
187
+ disabled: isMsgPinned,
154
188
  onPress: () => {
155
189
  if (isLocal) {
156
190
  // confirm dialog : user is deleting for all
157
191
  setShowDeleteMessageModal(true);
158
192
  //deleteAttachment(msgId, recallFromUser.toString(), chatType);
159
193
  } else {
160
- debugger;
161
194
  if (chatType === SDKChatType.GROUP_CHAT) {
162
195
  removeMessageFromStore(messageId, isLocal);
163
196
  }
@@ -238,6 +271,8 @@ export const MoreMessageOptions = ({
238
271
  messageId,
239
272
  type,
240
273
  message,
274
+ showReplyOption = true,
275
+ setIsHovered,
241
276
  }) => {
242
277
  const moreIconRef = React.useRef(null);
243
278
  const [messageOptionsMenuVisible, setMessageOptionsMenuVisible] =
@@ -256,6 +291,8 @@ export const MoreMessageOptions = ({
256
291
  messageId={messageId}
257
292
  type={type}
258
293
  message={message}
294
+ showReplyOption={showReplyOption}
295
+ setIsHovered={setIsHovered}
259
296
  />
260
297
 
261
298
  <View
@@ -278,7 +315,6 @@ export const MoreMessageOptions = ({
278
315
  borderRadius: 4,
279
316
  padding: 2,
280
317
  }}
281
- containerStyle={{margin: 4}}
282
318
  iconProps={{
283
319
  iconType: 'plain',
284
320
  name: 'more-menu',
@@ -12,6 +12,7 @@ import {useRoomInfo} from 'customization-api';
12
12
  import {
13
13
  ChatMessageType,
14
14
  SDKChatType,
15
+ useChatMessages,
15
16
  } from '../../components/chat-messages/useChatMessages';
16
17
  import {useString} from '../../utils/useString';
17
18
  import {
@@ -21,6 +22,7 @@ import {
21
22
  } from '../../language/default-labels/videoCallScreenLabels';
22
23
  import {isMobileUA, isWeb} from '../../utils/common';
23
24
  import Toast from '../../../react-native-toast-message';
25
+ import {ChatMessageChatType} from 'react-native-agora-chat';
24
26
 
25
27
  export interface ChatSendButtonProps {
26
28
  render?: (onPress: () => void) => JSX.Element;
@@ -41,6 +43,10 @@ export const handleChatSend = ({
41
43
  toastHeadingSize,
42
44
  errorSubHeadingSize,
43
45
  _resetTextareaHeight,
46
+ replyToMsgId,
47
+ setReplyToMsgId,
48
+ addMessageToStore,
49
+ addMessageToPrivateStore,
44
50
  }) => {
45
51
  const isAllFilesUploaded =
46
52
  uploadedFiles.length > 0 &&
@@ -76,9 +82,35 @@ export const handleChatSend = ({
76
82
  to: selectedUserId ? selectedUserId.toString() : groupID,
77
83
  ext: {
78
84
  from_platform: isWeb() ? 'web' : 'native',
85
+ replyToMsgId: replyToMsgId,
79
86
  },
80
87
  };
81
- sendChatSDKMessage(option);
88
+ const onProgress = (localMsgId: string, progress: number) => {
89
+ console.warn('chat msg in progress', progress);
90
+ };
91
+ const onError = (localMsgId: string, error: any) => {
92
+ console.warn('chat msg in error', error);
93
+ };
94
+ const onSuccess = (message: any) => {
95
+ console.warn('chat msg in success', message);
96
+ // Text message added here , attachments are added in ChatAttachment.native
97
+ const messageData = {
98
+ msg: option.msg.replace(/^(\n)+|(\n)+$/g, ''),
99
+ createdTimestamp: message.localTime,
100
+ msgId: message.msgId,
101
+ isDeleted: false,
102
+ type: message.body.type,
103
+ replyToMsgId: message.attributes?.replyToMsgId,
104
+ };
105
+ console.warn('message data', messageData);
106
+ // this is local user messages
107
+ if (message.chatType === ChatMessageChatType.PeerChat) {
108
+ addMessageToPrivateStore(Number(message.to), messageData, true);
109
+ } else {
110
+ addMessageToStore(Number(message.from), messageData);
111
+ }
112
+ };
113
+ sendChatSDKMessage(option, {onProgress, onError, onSuccess});
82
114
  };
83
115
 
84
116
  if (uploadedFiles.length > 0) {
@@ -106,6 +138,7 @@ export const handleChatSend = ({
106
138
  file_name,
107
139
  from_platform: isWeb() ? 'web' : 'native',
108
140
  msg: uploadedFiles.length === 1 ? message : '',
141
+ replyToMsgId: replyToMsgId,
109
142
  },
110
143
  };
111
144
  sendChatSDKMessage(option);
@@ -120,6 +153,7 @@ export const handleChatSend = ({
120
153
  }
121
154
 
122
155
  setMessage && setMessage('');
156
+ setReplyToMsgId('');
123
157
  setInputHeight && setInputHeight(MIN_HEIGHT);
124
158
  setUploadedFiles && setUploadedFiles(prev => []);
125
159
  isWeb() && setShowEmojiPicker(false);
@@ -128,6 +162,7 @@ export const handleChatSend = ({
128
162
  const ChatSendButton = (props: ChatSendButtonProps) => {
129
163
  const {sendChatSDKMessage} = useChatConfigure();
130
164
  const {setShowEmojiPicker} = useChatUIControls();
165
+ const {addMessageToPrivateStore, addMessageToStore} = useChatMessages();
131
166
  const {
132
167
  privateChatUser: selectedUserId,
133
168
  message,
@@ -138,6 +173,8 @@ const ChatSendButton = (props: ChatSendButtonProps) => {
138
173
  setUploadedFiles,
139
174
  setInputHeight,
140
175
  _resetTextareaHeight,
176
+ replyToMsgId,
177
+ setReplyToMsgId,
141
178
  } = useChatUIControls();
142
179
 
143
180
  const {data} = useRoomInfo();
@@ -166,6 +203,10 @@ const ChatSendButton = (props: ChatSendButtonProps) => {
166
203
  toastHeadingSize,
167
204
  errorSubHeadingSize,
168
205
  _resetTextareaHeight,
206
+ replyToMsgId,
207
+ setReplyToMsgId,
208
+ addMessageToPrivateStore,
209
+ addMessageToStore,
169
210
  });
170
211
 
171
212
  return props?.render ? (