agora-appbuilder-core 4.0.30-beta-4 → 4.0.31-beta-1

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 (31) 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 +51 -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 +5 -0
  11. package/template/src/components/chat-ui/useChatUIControls.tsx +21 -0
  12. package/template/src/components/room-info/useRoomInfo.tsx +12 -0
  13. package/template/src/pages/Create.tsx +25 -1
  14. package/template/src/pages/video-call/VideoCallMobileView.tsx +3 -2
  15. package/template/src/pages/video-call/VideoCallScreen.tsx +3 -1
  16. package/template/src/subComponents/ChatBubble.tsx +387 -110
  17. package/template/src/subComponents/ChatContainer.tsx +20 -2
  18. package/template/src/subComponents/ChatInput.native.tsx +93 -14
  19. package/template/src/subComponents/ChatInput.tsx +41 -7
  20. package/template/src/subComponents/caption/Caption.tsx +14 -2
  21. package/template/src/subComponents/caption/CaptionContainer.tsx +24 -3
  22. package/template/src/subComponents/caption/CaptionText.tsx +13 -1
  23. package/template/src/subComponents/chat/ChatActionMenu.tsx +40 -3
  24. package/template/src/subComponents/chat/ChatAttachment.native.tsx +4 -2
  25. package/template/src/subComponents/chat/ChatEmoji.native.tsx +181 -22
  26. package/template/src/subComponents/chat/ChatEmoji.tsx +4 -3
  27. package/template/src/subComponents/chat/ChatQuickActionsMenu.tsx +69 -33
  28. package/template/src/subComponents/chat/ChatSendButton.tsx +42 -1
  29. package/template/src/subComponents/chat/PinnedMessage.tsx +198 -0
  30. package/template/src/utils/useCreateRoom.ts +23 -4
  31. package/template/src/utils/useJoinRoom.ts +76 -23
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "4.0.30-beta-4",
3
+ "version": "4.0.31-beta-1",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -86,3 +86,4 @@ export type {TranscriptProps} from '../src/subComponents/caption/Transcript';
86
86
  export {default as CaptionPanel} from '../src/subComponents/caption/CaptionContainer';
87
87
  export {default as VBPreview} from '../src/components/virtual-background/VideoPreview';
88
88
  export {default as Toast} from '../react-native-toast-message';
89
+ export {default as CaptionContainer} from '../src/subComponents/caption/CaptionContainer';
@@ -76,8 +76,8 @@ const DefaultConfig = {
76
76
  CHAT_ORG_NAME: '',
77
77
  CHAT_APP_NAME: '',
78
78
  CHAT_URL: '',
79
- CLI_VERSION: '3.0.30-beta-4',
80
- CORE_VERSION: '4.0.30-beta-4',
79
+ CLI_VERSION: '3.0.30-1',
80
+ CORE_VERSION: '4.0.30-1',
81
81
  DISABLE_LANDSCAPE_MODE: false,
82
82
  STT_AUTO_START: false,
83
83
  CLOUD_RECORDING_AUTO_START: false,
@@ -70,7 +70,6 @@
70
70
  "electron-log": "4.3.5",
71
71
  "electron-squirrel-startup": "1.0.0",
72
72
  "electron-updater": "4.3.9",
73
- "emoji-mart-native": "^0.6.5-beta",
74
73
  "emoji-picker-react": "^4.7.1",
75
74
  "exponential-backoff": "3.1.0",
76
75
  "fetch-retry": "^5.0.6",
@@ -110,6 +109,7 @@
110
109
  "react-router-native": "5.2.0",
111
110
  "react-spring-bottom-sheet": "3.4.1",
112
111
  "react-tooltip": "4.5.1",
112
+ "rn-emoji-keyboard": "^1.7.0",
113
113
  "rn-fetch-blob": "0.12.0",
114
114
  "white-web-sdk": "2.16.42"
115
115
  },
@@ -33,6 +33,8 @@ export interface ChatBubbleProps {
33
33
  previousMessageCreatedTimestamp?: string;
34
34
  reactions?: Reaction[];
35
35
  scrollOffset?: number;
36
+ replyToMsgId?: string;
37
+ isLastMsg?: boolean;
36
38
 
37
39
  render?: (
38
40
  isLocal: boolean,
@@ -50,6 +52,7 @@ export interface ChatBubbleProps {
50
52
  ext?: string,
51
53
  previousMessageCreatedTimestamp?: string,
52
54
  reactions?: Reaction[],
55
+ replyToMsgId?: string,
53
56
  ) => JSX.Element;
54
57
  }
55
58
 
@@ -254,6 +254,7 @@ export const WhiteboardListener = () => {
254
254
 
255
255
  const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
256
256
  const {label} = useToolbarProps();
257
+ const {data} = useRoomInfo();
257
258
  const noiseCancellationLabel = useString(toolbarItemNoiseCancellationText)();
258
259
  const whiteboardLabel = useString<boolean>(toolbarItemWhiteboardText);
259
260
  const captionLabel = useString<boolean>(toolbarItemCaptionText);
@@ -452,6 +453,13 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
452
453
  whiteboardRoomState === RoomPhase.Connecting ||
453
454
  whiteboardRoomState === RoomPhase.Disconnecting;
454
455
 
456
+ //Disable whiteboard button when backend sends error
457
+ const WhiteboardError =
458
+ data?.whiteboard?.error &&
459
+ (data?.whiteboard?.error?.code || data?.whiteboard?.error?.message)
460
+ ? true
461
+ : false;
462
+
455
463
  //whiteboard ends
456
464
 
457
465
  if (isHost && $config.ENABLE_WHITEBOARD && isWebInternal()) {
@@ -466,8 +474,31 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
466
474
  textColor: $config.FONT_COLOR,
467
475
  title: whiteboardLabel(whiteboardActive),
468
476
  onPress: () => {
469
- setActionMenuVisible(false);
470
- toggleWhiteboard(whiteboardActive, true);
477
+ if (WhiteboardError) {
478
+ setActionMenuVisible(false);
479
+ Toast.show({
480
+ leadingIconName: 'alert',
481
+ type: 'error',
482
+ text1: 'Failed to enable Whiteboard Service.',
483
+ text2: data?.whiteboard?.error?.message,
484
+ visibilityTime: 1000 * 10,
485
+ primaryBtn: null,
486
+ secondaryBtn: null,
487
+ leadingIcon: null,
488
+ });
489
+ logger.error(
490
+ LogSource.Internals,
491
+ 'JOIN_MEETING',
492
+ 'Failed to enable Whiteboard Service',
493
+ {
494
+ message: data?.whiteboard?.error?.message,
495
+ code: data?.whiteboard?.error?.code,
496
+ },
497
+ );
498
+ } else {
499
+ setActionMenuVisible(false);
500
+ toggleWhiteboard(whiteboardActive, true);
501
+ }
471
502
  },
472
503
  });
473
504
  }
@@ -572,22 +603,24 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
572
603
  },
573
604
  });
574
605
 
575
- actionMenuitems.push({
576
- hide: w => {
577
- return w >= BREAKPOINTS.lg ? true : false;
578
- },
579
- componentName: 'chat',
580
- order: 7,
581
- icon: 'chat-nav',
582
- iconColor: $config.SECONDARY_ACTION_COLOR,
583
- textColor: $config.FONT_COLOR,
584
- title: chatLabel,
585
- onPress: () => {
586
- setActionMenuVisible(false);
587
- setChatType(ChatType.Group);
588
- setSidePanel(SidePanelType.Chat);
589
- },
590
- });
606
+ if ($config.CHAT) {
607
+ actionMenuitems.push({
608
+ hide: w => {
609
+ return w >= BREAKPOINTS.lg ? true : false;
610
+ },
611
+ componentName: 'chat',
612
+ order: 7,
613
+ icon: 'chat-nav',
614
+ iconColor: $config.SECONDARY_ACTION_COLOR,
615
+ textColor: $config.FONT_COLOR,
616
+ title: chatLabel,
617
+ onPress: () => {
618
+ setActionMenuVisible(false);
619
+ setChatType(ChatType.Group);
620
+ setSidePanel(SidePanelType.Chat);
621
+ },
622
+ });
623
+ }
591
624
 
592
625
  if ($config.SCREEN_SHARING) {
593
626
  if (
@@ -62,6 +62,8 @@ import {
62
62
  videoRoomRecordingText,
63
63
  } from '../language/default-labels/videoCallScreenLabels';
64
64
  import {useLanguage} from '../language/useLanguage';
65
+ import Toast from '../../react-native-toast-message';
66
+ import {logger, LogSource} from '../logger/AppBuilderLogger';
65
67
 
66
68
  export const ParticipantsCountView = ({
67
69
  isMobileView = false,
@@ -223,6 +225,12 @@ export const ChatIconButton = (props: ChatIconButtonProps) => {
223
225
  const {label = null, onPress: onPressCustom = null} = useToolbarProps();
224
226
  const {sidePanel, setSidePanel} = useSidePanel();
225
227
  const {isToolbarMenuItem} = useToolbarMenu();
228
+ const {data} = useRoomInfo();
229
+ //disable chat button when BE sends error on chat
230
+ const ChatError =
231
+ data?.chat?.error && (data?.chat?.error?.code || data?.chat?.error?.message)
232
+ ? true
233
+ : false;
226
234
  const {
227
235
  badgeContainerPosition = {
228
236
  top: 0,
@@ -249,7 +257,27 @@ export const ChatIconButton = (props: ChatIconButtonProps) => {
249
257
  }, [sidePanel]);
250
258
 
251
259
  const onPress = () => {
252
- {
260
+ if (ChatError) {
261
+ Toast.show({
262
+ leadingIconName: 'alert',
263
+ type: 'error',
264
+ text1: 'Failed to enable Chat Service.',
265
+ text2: data?.chat?.error?.message,
266
+ visibilityTime: 1000 * 10,
267
+ primaryBtn: null,
268
+ secondaryBtn: null,
269
+ leadingIcon: null,
270
+ });
271
+ logger.error(
272
+ LogSource.Internals,
273
+ 'JOIN_MEETING',
274
+ 'Failed to enable Chat Service',
275
+ {
276
+ message: data?.chat?.error?.message,
277
+ code: data?.chat?.error?.code,
278
+ },
279
+ );
280
+ } else {
253
281
  if (isPanelActive) {
254
282
  setSidePanel(SidePanelType.None);
255
283
  setChatType(ChatType.Group);
@@ -1,7 +1,7 @@
1
1
  import {createHook} from 'customization-implementation';
2
2
  import React, {createContext, useEffect, useState} from 'react';
3
3
  import {useRoomInfo} from '../room-info/useRoomInfo';
4
- import {useContent} from 'customization-api';
4
+ import {useChatUIControls, useContent} from 'customization-api';
5
5
  import {
6
6
  ChatClient,
7
7
  ChatConnectEventListener,
@@ -32,6 +32,7 @@ interface ChatMessageAttributes {
32
32
  from_platform?: string;
33
33
  channel?: string;
34
34
  msg?: string;
35
+ replyToMsgId?: string;
35
36
  }
36
37
  interface chatConfigureContextInterface {
37
38
  open: boolean;
@@ -49,6 +50,8 @@ interface chatConfigureContextInterface {
49
50
  ) => void;
50
51
  addReaction: (msgId: string, reaction: string) => void;
51
52
  removeReaction: (msgId: string, reaction: string) => void;
53
+ pinMessage: (messageId: string) => void;
54
+ unPinMessage: (messageId: string) => void;
52
55
  }
53
56
 
54
57
  export const chatConfigureContext =
@@ -61,6 +64,8 @@ export const chatConfigureContext =
61
64
  deleteAttachment: () => {},
62
65
  addReaction: () => {},
63
66
  removeReaction: () => {},
67
+ pinMessage: () => {},
68
+ unPinMessage: () => {},
64
69
  });
65
70
 
66
71
  const ChatConfigure = ({children}) => {
@@ -84,6 +89,7 @@ const ChatConfigure = ({children}) => {
84
89
  addReactionToPrivateStore,
85
90
  addReactionToStore,
86
91
  } = useChatMessages();
92
+ const {setPinMsgId, setPinnedByUser} = useChatUIControls();
87
93
 
88
94
  React.useEffect(() => {
89
95
  defaultContentRef.current = defaultContent;
@@ -131,8 +137,15 @@ const ChatConfigure = ({children}) => {
131
137
  const {msgId, from, body, localTime} = message;
132
138
  const chatType = body.type;
133
139
  const fromUser = from;
134
- const {file_ext, file_name, file_url, from_platform, channel, msg} =
135
- message.attributes as ChatMessageAttributes;
140
+ const {
141
+ file_ext,
142
+ file_name,
143
+ file_url,
144
+ from_platform,
145
+ channel,
146
+ msg,
147
+ replyToMsgId,
148
+ } = message.attributes as ChatMessageAttributes;
136
149
 
137
150
  // prevent cross-channel messages
138
151
  if (channel !== data.channel) {
@@ -151,6 +164,7 @@ const ChatConfigure = ({children}) => {
151
164
  msgId: msgId,
152
165
  isDeleted: false,
153
166
  type: ChatMessageType.TXT,
167
+ replyToMsgId,
154
168
  });
155
169
  }
156
170
  if (isPeerChat) {
@@ -163,6 +177,7 @@ const ChatConfigure = ({children}) => {
163
177
  msgId: msgId,
164
178
  isDeleted: false,
165
179
  type: ChatMessageType.TXT,
180
+ replyToMsgId,
166
181
  },
167
182
  false,
168
183
  );
@@ -197,6 +212,7 @@ const ChatConfigure = ({children}) => {
197
212
  thumb: thumb,
198
213
  url: url,
199
214
  fileName: file_name,
215
+ replyToMsgId,
200
216
  });
201
217
  }
202
218
  if (isPeerChat) {
@@ -217,6 +233,7 @@ const ChatConfigure = ({children}) => {
217
233
  thumb: thumb,
218
234
  url: url,
219
235
  fileName: file_name,
236
+ replyToMsgId,
220
237
  },
221
238
  false,
222
239
  );
@@ -242,6 +259,7 @@ const ChatConfigure = ({children}) => {
242
259
  url: file_url,
243
260
  ext: file_ext,
244
261
  fileName: file_name,
262
+ replyToMsgId,
245
263
  });
246
264
  }
247
265
  if (isPeerChat) {
@@ -262,6 +280,7 @@ const ChatConfigure = ({children}) => {
262
280
  url: file_url,
263
281
  ext: file_ext,
264
282
  fileName: file_name,
283
+ replyToMsgId,
265
284
  },
266
285
  false,
267
286
  );
@@ -285,6 +304,9 @@ const ChatConfigure = ({children}) => {
285
304
  );
286
305
  }
287
306
  },
307
+ // onMessagePinChanged: data => {
308
+ // console.warn('onMessagePinChanged', data);
309
+ // },
288
310
  };
289
311
  console.warn('setup listener');
290
312
  chatManager.removeAllMessageListener();
@@ -372,8 +394,11 @@ const ChatConfigure = ({children}) => {
372
394
  switch (type) {
373
395
  case ChatMessageType.TXT:
374
396
  chatMsg = ChatMessage.createTextMessage(to, msg, chatMsgChatType);
397
+ console.warn('createTextMessage', chatMsg);
375
398
  chatMsg.attributes = {
376
399
  channel: data.channel,
400
+ replyToMsgId: option?.ext?.replyToMsgId,
401
+ from_platform: 'native',
377
402
  };
378
403
  break;
379
404
  case ChatMessageType.IMAGE:
@@ -385,6 +410,7 @@ const ChatConfigure = ({children}) => {
385
410
  file_url: option?.ext?.file_url, // this local url , when upload util is available for native then will use it
386
411
  from_platform: 'native',
387
412
  channel: data.channel,
413
+ replyToMsgId: option?.ext?.replyToMsgId,
388
414
  };
389
415
 
390
416
  console.warn('Image msg to be sent', chatMsg);
@@ -401,37 +427,20 @@ const ChatConfigure = ({children}) => {
401
427
  file_url: option?.url, // this local url , when upload util is available for native then will use it
402
428
  from_platform: 'native',
403
429
  channel: data.channel,
430
+ replyToMsgId: option?.ext?.replyToMsgId,
404
431
  };
405
432
  console.warn('File msg to be sent', chatMsg);
406
433
  break;
407
434
  }
408
- //
435
+
409
436
  chatClient.chatManager
410
437
  .sendMessage(chatMsg, callback)
411
438
  .then(() => {
412
- // log here if the method call succeeds.
413
- console.warn('send message success');
414
- // add to local store of sender
415
439
  // for image and file msgs we will update on upload success of chatAttachment.native
416
- if (type === ChatMessageType.TXT) {
417
- const messageData = {
418
- msg: option.msg.replace(/^(\n)+|(\n)+$/g, ''),
419
- createdTimestamp: timeNow(),
420
- msgId: chatMsg.msgId,
421
- isDeleted: false,
422
- type: option.type,
423
- };
424
-
425
- // this is local user messages
426
- if (option.chatType === SDKChatType.SINGLE_CHAT) {
427
- addMessageToPrivateStore(Number(option.to), messageData, true);
428
- } else {
429
- addMessageToStore(Number(option.from), messageData);
430
- }
431
- }
440
+ // for text msgs ChatInput.native
441
+ console.warn('send message successfull ');
432
442
  })
433
443
  .catch(reason => {
434
- //log here if the method call fails.
435
444
  console.warn('send message fail.', reason);
436
445
  });
437
446
  };
@@ -525,7 +534,8 @@ const ChatConfigure = ({children}) => {
525
534
  );
526
535
  })
527
536
  .catch(err => {
528
- if (err.type === 1101) {
537
+ console.warn(err);
538
+ if (err.code === 1301) {
529
539
  // If user already added reaction then remove it
530
540
  removeReaction(msgId, reaction);
531
541
  } else {
@@ -559,6 +569,54 @@ const ChatConfigure = ({children}) => {
559
569
  });
560
570
  };
561
571
 
572
+ const pinMessage = (messageId: string) => {
573
+ return;
574
+ // available in 1.3.0 chat sdk
575
+ // chatClient.chatManager
576
+ // .pinMessage(messageId)
577
+ // .then(res => {
578
+ // setPinMsgId(messageId);
579
+ // setPinnedByUser(Number(localUid));
580
+ // logger.debug(
581
+ // LogSource.Internals,
582
+ // 'CHAT',
583
+ // `Successfully Pinned message with id ${messageId}`,
584
+ // res,
585
+ // );
586
+ // })
587
+ // .catch(err => {
588
+ // logger.debug(
589
+ // LogSource.Internals,
590
+ // 'CHAT',
591
+ // `Failed to Pin Message with id ${messageId}`,
592
+ // err,
593
+ // );
594
+ // });
595
+ };
596
+
597
+ const unPinMessage = (messageId: string) => {
598
+ return; // available in 1.3.0 chat sdk
599
+ // chatClient.chatManager
600
+ // .unpinMessage(messageId)
601
+ // .then(res => {
602
+ // setPinMsgId('');
603
+ // logger.debug(
604
+ // LogSource.Internals,
605
+ // 'CHAT',
606
+ // `Successfully Pinned message with id ${messageId}`,
607
+ // res,
608
+ // );
609
+ // })
610
+ // .catch(err => {
611
+ // logger.debug(
612
+ // LogSource.Internals,
613
+ // 'CHAT',
614
+ // `Failed to Pin Message with id ${messageId}`,
615
+ // err,
616
+ // );
617
+ // });
618
+ };
619
+
562
620
  return (
563
621
  <chatConfigureContext.Provider
564
622
  value={{
@@ -570,6 +628,8 @@ const ChatConfigure = ({children}) => {
570
628
  deleteAttachment,
571
629
  addReaction,
572
630
  removeReaction,
631
+ pinMessage,
632
+ unPinMessage,
573
633
  }}>
574
634
  {children}
575
635
  </chatConfigureContext.Provider>