agora-appbuilder-core 2.0.1 → 2.0.3-rc2

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 (79) hide show
  1. package/Readme.md +2 -1
  2. package/package.json +1 -1
  3. package/template/_package-lock.json +8853 -8806
  4. package/template/agora-rn-uikit/.git/index +0 -0
  5. package/template/agora-rn-uikit/.git/logs/HEAD +2 -2
  6. package/template/agora-rn-uikit/.git/logs/refs/heads/ab-dev-auto +1 -1
  7. package/template/agora-rn-uikit/.git/logs/refs/heads/master +1 -1
  8. package/template/agora-rn-uikit/.git/logs/refs/remotes/origin/HEAD +1 -1
  9. package/template/agora-rn-uikit/.git/objects/pack/pack-2a0122bf5a3199f941e5a52535f43881623f752c.idx +0 -0
  10. package/template/agora-rn-uikit/.git/objects/pack/{pack-f379286d0537eb68377220b4929979324b8d5d1c.pack → pack-2a0122bf5a3199f941e5a52535f43881623f752c.pack} +0 -0
  11. package/template/agora-rn-uikit/.git/packed-refs +4 -2
  12. package/template/agora-rn-uikit/.git/refs/heads/ab-dev-auto +1 -1
  13. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +21 -0
  14. package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +22 -14
  15. package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +17 -13
  16. package/template/agora-rn-uikit/src/Controls/types.ts +4 -0
  17. package/template/agora-rn-uikit/src/Rtc/Create.tsx +117 -19
  18. package/template/agora-rn-uikit/src/RtcConfigure.tsx +24 -13
  19. package/template/{src/utils/isSafariBrowser.tsx → agora-rn-uikit/src/Utils/isSafariBrowser.ts} +3 -0
  20. package/template/{src → agora-rn-uikit/src}/hooks/useImageDelay.tsx +5 -2
  21. package/template/agora-rn-uikit/src/index.ts +2 -0
  22. package/template/bridge/rtc/webNg/RtcEngine.ts +73 -70
  23. package/template/bridge/rtc/webNg/Types.ts +59 -5
  24. package/template/bridge/rtm/web/Types.ts +13 -0
  25. package/template/bridge/rtm/web/index.ts +78 -1
  26. package/template/global.d.ts +2 -0
  27. package/template/package-lock.json +8853 -8806
  28. package/template/package.json +3 -4
  29. package/template/react-native-toast-message/src/components/base/styles.js +4 -2
  30. package/template/src/assets/icons.ts +41 -28
  31. package/template/src/components/Chat.tsx +70 -184
  32. package/template/src/components/ChatContext.ts +13 -2
  33. package/template/src/components/Controls.native.tsx +37 -76
  34. package/template/src/components/Controls.tsx +50 -158
  35. package/template/src/components/DeviceConfigure.native.tsx +5 -1
  36. package/template/src/components/DeviceConfigure.tsx +38 -20
  37. package/template/src/components/Navbar.tsx +185 -226
  38. package/template/src/components/ParticipantsView.tsx +176 -184
  39. package/template/src/components/Precall.native.tsx +83 -69
  40. package/template/src/components/Precall.tsx +174 -191
  41. package/template/src/components/RTMConfigure.tsx +264 -78
  42. package/template/src/components/SettingsView.tsx +9 -19
  43. package/template/src/components/livestream/LiveStreamContext.tsx +411 -0
  44. package/template/src/components/livestream/Types.ts +69 -0
  45. package/template/src/components/livestream/index.ts +9 -0
  46. package/template/src/components/livestream/views/LiveStreamControls.tsx +27 -0
  47. package/template/src/components/participants/AllAudienceParticipants.tsx +53 -0
  48. package/template/src/components/participants/AllHostParticipants.tsx +65 -0
  49. package/template/src/components/participants/MeParticipant.tsx +37 -0
  50. package/template/src/components/participants/ParticipantName.tsx +47 -0
  51. package/template/src/components/participants/ParticipantSectionTitle.tsx +29 -0
  52. package/template/src/components/participants/RemoteParticipants.tsx +69 -0
  53. package/template/src/components/participants/ScreenshareParticipants.tsx +28 -0
  54. package/template/src/components/participants/context/ParticipantContext.tsx +97 -0
  55. package/template/src/components/styles.ts +13 -0
  56. package/template/src/pages/Create.tsx +25 -14
  57. package/template/src/pages/VideoCall.tsx +197 -159
  58. package/template/src/subComponents/ChatBubble.tsx +4 -1
  59. package/template/src/subComponents/ChatContainer.tsx +44 -20
  60. package/template/src/subComponents/ChatInput.tsx +4 -12
  61. package/template/src/subComponents/Checkbox.native.tsx +6 -5
  62. package/template/src/subComponents/Checkbox.tsx +1 -0
  63. package/template/src/subComponents/Recording.tsx +23 -9
  64. package/template/src/subComponents/RemoteVideoMute.tsx +2 -3
  65. package/template/src/subComponents/SelectDevice.tsx +70 -35
  66. package/template/src/subComponents/chat/ChatParticipants.tsx +121 -0
  67. package/template/src/subComponents/livestream/ApprovedLiveStreamControlsView.tsx +23 -0
  68. package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +70 -0
  69. package/template/src/subComponents/livestream/controls/LocalRaiseHand.tsx +57 -0
  70. package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +24 -0
  71. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +38 -0
  72. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +37 -0
  73. package/template/src/subComponents/livestream/index.ts +18 -0
  74. package/template/src/subComponents/screenshare/ScreenshareButton.tsx +80 -0
  75. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +24 -0
  76. package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +200 -0
  77. package/template/src/subComponents/screenshare/ScreenshareContext.tsx +21 -0
  78. package/template/src/utils/index.tsx +48 -0
  79. package/template/agora-rn-uikit/.git/objects/pack/pack-f379286d0537eb68377220b4929979324b8d5d1c.idx +0 -0
@@ -0,0 +1,411 @@
1
+ import React, {createContext, useContext, useState, useRef} from 'react';
2
+ import ChatContext, {
3
+ controlMessageEnum,
4
+ messageChannelType,
5
+ attrRequestTypes,
6
+ } from '../ChatContext';
7
+ import Toast from '../../../react-native-toast-message';
8
+ import {
9
+ LiveStreamControlMessageEnum,
10
+ LSNotificationObject,
11
+ liveStreamContext,
12
+ requestStatus,
13
+ requestInterface,
14
+ attrRequestStatus,
15
+ attrRequestInterface,
16
+ liveStreamPropsInterface,
17
+ } from './Types';
18
+ import {ClientRole} from '../../../agora-rn-uikit';
19
+ import ScreenshareContext from '../../subComponents/screenshare/ScreenshareContext';
20
+ import {filterObject} from '../../utils';
21
+
22
+ const LiveStreamContext = createContext(null as unknown as liveStreamContext);
23
+
24
+ export const LiveStreamContextConsumer = LiveStreamContext.Consumer;
25
+
26
+ export const LiveStreamContextProvider = (props: liveStreamPropsInterface) => {
27
+ const screenshareContextInstance = useContext(ScreenshareContext);
28
+
29
+ const {
30
+ userList,
31
+ localUid,
32
+ sendControlMessageToUid,
33
+ sendControlMessage,
34
+ broadcastUserAttributes,
35
+ addOrUpdateLocalUserAttributes,
36
+ events,
37
+ } = useContext(ChatContext);
38
+
39
+ const {isHost, setRtcProps} = props;
40
+
41
+ const [currLiveStreamRequest, setLiveStreamRequest] = useState<
42
+ Partial<Record<string, requestInterface>>
43
+ >({});
44
+
45
+ const [uidsOfInitialRequests, setUidsOfInitialRequests] = useState<
46
+ attrRequestInterface[]
47
+ >([]);
48
+
49
+ const [activeLiveStreamRequest, setActiveLiveStreamRequest] = useState<
50
+ Partial<Record<string, requestInterface>>
51
+ >({});
52
+
53
+ const [raiseHandRequestActive, setRaiseHandRequestActive] = useState(false);
54
+
55
+ const [lastCheckedRequestTimestamp, setLastCheckedRequestTimestamp] =
56
+ useState(0);
57
+
58
+ const [lastRequestReceivedTimestamp, setLastRequestReceivedTimestamp] =
59
+ useState(0);
60
+
61
+ const [isPendingRequestToReview, setPendingRequestToReview] = useState(false);
62
+
63
+ const localUserRef = useRef({uid: localUid, status: ''});
64
+
65
+ const showToast = (text: string) => {
66
+ Toast.show({
67
+ type: 'success',
68
+ text1: text,
69
+ visibilityTime: 1000,
70
+ });
71
+ };
72
+
73
+ const updateRtcProps = (newClientRole: ClientRole) => {
74
+ setRtcProps((prevState: any) => ({
75
+ ...prevState,
76
+ role:
77
+ newClientRole === ClientRole.Audience
78
+ ? ClientRole.Audience
79
+ : ClientRole.Broadcaster,
80
+ }));
81
+ };
82
+
83
+ const getAttendeeName = (uid: number | string) => {
84
+ return userList[uid] ? userList[uid]?.name : 'user';
85
+ };
86
+
87
+ React.useEffect(() => {
88
+ setActiveLiveStreamRequest(
89
+ filterObject(
90
+ currLiveStreamRequest,
91
+ ([k, v]) => v?.status === requestStatus.AwaitingAction,
92
+ ),
93
+ );
94
+ }, [currLiveStreamRequest]);
95
+
96
+ React.useEffect(() => {
97
+ // Get the time timestamp of recent request
98
+ const recentRequest = Object.values(activeLiveStreamRequest).sort(
99
+ (a, b) => b?.ts - a?.ts || 0,
100
+ )[0]; // sorting in descending order and take the first request
101
+
102
+ if (recentRequest?.ts) {
103
+ setLastRequestReceivedTimestamp(recentRequest.ts);
104
+ }
105
+ if (Object.keys(activeLiveStreamRequest).length === 0) {
106
+ setPendingRequestToReview(false);
107
+ }
108
+ }, [activeLiveStreamRequest]);
109
+
110
+ React.useEffect(() => {
111
+ if (
112
+ // If active requests and last seen is less than last message received
113
+ Object.keys(activeLiveStreamRequest).length !== 0 &&
114
+ lastRequestReceivedTimestamp >= lastCheckedRequestTimestamp
115
+ ) {
116
+ setPendingRequestToReview(true);
117
+ } else {
118
+ setPendingRequestToReview(false);
119
+ }
120
+ }, [lastRequestReceivedTimestamp, lastCheckedRequestTimestamp]);
121
+
122
+ React.useEffect(() => {
123
+ // Remove requests for users who are offline
124
+ setLiveStreamRequest(
125
+ filterObject(
126
+ currLiveStreamRequest,
127
+ ([k, v]) => userList[k] && !userList[k]?.offline,
128
+ ),
129
+ );
130
+
131
+ // Check attribute of user joined if it has request livestreaming attribute
132
+ const uidsOfUsersHavingLSRequest: attrRequestInterface[] = Object.keys(
133
+ filterObject(
134
+ userList,
135
+ ([k, v]) =>
136
+ v?.requests === attrRequestStatus.RaiseHand_AwaitingAction ||
137
+ v?.requests === attrRequestStatus.RaiseHand_Approved,
138
+ ),
139
+ ).map((key) => ({
140
+ uid: key,
141
+ status:
142
+ userList[key]?.requests || attrRequestStatus.RaiseHand_AwaitingAction,
143
+ }));
144
+
145
+ // console.log('uidsOfUsersHavingLSRequest', uidsOfUsersHavingLSRequest);
146
+ // Set uids of user who have active live streaming request
147
+ setUidsOfInitialRequests([...uidsOfUsersHavingLSRequest]);
148
+ }, [userList]);
149
+
150
+ React.useEffect(() => {
151
+ // Filter new requests
152
+ const initialRequests = uidsOfInitialRequests
153
+ .filter(
154
+ (item: attrRequestInterface) => !currLiveStreamRequest?.[item.uid],
155
+ )
156
+ .reduce((acc, item) => {
157
+ return {
158
+ ...acc,
159
+ [item.uid]: {
160
+ uid: item.uid,
161
+ ts: new Date().getTime(),
162
+ status:
163
+ item.status === attrRequestStatus.RaiseHand_Approved
164
+ ? requestStatus.Approved
165
+ : requestStatus.AwaitingAction,
166
+ },
167
+ };
168
+ }, {});
169
+ setLiveStreamRequest((oldLiveStreamRequest) => ({
170
+ ...oldLiveStreamRequest,
171
+ ...initialRequests,
172
+ }));
173
+ }, [uidsOfInitialRequests]);
174
+
175
+ // Events listening section
176
+
177
+ React.useEffect(() => {
178
+ events.on(
179
+ messageChannelType.Public,
180
+ 'onLiveStreamActionsForHost',
181
+ (data: any, error: any) => {
182
+ if (!data) return;
183
+ if (!isHost) return;
184
+ switch (data.msg) {
185
+ // 1. All Hosts in channel add the audience request with 'Awaiting action' status
186
+ case LiveStreamControlMessageEnum.raiseHandRequest:
187
+ showToast(
188
+ `${getAttendeeName(data.uid)} ${
189
+ LSNotificationObject.RAISE_HAND_RECEIVED
190
+ }`,
191
+ );
192
+ addOrUpdateLiveStreamRequest({
193
+ uid: data.uid,
194
+ ts: data.ts,
195
+ status: requestStatus.AwaitingAction,
196
+ });
197
+ break;
198
+ // 2. All Hosts in channel update their status when a audience recalls his request
199
+ case LiveStreamControlMessageEnum.raiseHandRequestRecall:
200
+ showToast(
201
+ `${getAttendeeName(data.uid)} ${
202
+ LSNotificationObject.RAISE_HAND_REQUEST_RECALL
203
+ }`,
204
+ );
205
+ addOrUpdateLiveStreamRequest({
206
+ uid: data.uid,
207
+ ts: data.ts,
208
+ status: requestStatus.Cancelled,
209
+ });
210
+ break;
211
+ // 3. All Host in channel update their status when a audience request is approved
212
+ case LiveStreamControlMessageEnum.notifyAllRequestApproved:
213
+ addOrUpdateLiveStreamRequest({
214
+ uid: data.uid,
215
+ ts: data.ts,
216
+ status: requestStatus.Approved,
217
+ });
218
+ break;
219
+ // 4. All Host in channel update their status when a audience request is rejected
220
+ case LiveStreamControlMessageEnum.notifyAllRequestRejected:
221
+ addOrUpdateLiveStreamRequest({
222
+ uid: data.uid,
223
+ ts: data.ts,
224
+ status: requestStatus.Cancelled,
225
+ });
226
+ break;
227
+ default:
228
+ break;
229
+ }
230
+ },
231
+ );
232
+ events.on(
233
+ messageChannelType.Private,
234
+ 'onLiveStreamActionsForAudience',
235
+ (data: any, error: any) => {
236
+ if (!data) return;
237
+ switch (data.msg) {
238
+ // 1. Audience receives this when the request is accepted by host
239
+ case LiveStreamControlMessageEnum.raiseHandRequestAccepted:
240
+ if (!raiseHandRequestActive) return;
241
+ showToast(LSNotificationObject.RAISE_HAND_ACCEPTED);
242
+ // Audience notfies all host when request is approved
243
+ notifyAllHostsInChannel(
244
+ LiveStreamControlMessageEnum.notifyAllRequestApproved,
245
+ );
246
+ changeClientRoleTo(ClientRole.Broadcaster);
247
+ localUserRef.current.status = requestStatus.Approved;
248
+ updateLocalUserAttributes(attrRequestStatus.RaiseHand_Approved);
249
+ break;
250
+ // 2. Audience receives this when the request is cancelled by host
251
+ case LiveStreamControlMessageEnum.raiseHandRequestRejected:
252
+ showToast(LSNotificationObject.RAISE_HAND_REJECTED);
253
+ setRaiseHandRequestActive(false);
254
+ // Audience notfies all host when request is approved
255
+ notifyAllHostsInChannel(
256
+ LiveStreamControlMessageEnum.notifyAllRequestRejected,
257
+ );
258
+ localUserRef.current.status = requestStatus.Cancelled;
259
+ updateLocalUserAttributes(attrRequestTypes.none);
260
+ break;
261
+ // 3. Audience receives this when host demotes (canceled after approval)
262
+ case LiveStreamControlMessageEnum.raiseHandApprovedRequestRecall:
263
+ showToast(LSNotificationObject.RAISE_HAND_APPROVED_REQUEST_RECALL);
264
+ screenshareContextInstance?.stopUserScreenShare(); // This will not exist on ios
265
+ setRaiseHandRequestActive(false);
266
+ // Audience notfies all host when request is rejected
267
+ notifyAllHostsInChannel(
268
+ LiveStreamControlMessageEnum.notifyAllRequestRejected,
269
+ );
270
+ changeClientRoleTo(ClientRole.Audience);
271
+ localUserRef.current.status = requestStatus.Cancelled;
272
+ break;
273
+ // 4. Audience when receives kickUser notifies all host when is kicked out
274
+ case controlMessageEnum.kickUser:
275
+ notifyAllHostsInChannel(
276
+ LiveStreamControlMessageEnum.notifyAllRequestRejected,
277
+ );
278
+ localUserRef.current.status = requestStatus.Cancelled;
279
+ break;
280
+ default:
281
+ break;
282
+ }
283
+ },
284
+ );
285
+
286
+ return () => {
287
+ // Cleanup the listeners
288
+ events.off(messageChannelType.Public, 'onLiveStreamActionsForHost');
289
+ events.off(messageChannelType.Private, 'onLiveStreamActionsForAudience');
290
+ };
291
+ }, [events, localUid, isHost, raiseHandRequestActive, userList]);
292
+
293
+ const addOrUpdateLiveStreamRequest = (request: requestInterface) => {
294
+ if (request && request?.uid && request?.ts && request?.uid) {
295
+ setLiveStreamRequest((oldLiveStreamRequest) => ({
296
+ ...oldLiveStreamRequest,
297
+ [request?.uid as string]: {
298
+ status: request.status,
299
+ ts: request.ts,
300
+ uid: request.uid,
301
+ },
302
+ }));
303
+ }
304
+ };
305
+
306
+ const changeClientRoleTo = (newRole: ClientRole) => {
307
+ updateRtcProps(newRole);
308
+ broadcastUserAttributes(
309
+ [{key: 'role', value: newRole.toString()}],
310
+ controlMessageEnum.clientRoleChanged,
311
+ );
312
+ };
313
+
314
+ const notifyAllHostsInChannel = (ctrlEnum: LiveStreamControlMessageEnum) => {
315
+ sendControlMessage(ctrlEnum);
316
+ };
317
+
318
+ /****************** HOST CONTROLS ******************
319
+ * Host controls for Live Streaming
320
+ * a. Host can approve streaming request sent by audience
321
+ * b. Host can reject streaming request sent by audience
322
+ */
323
+
324
+ const hostApprovesRequestOfUID = (uid: number | string) => {
325
+ addOrUpdateLiveStreamRequest({
326
+ uid,
327
+ ts: new Date().getTime(),
328
+ status: requestStatus.Cancelled,
329
+ });
330
+ sendControlMessageToUid(
331
+ LiveStreamControlMessageEnum.raiseHandRequestAccepted,
332
+ uid,
333
+ );
334
+ };
335
+
336
+ const hostRejectsRequestOfUID = (uid: number | string) => {
337
+ addOrUpdateLiveStreamRequest({
338
+ uid,
339
+ ts: new Date().getTime(),
340
+ status: requestStatus.Cancelled,
341
+ });
342
+ sendControlMessageToUid(
343
+ LiveStreamControlMessageEnum.raiseHandRequestRejected,
344
+ uid,
345
+ );
346
+ };
347
+
348
+ /****************** AUDIENCE CONTROLS ****************
349
+ * Audience have below controls
350
+ * a. Audience can raise a request to live stream
351
+ * b. Audience can recalls his request to live stream
352
+ * i. While recalling the request could be either approved or not approved
353
+ */
354
+
355
+ const audienceSendsRequest = () => {
356
+ showToast(LSNotificationObject.RAISE_HAND_REQUEST);
357
+ setRaiseHandRequestActive(true);
358
+ sendControlMessage(LiveStreamControlMessageEnum.raiseHandRequest);
359
+ updateLocalUserAttributes(attrRequestStatus.RaiseHand_AwaitingAction);
360
+ };
361
+
362
+ const audienceRecallsRequest = () => {
363
+ /**
364
+ * if: Check if request is already approved
365
+ * else: Audience Request was not approved by host, and was in 'Awaiting Action' status
366
+ */
367
+ if (
368
+ localUserRef &&
369
+ localUserRef.current?.status === requestStatus.Approved
370
+ ) {
371
+ screenshareContextInstance?.stopUserScreenShare(); // This will not exist on ios
372
+ setRaiseHandRequestActive(false);
373
+ /// Change role and send message in channel notifying the same
374
+ changeClientRoleTo(ClientRole.Audience);
375
+ notifyAllHostsInChannel(
376
+ LiveStreamControlMessageEnum.notifyAllRequestRejected,
377
+ );
378
+ } else {
379
+ setRaiseHandRequestActive(false);
380
+ // Send message in channel to withdraw the request
381
+ sendControlMessage(LiveStreamControlMessageEnum.raiseHandRequestRecall);
382
+ }
383
+ updateLocalUserAttributes(attrRequestTypes.none);
384
+ showToast(LSNotificationObject.RAISE_HAND_REQUEST_RECALL_LOCAL);
385
+ };
386
+
387
+ const updateLocalUserAttributes = (
388
+ value: attrRequestTypes | attrRequestStatus,
389
+ ) => {
390
+ addOrUpdateLocalUserAttributes([{key: 'requests', value: value}]);
391
+ };
392
+
393
+ return (
394
+ <LiveStreamContext.Provider
395
+ value={{
396
+ setLastCheckedRequestTimestamp,
397
+ isPendingRequestToReview,
398
+ currLiveStreamRequest,
399
+ hostApprovesRequestOfUID,
400
+ hostRejectsRequestOfUID,
401
+ audienceSendsRequest,
402
+ audienceRecallsRequest,
403
+ raiseHandRequestActive,
404
+ setRaiseHandRequestActive,
405
+ }}>
406
+ {props.children}
407
+ </LiveStreamContext.Provider>
408
+ );
409
+ };
410
+
411
+ export default LiveStreamContext;
@@ -0,0 +1,69 @@
1
+ // DECLARE ENUMS & CONTANTS
2
+
3
+ export enum requestStatus {
4
+ AwaitingAction = 'AWAITING_ACTION',
5
+ Approved = 'APPROVED',
6
+ Cancelled = 'CANCELLED',
7
+ }
8
+
9
+ export enum attrRequestStatus {
10
+ RaiseHand_AwaitingAction = 'AWAITING_ACTION',
11
+ RaiseHand_Approved = 'APPROVED',
12
+ }
13
+
14
+ export enum LiveStreamControlMessageEnum {
15
+ raiseHandRequest = 'RAISE_HAND_REQUEST',
16
+ raiseHandRequestAccepted = 'RAISE_HAND_ACCEPTED',
17
+ raiseHandRequestRejected = 'RAISE_HAND_REJECTED',
18
+ raiseHandRequestReceived = 'RAISE_HAND_RECEIVED',
19
+ raiseHandRequestRecall = 'RAISE_HAND_REQUEST_RECALL',
20
+ raiseHandRequestRecallLocal = 'RAISE_HAND_REQUEST_RECALL_LOCAL',
21
+ raiseHandApprovedRequestRecall = 'RAISE_HAND_APPROVED_REQUEST_RECALL',
22
+ notifyAllRequestApproved = 'NOTIFY_REQUEST_APPROVED',
23
+ notifyAllRequestRejected = 'NOTIFY_REQUEST_REJECTED',
24
+ }
25
+
26
+ export const LSNotificationObject = {
27
+ [LiveStreamControlMessageEnum.raiseHandRequest]:
28
+ 'You have raised your hand. Request sent to host for approval',
29
+ [LiveStreamControlMessageEnum.raiseHandRequestReceived]:
30
+ 'has raised their hand',
31
+ [LiveStreamControlMessageEnum.raiseHandRequestAccepted]:
32
+ 'Your request was approved, unmute to start talking',
33
+ [LiveStreamControlMessageEnum.raiseHandRequestRejected]:
34
+ 'Your request was rejected by the host',
35
+ [LiveStreamControlMessageEnum.raiseHandRequestRecall]:
36
+ 'has lowered their hand',
37
+ [LiveStreamControlMessageEnum.raiseHandRequestRecallLocal]:
38
+ 'You have lowered your hand',
39
+ [LiveStreamControlMessageEnum.raiseHandApprovedRequestRecall]:
40
+ 'The host has revoked streaming permissions',
41
+ };
42
+
43
+ export interface liveStreamPropsInterface {
44
+ isHost: boolean;
45
+ setRtcProps: any;
46
+ }
47
+
48
+ export interface liveStreamContext {
49
+ setLastCheckedRequestTimestamp: (timestamp: number) => void;
50
+ isPendingRequestToReview: boolean;
51
+ currLiveStreamRequest: Partial<Record<string, requestInterface>>;
52
+ hostApprovesRequestOfUID: (uid: number) => void;
53
+ hostRejectsRequestOfUID: (uid: number) => void;
54
+ audienceSendsRequest: () => void;
55
+ audienceRecallsRequest: () => void;
56
+ raiseHandRequestActive: boolean;
57
+ setRaiseHandRequestActive: (state: boolean) => void;
58
+ }
59
+
60
+ export interface requestInterface {
61
+ ts: number;
62
+ status: requestStatus;
63
+ uid: string | number;
64
+ }
65
+
66
+ export interface attrRequestInterface {
67
+ status: attrRequestStatus;
68
+ uid: string | number;
69
+ }
@@ -0,0 +1,9 @@
1
+ import {LiveStreamControlMessageEnum, requestStatus} from './Types';
2
+
3
+ import LiveStreamContext, {
4
+ LiveStreamContextProvider,
5
+ } from './LiveStreamContext';
6
+
7
+ export {LiveStreamContextProvider, LiveStreamControlMessageEnum, requestStatus};
8
+
9
+ export default LiveStreamContext;
@@ -0,0 +1,27 @@
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 {View} from 'react-native';
14
+ import {LocalRaiseHand} from '../../../subComponents/livestream';
15
+
16
+ const LiveStreamControls = (props: any) => {
17
+ const {showControls} = props;
18
+ if (!$config.RAISE_HAND) return <></>;
19
+ if (!showControls) return <></>;
20
+ return (
21
+ <View style={{alignSelf: 'center'}}>
22
+ <LocalRaiseHand />
23
+ </View>
24
+ );
25
+ };
26
+
27
+ export default LiveStreamControls;
@@ -0,0 +1,53 @@
1
+ import React, {useContext} from 'react';
2
+ import {View, Text} from 'react-native';
3
+ import RemoteEndCall from '../../subComponents/RemoteEndCall';
4
+ import ParticipantName from '../../components/participants/ParticipantName';
5
+ import chatContext from '../ChatContext';
6
+
7
+ const AllAudienceParticipants = (props: any) => {
8
+ const {p_style, isHost, participantList} = props;
9
+ const {localUid} = useContext(chatContext);
10
+
11
+ return (
12
+ <View style={p_style.participantContainer}>
13
+ {Object.keys(participantList).length == 0 ? (
14
+ <Text style={p_style.infoText}>No one has joined yet</Text>
15
+ ) : (
16
+ <>
17
+ {/* Audience should see his name first */}
18
+ {Object.entries(participantList)
19
+ .filter(([uid, _]: any) => uid === localUid)
20
+ .map(([uid, user]: any, index: number) => (
21
+ <View style={p_style.participantRow} key={index}>
22
+ <ParticipantName value={user.name} />
23
+ {isHost && (
24
+ <View style={p_style.participantActionContainer}>
25
+ <View style={[p_style.actionBtnIcon]}>
26
+ <RemoteEndCall uid={uid} isHost={isHost} />
27
+ </View>
28
+ </View>
29
+ )}
30
+ </View>
31
+ ))}
32
+ {/* Others Audience in the call */}
33
+ {Object.entries(participantList)
34
+ .filter(([uid, _]: any) => uid !== localUid)
35
+ .map(([uid, user]: any, index: number) => (
36
+ <View style={p_style.participantRow} key={index}>
37
+ <ParticipantName value={user.name} />
38
+ {isHost && (
39
+ <View style={p_style.participantActionContainer}>
40
+ <View style={[p_style.actionBtnIcon]}>
41
+ <RemoteEndCall uid={uid} isHost={isHost} />
42
+ </View>
43
+ </View>
44
+ )}
45
+ </View>
46
+ ))}
47
+ </>
48
+ )}
49
+ </View>
50
+ );
51
+ };
52
+
53
+ export default AllAudienceParticipants;
@@ -0,0 +1,65 @@
1
+ import React, {useContext} from 'react';
2
+ import {MinUidConsumer, MaxUidConsumer} from '../../../agora-rn-uikit';
3
+ import chatContext from '../ChatContext';
4
+
5
+ import MeParticipant from './MeParticipant';
6
+ import ScreenshareParticipants from './ScreenshareParticipants';
7
+ import RemoteParticipants from './RemoteParticipants';
8
+ import {UserType} from './../RTMConfigure';
9
+
10
+ export default function AllHostParticipants(props: any) {
11
+ const {p_style, isHost} = props;
12
+ const {userList, localUid} = useContext(chatContext);
13
+
14
+ const getParticipantName = (userUID: number | string) => {
15
+ if (userUID === 'local')
16
+ return userList[localUid] ? userList[localUid].name + ' ' : 'You ';
17
+ else if (userUID === 1)
18
+ return userList[localUid]
19
+ ? userList[localUid].name + "'s screenshare "
20
+ : 'Your screenshare ';
21
+ else
22
+ return userList[userUID]
23
+ ? userList[userUID].name + ' '
24
+ : String(userUID)[0] === '1'
25
+ ? 'PSTN User '
26
+ : 'User ';
27
+ };
28
+
29
+ return (
30
+ <MinUidConsumer>
31
+ {(minUsers) => (
32
+ <MaxUidConsumer>
33
+ {(maxUser) =>
34
+ [...minUsers, ...maxUser].map((user) =>
35
+ user.uid === 'local' ? (
36
+ <MeParticipant
37
+ name={getParticipantName(user.uid)}
38
+ p_style={p_style}
39
+ key={user.uid}
40
+ />
41
+ ) : user.uid === 1 ? (
42
+ <ScreenshareParticipants
43
+ name={getParticipantName(user.uid)}
44
+ p_styles={p_style}
45
+ key={user.uid}
46
+ />
47
+ ) : (
48
+ <RemoteParticipants
49
+ name={getParticipantName(user.uid)}
50
+ p_styles={p_style}
51
+ user={user}
52
+ showControls={
53
+ userList[user.uid]?.type !== UserType.ScreenShare
54
+ }
55
+ isHost={isHost}
56
+ key={user.uid}
57
+ />
58
+ ),
59
+ )
60
+ }
61
+ </MaxUidConsumer>
62
+ )}
63
+ </MinUidConsumer>
64
+ );
65
+ }
@@ -0,0 +1,37 @@
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 {View} from 'react-native';
14
+ import {LocalAudioMute, LocalVideoMute} from '../../../agora-rn-uikit';
15
+ import {LocalUserContext} from '../../../agora-rn-uikit';
16
+ import ParticipantName from './ParticipantName';
17
+
18
+ const MeParticipant = (props: any) => {
19
+ const {p_style, name} = props;
20
+
21
+ return (
22
+ <View style={p_style.participantRow}>
23
+ <ParticipantName value={name} />
24
+ <View style={p_style.participantActionContainer}>
25
+ <LocalUserContext>
26
+ <View style={[p_style.actionBtnIcon, {marginRight: 10}]}>
27
+ <LocalAudioMute btnText=" " variant="text" />
28
+ </View>
29
+ <View style={p_style.actionBtnIcon}>
30
+ <LocalVideoMute btnText=" " variant="text" />
31
+ </View>
32
+ </LocalUserContext>
33
+ </View>
34
+ </View>
35
+ );
36
+ };
37
+ export default MeParticipant;