agora-appbuilder-core 4.1.3 → 4.1.4-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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "4.1.3",
3
+ "version": "4.1.4-beta.1",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -55,3 +55,4 @@ export {useActionSheet} from '../src/utils/useActionSheet';
55
55
  export {default as PlatformWrapper} from '../src/utils/PlatformWrapper';
56
56
  export {useSpotlight} from '../src/utils/useSpotlight';
57
57
  export {useActiveUids} from '../src/utils/useActiveUids';
58
+ export {default as useUserBan} from '../src/utils/useUserBan';
@@ -76,8 +76,8 @@ const DefaultConfig = {
76
76
  CHAT_ORG_NAME: '',
77
77
  CHAT_APP_NAME: '',
78
78
  CHAT_URL: '',
79
- CLI_VERSION: '3.1.3',
80
- CORE_VERSION: '4.1.3',
79
+ CLI_VERSION: '3.1.4-beta.1',
80
+ CORE_VERSION: '4.1.4-beta.1',
81
81
  DISABLE_LANDSCAPE_MODE: false,
82
82
  STT_AUTO_START: false,
83
83
  CLOUD_RECORDING_AUTO_START: false,
@@ -24,6 +24,7 @@ export interface AppBuilderSdkApiInterface {
24
24
  preference?: {
25
25
  disableShareTile: boolean;
26
26
  disableVideoProcessors: boolean;
27
+ userRemovalTimeout: number;
27
28
  },
28
29
  ) => Promise<meetingData>;
29
30
  joinPrecall: (
@@ -33,6 +34,7 @@ export interface AppBuilderSdkApiInterface {
33
34
  preference?: {
34
35
  disableShareTile: boolean;
35
36
  disableVideoProcessors: boolean;
37
+ userRemovalTimeout: number;
36
38
  },
37
39
  ) => Promise<
38
40
  [
@@ -244,6 +244,7 @@ const EventsConfigure: React.FC<Props> = ({
244
244
  }, [defaultContent]);
245
245
  const {
246
246
  data: {isHost, roomId},
247
+ roomPreference: {userRemovalTimeout},
247
248
  } = useRoomInfo();
248
249
  const {setRoomInfo} = useSetRoomInfo();
249
250
  const isHostRef = React.useRef(isHost);
@@ -402,9 +403,13 @@ const EventsConfigure: React.FC<Props> = ({
402
403
  primaryBtn: null,
403
404
  secondaryBtn: null,
404
405
  });
405
- setTimeout(() => {
406
+ if (userRemovalTimeout > 0) {
407
+ setTimeout(() => {
408
+ executeEndCall();
409
+ }, userRemovalTimeout);
410
+ } else {
406
411
  executeEndCall();
407
- }, 5000);
412
+ }
408
413
  });
409
414
 
410
415
  events.on(controlMessageEnum.requestAudio, () => {
@@ -30,6 +30,7 @@ type SdkApiContextInterface = {
30
30
  preference: {
31
31
  disableShareTile: boolean;
32
32
  disableVideoProcessors: boolean;
33
+ userRemovalTimeout: number;
33
34
  };
34
35
  promise: extractPromises<_InternalSDKMethodEventsMap['join']>;
35
36
  }
@@ -100,6 +100,7 @@ export default function UserActionMenuOptionsOptions(
100
100
  const {hostUids, audienceUids} = useLiveStreamDataContext();
101
101
  const {
102
102
  data: {isHost},
103
+ roomPreference: {userRemovalTimeout},
103
104
  } = useRoomInfo();
104
105
  const remoteRequest = useRemoteRequest();
105
106
  const remoteMute = useRemoteMute();
@@ -516,15 +517,19 @@ export default function UserActionMenuOptionsOptions(
516
517
  setModalVisible={setRemoveMeetingPopupVisible}
517
518
  username={user.name}
518
519
  removeUserFromMeeting={() => {
519
- Toast.show({
520
- leadingIconName: 'info',
521
- type: 'info',
522
- text1: toastlabel(trimText(user.name)),
523
- visibilityTime: 5000,
524
- primaryBtn: null,
525
- secondaryBtn: null,
526
- leadingIcon: null,
527
- });
520
+ userRemovalTimeout > 0 &&
521
+ Toast.show({
522
+ leadingIconName: 'info',
523
+ type: 'info',
524
+ text1: toastlabel(
525
+ trimText(user.name),
526
+ userRemovalTimeout / 1000,
527
+ ),
528
+ visibilityTime: 5000,
529
+ primaryBtn: null,
530
+ secondaryBtn: null,
531
+ leadingIcon: null,
532
+ });
528
533
  endRemoteCall(user.uid);
529
534
  }}
530
535
  />
@@ -154,6 +154,7 @@ export const RoomInfoDefaultValue: RoomInfoContextInterface = {
154
154
  roomPreference: {
155
155
  disableShareTile: false,
156
156
  disableVideoProcessors: false,
157
+ userRemovalTimeout: 5000,
157
158
  },
158
159
  };
159
160
 
@@ -1189,8 +1189,8 @@ export const VideoCallScreenLabels: I18nVideoCallScreenLabelsInterface = {
1189
1189
  [peoplePanelMeText]: 'Me',
1190
1190
  [peoplePanelPresenterText]: 'Presenter',
1191
1191
 
1192
- [userRemovedFromTheRoomToastHeading]: name =>
1193
- `The system will remove ${name} from this call after 5 secs.`,
1192
+ [userRemovedFromTheRoomToastHeading]: (name, time) =>
1193
+ `The system will remove ${name} from this call after ${time} secs.`,
1194
1194
 
1195
1195
  [vbPanelImageUploadErrorToastHeading]: 'Upload Failed',
1196
1196
  [vbPanelImageUploadErrorToastSubHeading]:
@@ -103,7 +103,8 @@ type LogType = {
103
103
  | 'recording_start'
104
104
  | 'recording_stop'
105
105
  | 'recordings_get'
106
- | 'recording_delete';
106
+ | 'recording_delete'
107
+ | 'ban_user';
107
108
  [LogSource.Events]: 'CUSTOM_EVENTS' | 'RTM_EVENTS';
108
109
  [LogSource.CustomizationAPI]:
109
110
  | 'Log'
@@ -49,6 +49,7 @@ export interface userEventsMapInterface {
49
49
  'will-token-expire': () => void;
50
50
  'did-token-expire': () => void;
51
51
  'token-refreshed': () => void;
52
+ 'rtc-user-removed': (uid: UidType, channel: string) => void;
52
53
  }
53
54
 
54
55
  const SDKEvents = createNanoEvents<userEventsMapInterface>();
@@ -14,6 +14,7 @@ export interface SdkMethodEvents {
14
14
  preference?: {
15
15
  disableShareTile: boolean;
16
16
  disableVideoProcessors: boolean;
17
+ userRemovalTimeout: number;
17
18
  },
18
19
  ): RoomInfoContextInterface['data'];
19
20
  microphoneDevice: (deviceId: deviceId) => void;
@@ -148,6 +148,7 @@ const JOIN_CHANNEL_PHRASE = gql`
148
148
  export interface joinRoomPreference {
149
149
  disableShareTile: boolean;
150
150
  disableVideoProcessors: boolean;
151
+ userRemovalTimeout: number;
151
152
  }
152
153
 
153
154
  export default function useJoinRoom() {
@@ -3,13 +3,14 @@ import {useRoomInfo} from '../components/room-info/useRoomInfo';
3
3
  import useIsPSTN from './useIsPSTN';
4
4
  import {UidType} from '../../agora-rn-uikit';
5
5
  import events, {PersistanceLevel} from '../rtm-events-api';
6
+ import SDKEvents from './SdkEvents';
6
7
 
7
8
  /**
8
9
  * Returns a function to end the call for a remote user with the given uid.
9
10
  */
10
11
  const useRemoteEndCall = () => {
11
12
  const {
12
- data: {isHost},
13
+ data: {isHost, channel},
13
14
  } = useRoomInfo();
14
15
  const isPSTN = useIsPSTN();
15
16
 
@@ -22,6 +23,8 @@ const useRemoteEndCall = () => {
22
23
  PersistanceLevel.None,
23
24
  uid,
24
25
  );
26
+ // Also Send the SDK event for wrapper app to add extra functinalities like banning user;
27
+ SDKEvents.emit('rtc-user-removed', uid, channel);
25
28
  }
26
29
  } else {
27
30
  console.error('A host can only remove the audience from the call.');
@@ -0,0 +1,113 @@
1
+ /*
2
+ ********************************************
3
+ Copyright © 2021 Agora Lab, Inc., all rights reserved.
4
+ AppBuilder and all associated components, source code, APIs, services, and documentation
5
+ (the “Materials”) are owned by Agora Lab, Inc. and its licensors. The Materials may not be
6
+ accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
7
+ Use without a license or in violation of any license terms and conditions (including use for
8
+ any purpose competitive to Agora Lab, Inc.’s business) is strictly prohibited. For more
9
+ information visit https://appbuilder.agora.io.
10
+ *********************************************
11
+ */
12
+ import React from 'react';
13
+ import {logger, LogSource} from '../logger/AppBuilderLogger';
14
+ import {UidType} from '../../agora-rn-uikit';
15
+ import getUniqueID from './getUniqueID';
16
+ import StorageContext from '../components/StorageContext';
17
+ import {useRoomInfo} from 'customization-api';
18
+
19
+ type BanUserPrivilegesResponse = {
20
+ success: boolean;
21
+ message: string;
22
+ data?: any;
23
+ };
24
+
25
+ /**
26
+ * Bans specific user privileges in the channel.
27
+ * @param hostMeetingId - host meeting id.
28
+ * @param channel - channel from which to ban the user.
29
+ * @param uid - user id to ban.
30
+ * @param duration - how long to ban user in minutes - min 1 max 1440
31
+ * @param privileges - list of privileges to ban. default is ['join_channel', 'publish_audio', 'publish_video']
32
+ */
33
+
34
+ function useUserBan() {
35
+ const {store} = React.useContext(StorageContext);
36
+ const {
37
+ data: {roomId},
38
+ } = useRoomInfo();
39
+ const BAN_API_URL = `${$config.BACKEND_ENDPOINT}/v1/channel/user/ban`;
40
+
41
+ // duration - how long to ban user in minutes - min 1 max 1440
42
+ const banUserPrivileges = async (
43
+ hostMeetingID: string,
44
+ channel: string,
45
+ uid: UidType,
46
+ duration: number,
47
+ privileges: string[] = ['join_channel', 'publish_audio', 'publish_video'],
48
+ ): Promise<BanUserPrivilegesResponse> => {
49
+ if (!uid || !duration || duration < 1 || duration > 1440) {
50
+ logger.error(
51
+ LogSource.NetworkRest,
52
+ 'ban_user',
53
+ `Invalid parameters: uid=${uid}, duration=${duration}`,
54
+ );
55
+ return {success: false, message: 'Invalid user ID or duration'};
56
+ }
57
+
58
+ const requestId = getUniqueID();
59
+ logger.log(
60
+ LogSource.NetworkRest,
61
+ 'ban_user',
62
+ `Trying to ban user with id ${uid} in channel : ${channel}`,
63
+ );
64
+
65
+ const payload = {
66
+ passphrase: hostMeetingID || roomId?.host,
67
+ uid: uid,
68
+ channel_name: channel,
69
+ duration: duration,
70
+ privileges: privileges,
71
+ };
72
+
73
+ try {
74
+ const response = await fetch(BAN_API_URL, {
75
+ method: 'POST',
76
+ headers: {
77
+ 'Content-Type': 'application/json',
78
+ authorization: store?.token ? `Bearer ${store.token}` : '',
79
+ 'X-Request-Id': requestId,
80
+ 'X-Session-Id': logger.getSessionId(),
81
+ },
82
+ body: JSON.stringify(payload),
83
+ });
84
+
85
+ if (!response.ok && response.status != 200) {
86
+ const errorText = await response.text();
87
+ logger.error(
88
+ LogSource.NetworkRest,
89
+ 'ban_user',
90
+ `Failed to ban user with id ${uid}`,
91
+ errorText,
92
+ );
93
+ return {success: false, message: errorText};
94
+ }
95
+ return {
96
+ success: true,
97
+ message: 'User privileges banned successfully',
98
+ };
99
+ } catch (error) {
100
+ logger.error(
101
+ LogSource.NetworkRest,
102
+ 'ban_user',
103
+ `Error while trying to ban user with id ${uid}`,
104
+ error,
105
+ );
106
+ return {success: false, message: 'Error while banning the user'};
107
+ }
108
+ };
109
+
110
+ return banUserPrivileges;
111
+ }
112
+
113
+ export default useUserBan;