agora-appbuilder-core 4.0.0-api.7 → 4.0.0-api.9

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 (97) hide show
  1. package/package.json +3 -3
  2. package/template/_package-lock.json +5911 -4861
  3. package/template/agora-rn-uikit/.eslintrc.js +5 -0
  4. package/template/agora-rn-uikit/package.json +14 -14
  5. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +41 -22
  6. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +2 -2
  7. package/template/agora-rn-uikit/src/Rtc/Create.tsx +90 -57
  8. package/template/agora-rn-uikit/src/Rtc/Join.tsx +20 -16
  9. package/template/agora-rn-uikit/src/RtcConfigure.tsx +10 -10
  10. package/template/agora-rn-uikit/src/Utils/isBotUser.ts +15 -0
  11. package/template/agora-rn-uikit/src/Utils/quality.tsx +8 -0
  12. package/template/agora-rn-uikit/src/Views/MaxVideoView.native.tsx +32 -16
  13. package/template/agora-rn-uikit/src/Views/MaxVideoView.tsx +25 -14
  14. package/template/agora-rn-uikit/src/Views/MinVideoView.tsx +15 -9
  15. package/template/agora-rn-uikit/src/index.ts +1 -1
  16. package/template/bridge/rtc/webNg/RtcEngine.ts +73 -58
  17. package/template/bridge/rtc/webNg/{SurfaceView.tsx → RtcSurfaceView.tsx} +20 -26
  18. package/template/bridge/rtc/webNg/Types.ts +20 -5
  19. package/template/bridge/rtc/webNg/index.ts +9 -13
  20. package/template/customization-api/temp.ts +2 -2
  21. package/template/customization-api/typeDefinition.ts +1 -2
  22. package/template/customization-api/utils.ts +1 -2
  23. package/template/index.js +1 -0
  24. package/template/ios/HelloWorld/HelloWorldDebug.entitlements +10 -0
  25. package/template/ios/HelloWorld.xcodeproj/project.pbxproj +4 -0
  26. package/template/ios/Podfile +1 -1
  27. package/template/ios/Podfile.lock +72 -140
  28. package/template/package.json +5 -4
  29. package/template/src/App.tsx +58 -1
  30. package/template/src/AppRoutes.tsx +16 -3
  31. package/template/src/AppWrapper.tsx +21 -19
  32. package/template/src/components/Chat.tsx +17 -8
  33. package/template/src/components/ChatContext.ts +0 -2
  34. package/template/src/components/Controls.tsx +5 -5
  35. package/template/src/components/Controls1.native.tsx +7 -3
  36. package/template/src/components/DeviceConfigure.native.tsx +2 -2
  37. package/template/src/components/DeviceConfigure.tsx +2 -2
  38. package/template/src/components/EventsConfigure.tsx +13 -22
  39. package/template/src/components/GraphQLProvider.tsx +47 -30
  40. package/template/src/components/GridVideo.tsx +6 -2
  41. package/template/src/components/NetworkQualityContext.tsx +11 -5
  42. package/template/src/components/ParticipantsView.tsx +3 -3
  43. package/template/src/components/PinnedVideo.tsx +2 -2
  44. package/template/src/components/Precall.native.tsx +9 -6
  45. package/template/src/components/Precall.tsx +9 -6
  46. package/template/src/components/StorageContext.tsx +5 -2
  47. package/template/src/components/ToastComponent.tsx +7 -1
  48. package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
  49. package/template/src/components/livestream/LiveStreamContext.tsx +42 -33
  50. package/template/src/components/livestream/Types.ts +2 -2
  51. package/template/src/components/participants/Participant.tsx +1 -1
  52. package/template/src/components/participants/UserActionMenuOptions.tsx +7 -2
  53. package/template/src/components/recording-bot/RecordingBotRoute.tsx +42 -0
  54. package/template/src/components/virtual-background/useVB.native.tsx +16 -19
  55. package/template/src/components/virtual-background/useVB.tsx +1 -1
  56. package/template/src/components/whiteboard/WhiteboardConfigure.native.tsx +11 -0
  57. package/template/src/components/whiteboard/WhiteboardConfigure.tsx +5 -0
  58. package/template/src/components/whiteboard/WhiteboardView.native.tsx +91 -12
  59. package/template/src/components/whiteboard/WhiteboardWidget.tsx +15 -4
  60. package/template/src/language/default-labels/precallScreenLabels.ts +5 -3
  61. package/template/src/language/default-labels/videoCallScreenLabels.ts +93 -41
  62. package/template/src/pages/VideoCall.tsx +39 -37
  63. package/template/src/pages/video-call/ActionSheetContent.tsx +4 -3
  64. package/template/src/pages/video-call/NameWithMicIcon.tsx +2 -1
  65. package/template/src/pages/video-call/VideoCallMobileView.tsx +26 -2
  66. package/template/src/pages/video-call/VideoCallScreen.tsx +32 -12
  67. package/template/src/pages/video-call/VideoCallScreenWrapper.tsx +41 -0
  68. package/template/src/pages/video-call/VideoComponent.tsx +5 -2
  69. package/template/src/pages/video-call/VideoRenderer.tsx +55 -34
  70. package/template/src/rtm-events/constants.ts +0 -2
  71. package/template/src/subComponents/ChatBubble.tsx +2 -0
  72. package/template/src/subComponents/LocalAudioMute.tsx +8 -47
  73. package/template/src/subComponents/LocalEndCall.tsx +5 -52
  74. package/template/src/subComponents/LocalSwitchCamera.tsx +3 -3
  75. package/template/src/subComponents/LocalVideoMute.tsx +8 -50
  76. package/template/src/subComponents/SelectDevice.tsx +5 -2
  77. package/template/src/subComponents/SelectDeviceSettings.backup.tsx +9 -6
  78. package/template/src/subComponents/caption/Caption.tsx +12 -10
  79. package/template/src/subComponents/caption/Transcript.tsx +13 -10
  80. package/template/src/subComponents/caption/useTranscriptDownload.native.ts +11 -16
  81. package/template/src/subComponents/caption/utils.ts +1 -0
  82. package/template/src/subComponents/livestream/ApprovedLiveStreamControlsView.tsx +2 -2
  83. package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +3 -2
  84. package/template/src/subComponents/livestream/controls/LocalRaiseHand.tsx +1 -1
  85. package/template/src/subComponents/recording/useIsRecordingBot.tsx +38 -0
  86. package/template/src/subComponents/recording/useRecording.tsx +176 -135
  87. package/template/src/subComponents/screenshare/ScreenshareButton.tsx +3 -3
  88. package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +1 -22
  89. package/template/src/utils/index.tsx +16 -5
  90. package/template/src/utils/useEndCall.ts +65 -0
  91. package/template/src/utils/useIsLocalUserSpeaking.ts +6 -1
  92. package/template/{bridge/rtc/webNg/LocalView.tsx → src/utils/useLocalAudio.ts} +24 -6
  93. package/template/src/utils/useMuteToggleLocal.ts +10 -5
  94. package/template/src/utils/useSearchParams.tsx +18 -0
  95. package/template/src/wasms/agora-virtual-background.wasm +0 -0
  96. package/template/src/utils/endCallEveryOne.ts +0 -7
  97. package/template/src/utils/useDisableButton.tsx +0 -37
@@ -16,26 +16,43 @@ import React, {
16
16
  useEffect,
17
17
  useRef,
18
18
  useState,
19
+ useCallback,
19
20
  } from 'react';
20
- import {gql, useMutation} from '@apollo/client';
21
- import {useParams} from '../../components/Router';
22
- import {PropsContext} from '../../../agora-rn-uikit';
23
21
  import Toast from '../../../react-native-toast-message';
24
22
  import {createHook} from 'customization-implementation';
25
23
  import {useString} from '../../utils/useString';
26
24
  import ChatContext from '../../components/ChatContext';
27
25
  import events, {PersistanceLevel} from '../../rtm-events-api';
28
26
  import {EventActions, EventNames} from '../../rtm-events';
29
- import useRecordingLayoutQuery from './useRecordingLayoutQuery';
30
- import {useScreenContext} from '../../components/contexts/ScreenShareContext';
31
27
  import {useContent} from 'customization-api';
32
28
  import {trimText} from '../../utils/common';
33
29
  import {useRoomInfo} from 'customization-api';
30
+ import StorageContext from '../../components/StorageContext';
31
+ import {useSidePanel} from '../../utils/useSidePanel';
32
+ import {useCaption} from '../caption/useCaption';
33
+ import {SidePanelType} from '../SidePanelEnum';
34
+ import {
35
+ ChatType,
36
+ useChatUIControls,
37
+ } from '../../components/chat-ui/useChatUIControls';
38
+ import {useIsRecordingBot} from './useIsRecordingBot';
34
39
  import {
35
40
  videoRoomRecordingToastHeading,
36
41
  videoRoomRecordingToastSubHeading,
37
42
  videoRoomUserFallbackText,
43
+ videoRoomRecordingStartErrorToastHeading,
44
+ videoRoomRecordingStopErrorToastHeading,
45
+ videoRoomRecordingErrorToastSubHeading,
38
46
  } from '../../language/default-labels/videoCallScreenLabels';
47
+ import {getOriginURL} from '../../auth/config';
48
+
49
+ const getFrontendUrl = (url: string) => {
50
+ // check if it doesn't contains the https protocol
51
+ if (url.indexOf('https://') !== 0) {
52
+ url = `https://${url}`;
53
+ }
54
+ return url;
55
+ };
39
56
 
40
57
  export interface RecordingContextInterface {
41
58
  startRecording: () => void;
@@ -51,26 +68,6 @@ const RecordingContext = createContext<RecordingContextInterface>({
51
68
  inProgress: false,
52
69
  });
53
70
 
54
- const START_RECORDING = gql`
55
- mutation startRecordingSession(
56
- $passphrase: String!
57
- $secret: String
58
- $config: recordingConfig!
59
- ) {
60
- startRecordingSession(
61
- passphrase: $passphrase
62
- secret: $secret
63
- config: $config
64
- )
65
- }
66
- `;
67
-
68
- const STOP_RECORDING = gql`
69
- mutation stopRecordingSession($passphrase: String!) {
70
- stopRecordingSession(passphrase: $passphrase)
71
- }
72
- `;
73
-
74
71
  /**
75
72
  * Component to start / stop Agora cloud recording.
76
73
  * Sends a control message to all users in the channel over RTM to indicate that
@@ -100,17 +97,13 @@ interface RecordingProviderProps {
100
97
  */
101
98
 
102
99
  const RecordingProvider = (props: RecordingProviderProps) => {
103
- const {rtcProps} = useContext(PropsContext);
104
100
  const {setRecordingActive, isRecordingActive, callActive} = props?.value;
105
101
  const {
106
- data: {isHost},
102
+ data: {isHost, roomId},
107
103
  } = useRoomInfo();
108
104
  const [inProgress, setInProgress] = useState(false);
109
105
  const [uidWhoStarted, setUidWhoStarted] = useState(0);
110
106
  const {defaultContent, activeUids} = useContent();
111
- const {phrase} = useParams<{phrase: string}>();
112
- const [startRecordingQuery] = useMutation(START_RECORDING);
113
- const [stopRecordingQuery] = useMutation(STOP_RECORDING);
114
107
  const prevRecordingState = usePrevious<{isRecordingActive: boolean}>({
115
108
  isRecordingActive,
116
109
  });
@@ -118,36 +111,41 @@ const RecordingProvider = (props: RecordingProviderProps) => {
118
111
  videoRoomRecordingToastHeading,
119
112
  );
120
113
  const subheading = useString(videoRoomRecordingToastSubHeading);
114
+
115
+ const headingStartError = useString(
116
+ videoRoomRecordingStartErrorToastHeading,
117
+ )();
118
+ const headingStopError = useString(videoRoomRecordingStopErrorToastHeading)();
119
+ const subheadingError = useString(videoRoomRecordingErrorToastSubHeading)();
120
+
121
121
  const userlabel = useString(videoRoomUserFallbackText)();
122
122
 
123
- const {executePresenterQuery, executeNormalQuery} = useRecordingLayoutQuery();
124
123
  const {localUid} = useContext(ChatContext);
125
- const {screenShareData} = useScreenContext();
124
+ const {store} = React.useContext(StorageContext);
126
125
 
127
- React.useEffect(() => {
128
- events.on(EventNames.RECORDING_ATTRIBUTE, data => {
129
- const payload = JSON.parse(data.payload);
130
- const action = payload.action;
131
- const value = payload.value;
132
- switch (action) {
133
- case EventActions.RECORDING_STARTED:
134
- setUidWhoStarted(parseInt(value));
135
- setRecordingActive(true);
136
- break;
137
- case EventActions.RECORDING_STOPPED:
138
- setRecordingActive(false);
139
- break;
140
- case EventActions.RECORDING_STOP_REQUEST:
141
- stopRecording();
142
- break;
143
- default:
144
- break;
126
+ const {setChatType} = useChatUIControls();
127
+ const {setSidePanel} = useSidePanel();
128
+ const {setIsCaptionON} = useCaption();
129
+ const {isRecordingBot, recordingBotUIConfig} = useIsRecordingBot();
130
+
131
+ const setRecordingBotUI = () => {
132
+ if (isRecordingBot) {
133
+ if (recordingBotUIConfig?.chat && $config.CHAT) {
134
+ setSidePanel(SidePanelType.Chat);
135
+ setChatType(ChatType.Group);
145
136
  }
146
- });
147
- return () => {
148
- events.off(EventNames.RECORDING_ATTRIBUTE);
149
- };
150
- }, []);
137
+ if (recordingBotUIConfig.stt && $config.ENABLE_STT) {
138
+ setIsCaptionON(true);
139
+ }
140
+ }
141
+ };
142
+
143
+ useEffect(() => {
144
+ if (callActive) {
145
+ setRecordingBotUI();
146
+ }
147
+ // eslint-disable-next-line react-hooks/exhaustive-deps
148
+ }, [callActive]);
151
149
 
152
150
  useEffect(() => {
153
151
  /**
@@ -180,25 +178,54 @@ const RecordingProvider = (props: RecordingProviderProps) => {
180
178
  }
181
179
  }, [isRecordingActive, callActive, isHost]);
182
180
 
181
+ const showErrorToast = (text1: string, text2?: string) => {
182
+ Toast.show({
183
+ leadingIconName: 'alert',
184
+ type: 'error',
185
+ text1: text1,
186
+ text2: text2 ? text2 : '',
187
+ visibilityTime: 3000,
188
+ primaryBtn: null,
189
+ secondaryBtn: null,
190
+ leadingIcon: null,
191
+ });
192
+ };
193
+
183
194
  const startRecording = () => {
195
+ const passphrase = roomId.host || '';
196
+ let recordinghostURL = getOriginURL();
197
+ console.log('web-recording - start recording API called');
198
+
199
+ if (inProgress) {
200
+ console.error('web-recording - start recording API already in progress');
201
+ return;
202
+ }
203
+ if (recordinghostURL.includes('localhost')) {
204
+ console.error(
205
+ 'web-recording - Recording url cannot be localhost. It should be a valid deployed URL',
206
+ );
207
+ return;
208
+ }
209
+ recordinghostURL = getFrontendUrl(recordinghostURL);
210
+ console.log('web-recording - recordinghostURL: ', recordinghostURL);
211
+
184
212
  setInProgress(true);
185
- // If recording is not going on, start the recording by executing the graphql query
186
- startRecordingQuery({
187
- variables: {
188
- passphrase: phrase,
189
- secret:
190
- rtcProps.encryption && rtcProps.encryption.key
191
- ? rtcProps.encryption.key
192
- : '',
193
- config: {
194
- resolution: 'SD360p',
195
- trigger: 'AUTO',
196
- },
213
+ fetch(`${$config.BACKEND_ENDPOINT}/v1/recording/start`, {
214
+ method: 'POST',
215
+ headers: {
216
+ 'Content-Type': 'application/json',
217
+ authorization: store.token ? `Bearer ${store.token}` : '',
197
218
  },
219
+ body: JSON.stringify({
220
+ passphrase: roomId.host,
221
+ url: `${recordinghostURL}/${passphrase}`,
222
+ webpage_ready_timeout: 10,
223
+ encryption: $config.ENCRYPTION_ENABLED,
224
+ }),
198
225
  })
199
- .then(res => {
226
+ .then((res: any) => {
200
227
  setInProgress(false);
201
- if (res.data.startRecordingSession === 'success') {
228
+ if (res.status === 200) {
202
229
  /**
203
230
  * 1. Once the backend sucessfuly starts recording, send message
204
231
  * in the channel indicating that cloud recording is now active.
@@ -214,22 +241,10 @@ const RecordingProvider = (props: RecordingProviderProps) => {
214
241
  // 2. set the local recording state to true to update the UI
215
242
  setUidWhoStarted(localUid);
216
243
  setRecordingActive(true);
217
- // 3. set the presenter mode if screen share is active
218
- // 3.a Get the most recent screenshare uid
219
- const sorted = Object.entries(screenShareData)
220
- .filter(el => el[1]?.ts && el[1].ts > 0 && el[1]?.isActive)
221
- .sort((a, b) => b[1].ts - a[1].ts);
222
-
223
- const activeScreenshareUid = sorted.length > 0 ? sorted[0][0] : 0;
224
- if (activeScreenshareUid) {
225
- console.log(
226
- 'screenshare: Executing presenter query for screenuid',
227
- activeScreenshareUid,
228
- );
229
- executePresenterQuery(parseInt(activeScreenshareUid));
230
- } else {
231
- executeNormalQuery();
232
- }
244
+ } else if (res.status === 500) {
245
+ showErrorToast(headingStartError, subheadingError);
246
+ } else {
247
+ showErrorToast(headingStartError);
233
248
  }
234
249
  })
235
250
  .catch(err => {
@@ -238,60 +253,86 @@ const RecordingProvider = (props: RecordingProviderProps) => {
238
253
  });
239
254
  };
240
255
 
241
- const stopRecording = () => {
256
+ const stopRecording = useCallback(() => {
242
257
  /**
243
- * if condition added for below issue
244
- *
245
- * user 1 and user 2 in the call
246
- * user 1 start the recording
247
- * user 2 stops the recording
248
- * user 2 join the call getting stop recording notification which is not needed
249
- *
250
- * solution
251
- * case 1 - if recording is not started by the host then we will send level1 message to host who started the recording
252
- * case 2 - if person who started the recording no longer available in the call then will stop the recording
258
+ * Any host in the channel can stop recording.
253
259
  */
254
- if (
255
- localUid === uidWhoStarted ||
256
- activeUids.indexOf(uidWhoStarted) === -1
257
- ) {
258
- setInProgress(true);
259
- // If recording is already going on, stop the recording by executing the graphql query.
260
- stopRecordingQuery({variables: {passphrase: phrase}})
261
- .then(res => {
262
- setInProgress(false);
263
- if (res.data.stopRecordingSession === 'success') {
264
- /**
265
- * 1. Once the backend sucessfuly starts recording, send message
266
- * in the channel indicating that cloud recording is now inactive.
267
- */
268
- events.send(
269
- EventNames.RECORDING_ATTRIBUTE,
270
- JSON.stringify({
271
- action: EventActions.RECORDING_STOPPED,
272
- value: '',
273
- }),
274
- PersistanceLevel.Session,
275
- );
276
- // 2. set the local recording state to false to update the UI
277
- setRecordingActive(false);
278
- }
279
- })
280
- .catch(err => {
281
- setInProgress(false);
282
- console.log(err);
283
- });
284
- } else {
285
- events.send(
286
- EventNames.RECORDING_ATTRIBUTE,
287
- JSON.stringify({
288
- action: EventActions.RECORDING_STOP_REQUEST,
289
- value: '',
290
- }),
291
- PersistanceLevel.None,
260
+ console.log('web-recording - stop recording API called');
261
+ if (inProgress) {
262
+ console.error(
263
+ 'web-recording - stop recording already in progress. Aborting..',
292
264
  );
265
+ return;
293
266
  }
294
- };
267
+ setInProgress(true);
268
+ // If recording is already going on, stop the recording by executing the below query.
269
+ fetch(`${$config.BACKEND_ENDPOINT}/v1/recording/stop`, {
270
+ method: 'POST',
271
+ headers: {
272
+ 'Content-Type': 'application/json',
273
+ authorization: store.token ? `Bearer ${store.token}` : '',
274
+ },
275
+ body: JSON.stringify({
276
+ passphrase: roomId.host,
277
+ }),
278
+ })
279
+ .then(res => {
280
+ setInProgress(false);
281
+ if (res.status === 200) {
282
+ /**
283
+ * 1. Once the backend sucessfuly stops recording, send message
284
+ * in the channel indicating that cloud recording is now inactive.
285
+ */
286
+ events.send(
287
+ EventNames.RECORDING_ATTRIBUTE,
288
+ JSON.stringify({
289
+ action: EventActions.RECORDING_STOPPED,
290
+ value: '',
291
+ }),
292
+ PersistanceLevel.Session,
293
+ );
294
+ // 2. set the local recording state to false to update the UI
295
+ setRecordingActive(false);
296
+ } else if (res.status === 500) {
297
+ showErrorToast(headingStopError, subheadingError);
298
+ } else {
299
+ showErrorToast(headingStopError);
300
+ }
301
+ })
302
+ .catch(err => {
303
+ setInProgress(false);
304
+ console.log(err);
305
+ });
306
+ }, [
307
+ headingStopError,
308
+ inProgress,
309
+ roomId.host,
310
+ setRecordingActive,
311
+ store.token,
312
+ subheadingError,
313
+ ]);
314
+
315
+ React.useEffect(() => {
316
+ events.on(EventNames.RECORDING_ATTRIBUTE, data => {
317
+ const payload = JSON.parse(data.payload);
318
+ const action = payload.action;
319
+ const value = payload.value;
320
+ switch (action) {
321
+ case EventActions.RECORDING_STARTED:
322
+ setUidWhoStarted(parseInt(value));
323
+ setRecordingActive(true);
324
+ break;
325
+ case EventActions.RECORDING_STOPPED:
326
+ setRecordingActive(false);
327
+ break;
328
+ default:
329
+ break;
330
+ }
331
+ });
332
+ return () => {
333
+ events.off(EventNames.RECORDING_ATTRIBUTE);
334
+ };
335
+ }, [roomId.host, setRecordingActive]);
295
336
 
296
337
  return (
297
338
  <RecordingContext.Provider
@@ -16,7 +16,7 @@ import Styles from '../../components/styles';
16
16
  import {useString} from '../../utils/useString';
17
17
  import {useScreenshare} from './useScreenshare';
18
18
  import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
19
- import {PropsContext, ClientRole} from '../../../agora-rn-uikit';
19
+ import {PropsContext, ClientRoleType} from '../../../agora-rn-uikit';
20
20
  import {useLocalUserInfo, useRoomInfo} from 'customization-api';
21
21
  import useIsHandRaised from '../../utils/useIsHandRaised';
22
22
  import {isAndroid, isIOS} from '../../utils/common';
@@ -83,7 +83,7 @@ const ScreenshareButton = (props: ScreenshareButtonProps) => {
83
83
  };
84
84
  iconButtonProps.isOnActionSheet = isOnActionSheet;
85
85
  if (
86
- rtcProps.role == ClientRole.Audience &&
86
+ rtcProps.role == ClientRoleType.ClientRoleAudience &&
87
87
  $config.EVENT_MODE &&
88
88
  !$config.RAISE_HAND
89
89
  ) {
@@ -91,7 +91,7 @@ const ScreenshareButton = (props: ScreenshareButtonProps) => {
91
91
  }
92
92
 
93
93
  if (
94
- rtcProps.role == ClientRole.Audience &&
94
+ rtcProps.role == ClientRoleType.ClientRoleAudience &&
95
95
  $config.EVENT_MODE &&
96
96
  $config.RAISE_HAND &&
97
97
  !isHost
@@ -18,12 +18,10 @@ import {
18
18
  useChangeDefaultLayout,
19
19
  useSetPinnedLayout,
20
20
  } from '../../pages/video-call/DefaultLayouts';
21
- import {useRecording} from '../recording/useRecording';
22
21
  import {useScreenContext} from '../../components/contexts/ScreenShareContext';
23
22
  import events, {PersistanceLevel} from '../../rtm-events-api';
24
23
  import {EventActions, EventNames} from '../../rtm-events';
25
24
  import {IAgoraRTC} from 'agora-rtc-sdk-ng';
26
- import useRecordingLayoutQuery from '../recording/useRecordingLayoutQuery';
27
25
  import {timeNow} from '../../rtm/utils';
28
26
  import {
29
27
  controlMessageEnum,
@@ -50,8 +48,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
50
48
  const {defaultContent, activeUids, pinnedUid, secondaryPinnedUid} =
51
49
  useContent();
52
50
  const isPinned = useRef(0);
53
- const {isRecordingActive} = useRecording();
54
- const {executeNormalQuery, executePresenterQuery} = useRecordingLayoutQuery();
55
51
  const {setScreenShareData, screenShareData} = useScreenContext();
56
52
  const setPinnedLayout = useSetPinnedLayout();
57
53
  const changeLayout = useChangeDefaultLayout();
@@ -232,7 +228,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
232
228
  const ScreenshareStoppedCallback = () => {
233
229
  setScreenshareActive(false);
234
230
  console.log('STOPPED SHARING');
235
- executeNormalQuery();
236
231
  events.send(
237
232
  EventNames.SCREENSHARE_ATTRIBUTE,
238
233
  JSON.stringify({
@@ -268,22 +263,11 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
268
263
  useEffect(() => {
269
264
  // @ts-ignore
270
265
  rtc.RtcEngineUnsafe.addListener(
271
- 'ScreenshareStopped',
266
+ 'onScreenshareStopped',
272
267
  ScreenshareStoppedCallback,
273
268
  );
274
269
  }, []);
275
270
 
276
- const executeRecordingQuery = (isScreenActive: boolean) => {
277
- if (isScreenActive) {
278
- console.log('screenshare: Executing presenter query');
279
- // If screen share is not going on, start the screen share by executing the graphql query
280
- executePresenterQuery(screenShareUid);
281
- } else {
282
- // If recording is already going on, stop the recording by executing the graphql query.
283
- executeNormalQuery();
284
- }
285
- };
286
-
287
271
  const stopUserScreenShare = () => {
288
272
  if (!isScreenshareActive) {
289
273
  return;
@@ -298,10 +282,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
298
282
  };
299
283
 
300
284
  const userScreenshare = async (isActive: boolean) => {
301
- if (isRecordingActive) {
302
- executeRecordingQuery(isActive);
303
- }
304
- console.log('screenshare query executed');
305
285
  try {
306
286
  // @ts-ignore
307
287
  await rtc.RtcEngineUnsafe.startScreenshare(
@@ -341,7 +321,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
341
321
  }
342
322
  } catch (e) {
343
323
  console.error("can't start the screen share", e);
344
- executeNormalQuery();
345
324
  Toast.show({
346
325
  leadingIconName: 'alert',
347
326
  type: 'error',
@@ -1,3 +1,5 @@
1
+ import {isWebInternal} from './common';
2
+
1
3
  const Buffer = require('buffer/').Buffer;
2
4
  type Entry<T> = {
3
5
  [K in keyof T]: [K, T[K]];
@@ -90,10 +92,19 @@ export const base64ToUint8Array = (base64Str: string) => {
90
92
 
91
93
  decodedData = Buffer.from(base64Str, 'base64').toString('binary');
92
94
 
93
- const result = new Uint8Array(new ArrayBuffer(decodedData.length));
94
- for (let i = 0; i < decodedData.length; i += 1) {
95
- result[i] = decodedData.charCodeAt(i);
95
+ if (isWebInternal()) {
96
+ const result: Uint8Array = new Uint8Array(
97
+ new ArrayBuffer(decodedData.length),
98
+ );
99
+ for (let i = 0; i < decodedData.length; i += 1) {
100
+ result[i] = decodedData.charCodeAt(i);
101
+ }
102
+ return result;
103
+ } else {
104
+ const result: number[] = [];
105
+ for (let i = 0; i < decodedData.length; i++) {
106
+ result.push(decodedData.charCodeAt(i));
107
+ }
108
+ return result;
96
109
  }
97
-
98
- return result;
99
110
  };
@@ -0,0 +1,65 @@
1
+ import {useContext} from 'react';
2
+ import {useCustomization} from 'customization-implementation';
3
+ import {useCaption, useContent, useRoomInfo} from 'customization-api';
4
+ import {PropsContext, DispatchContext} from '../../agora-rn-uikit';
5
+ import {useHistory} from '../components/Router';
6
+ import {stopForegroundService} from '../subComponents/LocalEndCall';
7
+ import RTMEngine from '../rtm/RTMEngine';
8
+ import {ENABLE_AUTH} from '../auth/config';
9
+ import {useAuth} from '../auth/AuthProvider';
10
+
11
+ const useEndCall = () => {
12
+ const history = useHistory();
13
+ const {defaultContent} = useContent();
14
+ const {isSTTActive} = useCaption();
15
+ const {
16
+ data: {isHost},
17
+ } = useRoomInfo();
18
+ const {authLogin} = useAuth();
19
+
20
+ const {rtcProps} = useContext(PropsContext);
21
+ const {dispatch} = useContext(DispatchContext);
22
+
23
+ const beforeEndCall = useCustomization(
24
+ data =>
25
+ data?.lifecycle?.useBeforeEndCall && data?.lifecycle?.useBeforeEndCall(),
26
+ );
27
+ const afterEndCall = useCustomization(
28
+ data =>
29
+ data?.lifecycle?.useAfterEndCall && data?.lifecycle?.useAfterEndCall(),
30
+ );
31
+
32
+ return async () => {
33
+ try {
34
+ await beforeEndCall(isHost, history as unknown as History);
35
+ } catch (error) {
36
+ console.log('debugging error on beforeEndCall');
37
+ }
38
+
39
+ setTimeout(() => {
40
+ dispatch({
41
+ type: 'EndCall',
42
+ value: [],
43
+ });
44
+ });
45
+ // stopping foreground servie on end call
46
+ stopForegroundService();
47
+ // stopping STT on call end,if only last user is remaining in call
48
+ const usersInCall = Object.entries(defaultContent).filter(
49
+ item => item[1].type === 'rtc',
50
+ );
51
+ usersInCall.length === 1 && isSTTActive && stop();
52
+ RTMEngine.getInstance().engine.leaveChannel(rtcProps.channel);
53
+ if (!ENABLE_AUTH) {
54
+ // await authLogout();
55
+ await authLogin();
56
+ }
57
+ try {
58
+ await afterEndCall(isHost, history as unknown as History);
59
+ } catch (error) {
60
+ console.log('debugging error on afterEndCall');
61
+ }
62
+ };
63
+ };
64
+
65
+ export default useEndCall;
@@ -5,6 +5,7 @@ import {useAsyncEffect} from './useAsyncEffect';
5
5
  import LocalEventEmitter, {
6
6
  LocalEventsEnum,
7
7
  } from '../rtm-events-api/LocalEvents';
8
+ import {useIsRecordingBot} from '../subComponents/recording/useIsRecordingBot';
8
9
 
9
10
  const useIsLocalUserSpeaking = () => {
10
11
  const log: (arg1: string, ...args: any[]) => void = (arg1, ...args) => {
@@ -15,6 +16,7 @@ const useIsLocalUserSpeaking = () => {
15
16
  const speechRef = useRef(null);
16
17
  const audioRef = useRef(audio);
17
18
  const audioTrackRef = useRef(null);
19
+ const {isRecordingBot} = useIsRecordingBot();
18
20
 
19
21
  useEffect(() => {
20
22
  audioRef.current = audio;
@@ -40,6 +42,9 @@ const useIsLocalUserSpeaking = () => {
40
42
 
41
43
  useEffect(() => {
42
44
  LocalEventEmitter.on(LocalEventsEnum.MIC_CHANGED, () => {
45
+ if (isRecordingBot) {
46
+ return;
47
+ }
43
48
  listenForSpeaker();
44
49
  });
45
50
  }, []);
@@ -75,7 +80,7 @@ const useIsLocalUserSpeaking = () => {
75
80
  };
76
81
 
77
82
  useAsyncEffect(async () => {
78
- if ($config.ACTIVE_SPEAKER) {
83
+ if ($config.ACTIVE_SPEAKER && !isRecordingBot) {
79
84
  await listenForSpeaker();
80
85
  return () => {
81
86
  try {
@@ -9,12 +9,30 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import React from 'react';
13
- import SurfaceView, {RtcSurfaceViewProps, StyleProps} from './SurfaceView';
14
12
 
15
- interface LocalViewInterface extends RtcSurfaceViewProps, StyleProps {}
13
+ import {DispatchContext, RtcContext} from '../../agora-rn-uikit';
14
+ import {useContext} from 'react';
16
15
 
17
- export default function LocalView(props: LocalViewInterface) {
18
- // console.log('LocalView props: ', props);
19
- return <SurfaceView uid={0} {...props} />;
16
+ function useLocalAudio() {
17
+ const {dispatch} = useContext(DispatchContext);
18
+ const {RtcEngineUnsafe} = useContext(RtcContext);
19
+
20
+ const disableAudioButton = () => {
21
+ RtcEngineUnsafe.muteLocalAudioStream(true);
22
+ dispatch({
23
+ type: 'LocalMuteAudio',
24
+ value: [0, true],
25
+ });
26
+ };
27
+
28
+ const enableAudioButton = () => {
29
+ dispatch({
30
+ type: 'LocalMuteAudio',
31
+ value: [0, false],
32
+ });
33
+ };
34
+
35
+ return {enableAudioButton, disableAudioButton};
20
36
  }
37
+
38
+ export default useLocalAudio;