agora-appbuilder-core 4.1.9 → 4.1.10-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 +2 -2
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -3
- package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +1 -2
- package/template/agora-rn-uikit/src/Reducer/index.ts +0 -2
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +11 -25
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +1 -14
- package/template/bridge/rtc/webNg/RtcEngine.ts +2 -2
- package/template/bridge/rtm/web/index.ts +30 -0
- package/template/customization-api/typeDefinition.ts +1 -0
- package/template/defaultConfig.js +3 -2
- package/template/global.d.ts +1 -0
- package/template/src/AppRoutes.tsx +3 -3
- package/template/src/ai-agent/components/ControlButtons.tsx +1 -1
- package/template/src/assets/font-styles.css +36 -0
- package/template/src/assets/fonts/icomoon.ttf +0 -0
- package/template/src/assets/selection.json +1 -1
- package/template/src/atoms/CustomIcon.tsx +8 -0
- package/template/src/atoms/Dropdown.tsx +5 -0
- package/template/src/atoms/TertiaryButton.tsx +1 -1
- package/template/src/atoms/UserAvatar.tsx +1 -1
- package/template/src/components/ChatContext.ts +5 -3
- package/template/src/components/Controls.tsx +68 -22
- package/template/src/components/DeviceConfigure.tsx +1 -1
- package/template/src/components/EventsConfigure.tsx +22 -17
- package/template/src/components/Navbar.tsx +14 -11
- package/template/src/components/RTMConfigure.tsx +31 -1036
- package/template/src/components/UserGlobalPreferenceProvider.tsx +227 -0
- package/template/src/components/beauty-effect/useBeautyEffects.tsx +50 -13
- package/template/src/components/breakout-room/BreakoutRoomPanel.tsx +58 -0
- package/template/src/components/breakout-room/context/BreakoutRoomContext.tsx +2508 -0
- package/template/src/components/breakout-room/events/BreakoutRoomEventsConfigure.tsx +272 -0
- package/template/src/components/breakout-room/events/constants.ts +17 -0
- package/template/src/components/breakout-room/hoc/BreakoutRoomNameRenderer.tsx +68 -0
- package/template/src/components/breakout-room/hooks/useBreakoutRoomExit.ts +49 -0
- package/template/src/components/breakout-room/state/reducer.ts +522 -0
- package/template/src/components/breakout-room/state/types.ts +54 -0
- package/template/src/components/breakout-room/ui/BreakoutMeetingTitle.tsx +60 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomActionMenu.tsx +136 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomAnnouncementModal.tsx +135 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomGroupSettings.tsx +588 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomMainRoomUsers.tsx +142 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomMemberActionMenu.tsx +122 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomParticipants.tsx +124 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomRaiseHand.tsx +65 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomRenameModal.tsx +227 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomSettings.tsx +140 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomTransition.tsx +52 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomView.tsx +193 -0
- package/template/src/components/breakout-room/ui/ExitBreakoutRoomIconButton.tsx +79 -0
- package/template/src/components/breakout-room/ui/ParticipantManualAssignmentModal.tsx +638 -0
- package/template/src/components/breakout-room/ui/SelectParticipantAssignmentStrategy.tsx +57 -0
- package/template/src/components/chat/chatConfigure.tsx +7 -1
- package/template/src/components/chat-messages/useChatMessages.tsx +43 -11
- package/template/src/components/common/Dividers.tsx +53 -0
- package/template/src/components/controls/toolbar-items/ExitBreakoutRoomToolbarItem.tsx +13 -0
- package/template/src/components/controls/useControlPermissionMatrix.tsx +32 -4
- package/template/src/components/participants/AllHostParticipants.tsx +10 -2
- package/template/src/components/participants/Participant.tsx +7 -1
- package/template/src/components/participants/UserActionMenuOptions.tsx +12 -2
- package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +12 -8
- package/template/src/components/precall/joinWaitingRoomBtn.tsx +14 -10
- package/template/src/components/raise-hand/RaiseHandButton.tsx +50 -0
- package/template/src/components/raise-hand/RaiseHandProvider.tsx +308 -0
- package/template/src/components/raise-hand/index.ts +14 -0
- package/template/src/components/recordings/RecordingsDateTable.tsx +3 -2
- package/template/src/components/room-info/useCurrentRoomInfo.tsx +42 -0
- package/template/src/components/room-info/useSetBreakoutRoomInfo.tsx +64 -0
- package/template/src/components/useUserPreference.tsx +39 -12
- package/template/src/components/virtual-background/useVB.tsx +18 -0
- package/template/src/components/whiteboard/WhiteboardConfigure.tsx +27 -0
- package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -0
- package/template/src/logger/AppBuilderLogger.tsx +11 -3
- package/template/src/pages/VideoCall.tsx +171 -518
- package/template/src/pages/video-call/BreakoutVideoCall.tsx +213 -0
- package/template/src/pages/video-call/SidePanelHeader.tsx +17 -0
- package/template/src/pages/video-call/VideoCallContent.tsx +211 -0
- package/template/src/pages/video-call/VideoCallScreen.tsx +18 -0
- package/template/src/pages/video-call/VideoCallScreenWrapper.tsx +0 -1
- package/template/src/pages/video-call/VideoCallStateWrapper.tsx +495 -0
- package/template/src/rtm/RTMConfigureBreakoutRoomProvider.tsx +882 -0
- package/template/src/rtm/RTMConfigureMainRoomProvider.tsx +757 -0
- package/template/src/rtm/RTMCoreProvider.tsx +419 -0
- package/template/src/rtm/RTMEngine.ts +188 -60
- package/template/src/rtm/RTMGlobalStateProvider.tsx +706 -0
- package/template/src/rtm/RTMStatusBanner.tsx +99 -0
- package/template/src/rtm/constants.ts +12 -0
- package/template/src/rtm/hooks/useMainRoomUserDisplayName.ts +45 -0
- package/template/src/rtm/rtm-presence-utils.ts +344 -0
- package/template/src/rtm/utils.ts +68 -1
- package/template/src/rtm-events/constants.ts +40 -1
- package/template/src/rtm-events-api/Events.ts +62 -19
- package/template/src/subComponents/ChatBubble.tsx +3 -3
- package/template/src/subComponents/ChatContainer.tsx +19 -9
- package/template/src/subComponents/LocalAudioMute.tsx +2 -2
- package/template/src/subComponents/LocalVideoMute.tsx +2 -2
- package/template/src/subComponents/SidePanelEnum.tsx +1 -0
- package/template/src/subComponents/caption/useCaption.tsx +1 -1
- package/template/src/subComponents/chat/ChatAnnouncementView.tsx +65 -0
- package/template/src/subComponents/chat/ChatSendButton.tsx +1 -0
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +16 -0
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +1 -1
- package/template/src/subComponents/waiting-rooms/WaitingRoomControls.tsx +7 -4
- package/template/src/utils/useDebouncedCallback.tsx +20 -0
- package/template/src/utils/useEndCall.ts +0 -2
- package/template/src/utils/useMuteToggleLocal.ts +14 -10
- package/template/agora-rn-uikit/src/Reducer/Spotlight.ts +0 -11
- package/template/agora-rn-uikit/src/Reducer/UserBanned.ts +0 -11
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
('use strict');
|
|
14
14
|
import {type RTMClient} from 'agora-react-native-rtm';
|
|
15
15
|
import RTMEngine from '../rtm/RTMEngine';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
EventUtils,
|
|
18
|
+
RTM_EVENT_SCOPE,
|
|
19
|
+
RTM_GLOBAL_SCOPE_EVENTS,
|
|
20
|
+
RTM_SESSION_SCOPE_EVENTS,
|
|
21
|
+
} from '../rtm-events';
|
|
17
22
|
import {
|
|
18
23
|
ReceiverUid,
|
|
19
24
|
EventCallback,
|
|
@@ -25,6 +30,16 @@ import {adjustUID} from '../rtm/utils';
|
|
|
25
30
|
import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
26
31
|
import {nativeChannelTypeMapping} from '../../bridge/rtm/web/Types';
|
|
27
32
|
|
|
33
|
+
function getRTMEventScope(eventName: string): RTM_EVENT_SCOPE {
|
|
34
|
+
if (RTM_GLOBAL_SCOPE_EVENTS.includes(eventName)) {
|
|
35
|
+
return RTM_EVENT_SCOPE.GLOBAL;
|
|
36
|
+
}
|
|
37
|
+
if (RTM_SESSION_SCOPE_EVENTS.includes(eventName)) {
|
|
38
|
+
return RTM_EVENT_SCOPE.SESSION;
|
|
39
|
+
}
|
|
40
|
+
return RTM_EVENT_SCOPE.LOCAL;
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
class Events {
|
|
29
44
|
private source: EventSource = EventSource.core;
|
|
30
45
|
|
|
@@ -41,10 +56,16 @@ class Events {
|
|
|
41
56
|
* @param {String} payload to be stored in rtm Attribute value
|
|
42
57
|
* @api private
|
|
43
58
|
*/
|
|
44
|
-
private _persist = async (evt: string, payload: string) => {
|
|
59
|
+
private _persist = async (evt: string, payload: string, roomKey?: string) => {
|
|
45
60
|
const rtmEngine: RTMClient = RTMEngine.getInstance().engine;
|
|
46
61
|
const userId = RTMEngine.getInstance().localUid;
|
|
47
62
|
try {
|
|
63
|
+
// const roomAwareKey = roomKey ? `${roomKey}__${evt}` : evt;
|
|
64
|
+
// console.log(
|
|
65
|
+
// 'session-attributes setting roomAwareKey as: ',
|
|
66
|
+
// roomAwareKey,
|
|
67
|
+
// evt,
|
|
68
|
+
// );
|
|
48
69
|
const rtmAttribute = {key: evt, value: payload};
|
|
49
70
|
// Step 1: Call RTM API to update local attributes
|
|
50
71
|
await rtmEngine.storage.setUserMetadata(
|
|
@@ -104,11 +125,13 @@ class Events {
|
|
|
104
125
|
*
|
|
105
126
|
* @param {Object} rtmPayload payload to be sent across
|
|
106
127
|
* @param {ReceiverUid} toUid uid or uids[] of user
|
|
128
|
+
* @param {string} channelId optional specific channel ID, defaults to primary channel
|
|
107
129
|
* @api private
|
|
108
130
|
*/
|
|
109
131
|
private _send = async (
|
|
110
132
|
rtmPayload: RTMAttributePayload,
|
|
111
133
|
toUid?: ReceiverUid,
|
|
134
|
+
toChannelId?: string,
|
|
112
135
|
) => {
|
|
113
136
|
const to = typeof toUid === 'string' ? parseInt(toUid, 10) : toUid;
|
|
114
137
|
|
|
@@ -131,16 +154,21 @@ class Events {
|
|
|
131
154
|
'case 1 executed - sending in channel',
|
|
132
155
|
);
|
|
133
156
|
try {
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
logger.debug(
|
|
158
|
+
LogSource.Events,
|
|
159
|
+
'CUSTOM_EVENTS',
|
|
160
|
+
'event is sent to targetChannelId ->',
|
|
161
|
+
toChannelId,
|
|
162
|
+
);
|
|
163
|
+
if (!toChannelId || toChannelId.trim() === '') {
|
|
136
164
|
throw new Error(
|
|
137
|
-
'Channel ID is not set. Cannot send channel
|
|
165
|
+
'Channel ID is not set. Cannot send channel messages.',
|
|
138
166
|
);
|
|
139
167
|
}
|
|
140
|
-
await rtmEngine.publish(
|
|
168
|
+
await rtmEngine.publish(toChannelId, text, {
|
|
141
169
|
channelType: nativeChannelTypeMapping.MESSAGE, // 1 is message
|
|
142
|
-
customType: 'PlainText',
|
|
143
|
-
messageType:
|
|
170
|
+
// customType: 'PlainText',
|
|
171
|
+
// messageType: RtmMessageType.string,
|
|
144
172
|
});
|
|
145
173
|
} catch (error) {
|
|
146
174
|
logger.error(
|
|
@@ -223,7 +251,10 @@ class Events {
|
|
|
223
251
|
}
|
|
224
252
|
};
|
|
225
253
|
|
|
226
|
-
private _sendAsChannelAttribute = async (
|
|
254
|
+
private _sendAsChannelAttribute = async (
|
|
255
|
+
rtmPayload: RTMAttributePayload,
|
|
256
|
+
toChannelId?: string,
|
|
257
|
+
) => {
|
|
227
258
|
// Case 1: send to channel
|
|
228
259
|
logger.debug(
|
|
229
260
|
LogSource.Events,
|
|
@@ -237,16 +268,13 @@ class Events {
|
|
|
237
268
|
}
|
|
238
269
|
const rtmEngine: RTMClient = RTMEngine.getInstance().engine;
|
|
239
270
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
throw new Error(
|
|
243
|
-
'Channel ID is not set. Cannot send channel attributes.',
|
|
244
|
-
);
|
|
271
|
+
if (!toChannelId) {
|
|
272
|
+
throw new Error('Channel ID is not set. Cannot send channel messages.');
|
|
245
273
|
}
|
|
246
274
|
|
|
247
275
|
const rtmAttribute = [{key: rtmPayload.evt, value: rtmPayload.value}];
|
|
248
276
|
await rtmEngine.storage.setChannelMetadata(
|
|
249
|
-
|
|
277
|
+
toChannelId,
|
|
250
278
|
nativeChannelTypeMapping.MESSAGE,
|
|
251
279
|
{
|
|
252
280
|
items: rtmAttribute,
|
|
@@ -351,6 +379,7 @@ class Events {
|
|
|
351
379
|
* @param {String} payload (optional) Additional data to be sent along with the event.
|
|
352
380
|
* @param {Enum} persistLevel (optional) set different levels of persistance. Default value is Level 1
|
|
353
381
|
* @param {ReceiverUid} receiver (optional) uid or uid array. Default mode sends message in channel.
|
|
382
|
+
* @param {String} channelId (optional) specific channel to send to, defaults to primary channel.
|
|
354
383
|
* @api public
|
|
355
384
|
* */
|
|
356
385
|
send = async (
|
|
@@ -358,6 +387,7 @@ class Events {
|
|
|
358
387
|
payload: string = '',
|
|
359
388
|
persistLevel: PersistanceLevel = PersistanceLevel.None,
|
|
360
389
|
receiver: ReceiverUid = -1,
|
|
390
|
+
toChannelId?: string,
|
|
361
391
|
) => {
|
|
362
392
|
try {
|
|
363
393
|
if (!this._validateEvt(eventName)) {
|
|
@@ -373,12 +403,18 @@ class Events {
|
|
|
373
403
|
return; // Don't throw - just log and return
|
|
374
404
|
}
|
|
375
405
|
|
|
406
|
+
// Add meta data
|
|
407
|
+
let currentEventScope = getRTMEventScope(eventName);
|
|
408
|
+
let currentChannelId = RTMEngine.getInstance().getActiveChannelId();
|
|
409
|
+
let currentRoomKey = RTMEngine.getInstance().getActiveChannelName();
|
|
410
|
+
|
|
376
411
|
const persistValue = JSON.stringify({
|
|
377
412
|
payload,
|
|
378
413
|
persistLevel,
|
|
379
414
|
source: this.source,
|
|
415
|
+
_scope: currentEventScope,
|
|
416
|
+
_channelId: currentChannelId,
|
|
380
417
|
});
|
|
381
|
-
|
|
382
418
|
const rtmPayload: RTMAttributePayload = {
|
|
383
419
|
evt: eventName,
|
|
384
420
|
value: persistValue,
|
|
@@ -389,7 +425,13 @@ class Events {
|
|
|
389
425
|
persistLevel === PersistanceLevel.Session
|
|
390
426
|
) {
|
|
391
427
|
try {
|
|
392
|
-
await this._persist(
|
|
428
|
+
await this._persist(
|
|
429
|
+
eventName,
|
|
430
|
+
persistValue,
|
|
431
|
+
persistLevel === PersistanceLevel.Session
|
|
432
|
+
? currentRoomKey
|
|
433
|
+
: undefined,
|
|
434
|
+
);
|
|
393
435
|
} catch (error) {
|
|
394
436
|
logger.error(LogSource.Events, 'CUSTOM_EVENTS', 'persist error', error);
|
|
395
437
|
// don't throw - just log the error, application should continue running
|
|
@@ -402,10 +444,11 @@ class Events {
|
|
|
402
444
|
`sending event -> ${eventName}`,
|
|
403
445
|
persistValue,
|
|
404
446
|
);
|
|
447
|
+
const targetChannelId = toChannelId || currentChannelId;
|
|
405
448
|
if (persistLevel === PersistanceLevel.Channel) {
|
|
406
|
-
await this._sendAsChannelAttribute(rtmPayload);
|
|
449
|
+
await this._sendAsChannelAttribute(rtmPayload, targetChannelId);
|
|
407
450
|
} else {
|
|
408
|
-
await this._send(rtmPayload, receiver);
|
|
451
|
+
await this._send(rtmPayload, receiver, targetChannelId);
|
|
409
452
|
}
|
|
410
453
|
} catch (error) {
|
|
411
454
|
logger.error(
|
|
@@ -52,6 +52,7 @@ import {useChatConfigure} from '../../src/components/chat/chatConfigure';
|
|
|
52
52
|
import Tooltip from '../../src/atoms/Tooltip';
|
|
53
53
|
import {MoreMessageOptions} from './chat/ChatQuickActionsMenu';
|
|
54
54
|
import {EMessageStatus} from '../../src/ai-agent/components/AgentControls/message';
|
|
55
|
+
import {useMainRoomUserDisplayName} from '../rtm/hooks/useMainRoomUserDisplayName';
|
|
55
56
|
|
|
56
57
|
type AttachmentBubbleProps = {
|
|
57
58
|
fileName: string;
|
|
@@ -362,6 +363,7 @@ const ChatBubble = (props: ChatBubbleProps) => {
|
|
|
362
363
|
//commented for v1 release
|
|
363
364
|
//const remoteUserDefaultLabel = useString('remoteUserDefaultLabel')();
|
|
364
365
|
const remoteUserDefaultLabel = useString(videoRoomUserFallbackText)();
|
|
366
|
+
const getDisplayName = useMainRoomUserDisplayName();
|
|
365
367
|
|
|
366
368
|
const getUsername = () => {
|
|
367
369
|
if (isLocal) {
|
|
@@ -370,9 +372,7 @@ const ChatBubble = (props: ChatBubbleProps) => {
|
|
|
370
372
|
if (remoteUIConfig?.username) {
|
|
371
373
|
return trimText(remoteUIConfig?.username);
|
|
372
374
|
}
|
|
373
|
-
return
|
|
374
|
-
? trimText(defaultContent[uid].name)
|
|
375
|
-
: remoteUserDefaultLabel;
|
|
375
|
+
return getDisplayName(uid);
|
|
376
376
|
};
|
|
377
377
|
|
|
378
378
|
return props?.render ? (
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
} from 'react-native';
|
|
28
28
|
import {RFValue} from 'react-native-responsive-fontsize';
|
|
29
29
|
import ChatBubble from './ChatBubble';
|
|
30
|
-
import {ChatBubbleProps} from '../components/ChatContext';
|
|
30
|
+
import ChatContext, {ChatBubbleProps} from '../components/ChatContext';
|
|
31
31
|
import {
|
|
32
32
|
DispatchContext,
|
|
33
33
|
ContentInterface,
|
|
@@ -59,6 +59,7 @@ import {
|
|
|
59
59
|
} from '../language/default-labels/videoCallScreenLabels';
|
|
60
60
|
import CommonStyles from '../components/CommonStyles';
|
|
61
61
|
import PinnedMessage from './chat/PinnedMessage';
|
|
62
|
+
import ChatAnnouncementView from './chat/ChatAnnouncementView';
|
|
62
63
|
|
|
63
64
|
/**
|
|
64
65
|
* Chat container is the component which renders all the chat messages
|
|
@@ -71,6 +72,7 @@ const ChatContainer = (props?: {
|
|
|
71
72
|
const info1 = useString<boolean>(groupChatWelcomeContent);
|
|
72
73
|
const [scrollToEnd, setScrollToEnd] = useState(false);
|
|
73
74
|
const {dispatch} = useContext(DispatchContext);
|
|
75
|
+
const {syncUserState} = useContext(ChatContext);
|
|
74
76
|
const [grpUnreadCount, setGrpUnreadCount] = useState(0);
|
|
75
77
|
const [privateUnreadCount, setPrivateUnreadCount] = useState(0);
|
|
76
78
|
const {defaultContent} = useContent();
|
|
@@ -118,16 +120,18 @@ const ChatContainer = (props?: {
|
|
|
118
120
|
});
|
|
119
121
|
//Once message is seen, reset lastMessageTimeStamp.
|
|
120
122
|
//so whoever has unread count will show in the top of participant list
|
|
121
|
-
updateRenderListState(privateChatUser, {lastMessageTimeStamp: 0});
|
|
123
|
+
// updateRenderListState(privateChatUser, {lastMessageTimeStamp: 0});
|
|
124
|
+
syncUserState(privateChatUser, {lastMessageTimeStamp: 0});
|
|
122
125
|
}
|
|
123
126
|
}, [privateChatUser]);
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
128
|
+
// We will be using syncRoomusers
|
|
129
|
+
// const updateRenderListState = (
|
|
130
|
+
// uid: number,
|
|
131
|
+
// data: Partial<ContentInterface>,
|
|
132
|
+
// ) => {
|
|
133
|
+
// dispatch({type: 'UpdateRenderList', value: [uid, data]});
|
|
134
|
+
// };
|
|
131
135
|
|
|
132
136
|
const onScroll = event => {
|
|
133
137
|
setScrollOffset(event.nativeEvent.contentOffset.y);
|
|
@@ -249,7 +253,13 @@ const ChatContainer = (props?: {
|
|
|
249
253
|
</Text>
|
|
250
254
|
</View>
|
|
251
255
|
) : null}
|
|
252
|
-
|
|
256
|
+
|
|
257
|
+
{message?.announcement ? (
|
|
258
|
+
<ChatAnnouncementView
|
|
259
|
+
message={message.msg}
|
|
260
|
+
announcement={message.announcement}
|
|
261
|
+
/>
|
|
262
|
+
) : !message?.hide ? (
|
|
253
263
|
<ChatBubbleComponent
|
|
254
264
|
isLocal={localUid === message.uid}
|
|
255
265
|
isSameUser={
|
|
@@ -85,7 +85,7 @@ function LocalAudioMute(props: LocalAudioMuteProps) {
|
|
|
85
85
|
local.permissionStatus === PermissionState.REJECTED ||
|
|
86
86
|
local.permissionStatus === PermissionState.GRANTED_FOR_CAM_ONLY;
|
|
87
87
|
|
|
88
|
-
const onPress = () => {
|
|
88
|
+
const onPress = async () => {
|
|
89
89
|
logger.log(
|
|
90
90
|
LogSource.Internals,
|
|
91
91
|
'LOCAL_MUTE',
|
|
@@ -95,7 +95,7 @@ function LocalAudioMute(props: LocalAudioMuteProps) {
|
|
|
95
95
|
permissionDenied,
|
|
96
96
|
},
|
|
97
97
|
);
|
|
98
|
-
localMute(MUTE_LOCAL_TYPE.audio);
|
|
98
|
+
await localMute(MUTE_LOCAL_TYPE.audio);
|
|
99
99
|
};
|
|
100
100
|
const audioLabel = permissionDenied
|
|
101
101
|
? micButtonLabel(I18nDeviceStatus.PERMISSION_DENIED)
|
|
@@ -79,7 +79,7 @@ function LocalVideoMute(props: LocalVideoMuteProps) {
|
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
const lstooltip = useString<boolean>(livestreamingCameraTooltipText);
|
|
82
|
-
const onPress = () => {
|
|
82
|
+
const onPress = async () => {
|
|
83
83
|
//if screensharing is going on native - to turn on video screenshare should be turn off
|
|
84
84
|
//show confirm popup to stop the screenshare
|
|
85
85
|
logger.log(
|
|
@@ -91,7 +91,7 @@ function LocalVideoMute(props: LocalVideoMuteProps) {
|
|
|
91
91
|
permissionDenied,
|
|
92
92
|
},
|
|
93
93
|
);
|
|
94
|
-
localMute(MUTE_LOCAL_TYPE.video);
|
|
94
|
+
await localMute(MUTE_LOCAL_TYPE.video);
|
|
95
95
|
};
|
|
96
96
|
const isVideoEnabled = local.video === ToggleState.enabled;
|
|
97
97
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {View, StyleSheet, Text} from 'react-native';
|
|
3
|
+
import ImageIcon from '../../atoms/ImageIcon';
|
|
4
|
+
import ThemeConfig from '../../theme';
|
|
5
|
+
import {AnnouncementMessage} from '../../components/chat-messages/useChatMessages';
|
|
6
|
+
|
|
7
|
+
export default function ChatAnnouncementView({
|
|
8
|
+
message,
|
|
9
|
+
announcement,
|
|
10
|
+
}: {
|
|
11
|
+
message: string;
|
|
12
|
+
announcement: AnnouncementMessage;
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<View style={style.announcementView}>
|
|
16
|
+
<ImageIcon
|
|
17
|
+
iconSize={20}
|
|
18
|
+
iconType="plain"
|
|
19
|
+
name="announcement"
|
|
20
|
+
tintColor={'#099DFD'}
|
|
21
|
+
/>
|
|
22
|
+
<View style={style.announcementMessage}>
|
|
23
|
+
<Text style={style.announcementMessageHeader}>
|
|
24
|
+
Message from host: {announcement.sender}
|
|
25
|
+
</Text>
|
|
26
|
+
<Text style={style.announcementMessageBody}>{message}</Text>
|
|
27
|
+
</View>
|
|
28
|
+
</View>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const style = StyleSheet.create({
|
|
33
|
+
announcementView: {
|
|
34
|
+
display: 'flex',
|
|
35
|
+
flexDirection: 'row',
|
|
36
|
+
alignItems: 'flex-start',
|
|
37
|
+
justifyContent: 'flex-start',
|
|
38
|
+
marginRight: 12,
|
|
39
|
+
marginLeft: 12,
|
|
40
|
+
marginBottom: 4,
|
|
41
|
+
marginTop: 16,
|
|
42
|
+
gap: 6,
|
|
43
|
+
},
|
|
44
|
+
announcementMessage: {
|
|
45
|
+
display: 'flex',
|
|
46
|
+
flexDirection: 'column',
|
|
47
|
+
gap: 2,
|
|
48
|
+
},
|
|
49
|
+
announcementMessageHeader: {
|
|
50
|
+
fontSize: ThemeConfig.FontSize.tiny,
|
|
51
|
+
fontStyle: 'normal',
|
|
52
|
+
fontFamily: ThemeConfig.FontFamily.sansPro,
|
|
53
|
+
color: '#099DFD',
|
|
54
|
+
fontWeight: '700',
|
|
55
|
+
lineHeight: 14,
|
|
56
|
+
},
|
|
57
|
+
announcementMessageBody: {
|
|
58
|
+
fontSize: ThemeConfig.FontSize.tiny,
|
|
59
|
+
fontStyle: 'italic',
|
|
60
|
+
fontFamily: ThemeConfig.FontFamily.sansPro,
|
|
61
|
+
color: '#099DFD',
|
|
62
|
+
fontWeight: '400',
|
|
63
|
+
lineHeight: 14,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
toolbarItemShareText,
|
|
26
26
|
} from '../../language/default-labels/videoCallScreenLabels';
|
|
27
27
|
import {useToolbarProps} from '../../atoms/ToolbarItem';
|
|
28
|
+
import {useBreakoutRoom} from '../../components/breakout-room/context/BreakoutRoomContext';
|
|
28
29
|
/**
|
|
29
30
|
* A component to start and stop screen sharing on web clients.
|
|
30
31
|
* Screen sharing is not yet implemented on mobile platforms.
|
|
@@ -53,6 +54,11 @@ const ScreenshareButton = (props: ScreenshareButtonProps) => {
|
|
|
53
54
|
const {setShowStartScreenSharePopup} = useVideoCall();
|
|
54
55
|
const screenShareButtonLabel = useString<boolean>(toolbarItemShareText);
|
|
55
56
|
const lstooltip = useString<boolean>(livestreamingShareTooltipText);
|
|
57
|
+
const {permissions} = useBreakoutRoom();
|
|
58
|
+
// In the main room (default case), permissions come from the main room state.
|
|
59
|
+
// If the user is in a breakout room, retrieve permissions from the breakout room instead.
|
|
60
|
+
const canScreenshareInBreakoutRoom = permissions.canScreenshare;
|
|
61
|
+
|
|
56
62
|
const onPress = () => {
|
|
57
63
|
if (isScreenshareActive) {
|
|
58
64
|
stopScreenshare();
|
|
@@ -105,6 +111,16 @@ const ScreenshareButton = (props: ScreenshareButtonProps) => {
|
|
|
105
111
|
iconButtonProps.disabled = true;
|
|
106
112
|
}
|
|
107
113
|
|
|
114
|
+
if (!canScreenshareInBreakoutRoom) {
|
|
115
|
+
iconButtonProps.iconProps = {
|
|
116
|
+
...iconButtonProps.iconProps,
|
|
117
|
+
tintColor: $config.SEMANTIC_NEUTRAL,
|
|
118
|
+
showWarningIcon: true,
|
|
119
|
+
};
|
|
120
|
+
iconButtonProps.toolTipMessage = 'cannot screenshare';
|
|
121
|
+
iconButtonProps.disabled = true;
|
|
122
|
+
}
|
|
123
|
+
|
|
108
124
|
return props?.render ? (
|
|
109
125
|
props.render(onPress, isScreenshareActive)
|
|
110
126
|
) : isToolbarMenuItem ? (
|
|
@@ -319,7 +319,7 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
|
|
|
319
319
|
'Trying to start native screenshare',
|
|
320
320
|
);
|
|
321
321
|
if (video) {
|
|
322
|
-
localMute(MUTE_LOCAL_TYPE.video);
|
|
322
|
+
await localMute(MUTE_LOCAL_TYPE.video);
|
|
323
323
|
}
|
|
324
324
|
try {
|
|
325
325
|
await engine.current.startScreenCapture({
|
|
@@ -14,12 +14,14 @@ import {
|
|
|
14
14
|
peoplePanelWaitingRoomRequestApprovalBtnTxt,
|
|
15
15
|
peoplePanelWaitingRoomRequestDenyBtnTxt,
|
|
16
16
|
} from '../../../src/language/default-labels/videoCallScreenLabels';
|
|
17
|
+
import ChatContext from '../../components/ChatContext';
|
|
17
18
|
|
|
18
19
|
const WaitingRoomButton = props => {
|
|
19
20
|
const {uid, screenUid, isAccept} = props;
|
|
20
21
|
const {approval} = useWaitingRoomAPI();
|
|
21
22
|
const localUid = useLocalUid();
|
|
22
23
|
const {dispatch} = useContext(DispatchContext);
|
|
24
|
+
const {syncUserState} = useContext(ChatContext);
|
|
23
25
|
const {waitingRoomRef} = useWaitingRoomContext();
|
|
24
26
|
const admintext = useString(peoplePanelWaitingRoomRequestApprovalBtnTxt)();
|
|
25
27
|
const denytext = useString(peoplePanelWaitingRoomRequestDenyBtnTxt)();
|
|
@@ -40,10 +42,11 @@ const WaitingRoomButton = props => {
|
|
|
40
42
|
Toast.hide();
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
dispatch({
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
45
|
+
// dispatch({
|
|
46
|
+
// type: 'UpdateRenderList',
|
|
47
|
+
// value: [uid, {isInWaitingRoom: false}],
|
|
48
|
+
// });
|
|
49
|
+
syncUserState(uid, {isInWaitingRoom: false});
|
|
47
50
|
|
|
48
51
|
if (waitingRoomRef.current) {
|
|
49
52
|
waitingRoomRef.current[uid] = approved ? 'APPROVED' : 'REJECTED';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {useRef, useCallback} from 'react';
|
|
2
|
+
|
|
3
|
+
export function useDebouncedCallback<T extends (...args: any[]) => void>(
|
|
4
|
+
fn: T,
|
|
5
|
+
delay: number,
|
|
6
|
+
): (...args: Parameters<T>) => void {
|
|
7
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
8
|
+
|
|
9
|
+
const debounced = useCallback(
|
|
10
|
+
(...args: Parameters<T>) => {
|
|
11
|
+
if (timeoutRef.current) {
|
|
12
|
+
clearTimeout(timeoutRef.current);
|
|
13
|
+
}
|
|
14
|
+
timeoutRef.current = setTimeout(() => fn(...args), delay);
|
|
15
|
+
},
|
|
16
|
+
[fn, delay],
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
return debounced;
|
|
20
|
+
}
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
import {PropsContext, DispatchContext} from '../../agora-rn-uikit';
|
|
10
10
|
import {useHistory} from '../components/Router';
|
|
11
11
|
import {stopForegroundService} from '../subComponents/LocalEndCall';
|
|
12
|
-
import RTMEngine from '../rtm/RTMEngine';
|
|
13
12
|
import {ENABLE_AUTH} from '../auth/config';
|
|
14
13
|
import {useAuth} from '../auth/AuthProvider';
|
|
15
14
|
import {useChatConfigure} from '../components/chat/chatConfigure';
|
|
@@ -69,7 +68,6 @@ const useEndCall = () => {
|
|
|
69
68
|
if ($config.CHAT) {
|
|
70
69
|
deleteChatUser();
|
|
71
70
|
}
|
|
72
|
-
RTMEngine.getInstance().engine.unsubscribe(rtcProps.channel);
|
|
73
71
|
if (!ENABLE_AUTH) {
|
|
74
72
|
// await authLogout();
|
|
75
73
|
await authLogin();
|
|
@@ -86,14 +86,16 @@ function useMuteToggleLocal() {
|
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
// Enable UI
|
|
89
|
+
const newAudioState =
|
|
90
|
+
localAudioState === ToggleState.enabled
|
|
91
|
+
? ToggleState.disabled
|
|
92
|
+
: ToggleState.enabled;
|
|
93
|
+
|
|
89
94
|
dispatch({
|
|
90
95
|
type: 'LocalMuteAudio',
|
|
91
|
-
value: [
|
|
92
|
-
localAudioState === ToggleState.enabled
|
|
93
|
-
? ToggleState.disabled
|
|
94
|
-
: ToggleState.enabled,
|
|
95
|
-
],
|
|
96
|
+
value: [newAudioState],
|
|
96
97
|
});
|
|
98
|
+
|
|
97
99
|
handleQueue();
|
|
98
100
|
} catch (e) {
|
|
99
101
|
dispatch({
|
|
@@ -152,14 +154,16 @@ function useMuteToggleLocal() {
|
|
|
152
154
|
);
|
|
153
155
|
}
|
|
154
156
|
// Enable UI
|
|
157
|
+
const newVideoState =
|
|
158
|
+
localVideoState === ToggleState.enabled
|
|
159
|
+
? ToggleState.disabled
|
|
160
|
+
: ToggleState.enabled;
|
|
161
|
+
|
|
155
162
|
dispatch({
|
|
156
163
|
type: 'LocalMuteVideo',
|
|
157
|
-
value: [
|
|
158
|
-
localVideoState === ToggleState.enabled
|
|
159
|
-
? ToggleState.disabled
|
|
160
|
-
: ToggleState.enabled,
|
|
161
|
-
],
|
|
164
|
+
value: [newVideoState],
|
|
162
165
|
});
|
|
166
|
+
|
|
163
167
|
handleQueue();
|
|
164
168
|
} catch (e) {
|
|
165
169
|
dispatch({
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import {ActionType, ContentStateInterface} from '../Contexts/RtcContext';
|
|
2
|
-
|
|
3
|
-
export default function Spotlight(
|
|
4
|
-
state: ContentStateInterface,
|
|
5
|
-
action: ActionType<'Spotlight'>,
|
|
6
|
-
) {
|
|
7
|
-
return {
|
|
8
|
-
...state,
|
|
9
|
-
spotlightUid: action?.value && action.value?.length ? action.value[0] : 0,
|
|
10
|
-
};
|
|
11
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import {ActionType, ContentStateInterface} from '../Contexts/RtcContext';
|
|
2
|
-
|
|
3
|
-
export default function UserBanned(
|
|
4
|
-
state: ContentStateInterface,
|
|
5
|
-
action: ActionType<'UserBanned'>,
|
|
6
|
-
) {
|
|
7
|
-
return {
|
|
8
|
-
...state,
|
|
9
|
-
isUserBaned: action?.value[0] || false,
|
|
10
|
-
};
|
|
11
|
-
}
|