agora-appbuilder-core 4.1.4-beta.7 → 4.1.4
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 +1 -1
- package/template/customization-api/typeDefinition.ts +4 -0
- package/template/defaultConfig.js +2 -2
- package/template/src/atoms/ActionMenu.tsx +3 -0
- package/template/src/atoms/UserActionMenuPreset.tsx +2 -0
- package/template/src/components/HostControlView.tsx +39 -3
- package/template/src/components/participants/UserActionMenuOptions.tsx +16 -8
- package/template/src/components/useUserActionMenu.tsx +38 -2
- package/template/src/subComponents/chat/ChatParticipants.tsx +5 -0
package/package.json
CHANGED
|
@@ -94,6 +94,10 @@ export interface VideoCallInterface extends BeforeAndAfterInterface {
|
|
|
94
94
|
title: string;
|
|
95
95
|
renderComponent?: React.ComponentType;
|
|
96
96
|
};
|
|
97
|
+
hostControls?: {
|
|
98
|
+
audioControl?: React.ComponentType;
|
|
99
|
+
videoControl?: React.ComponentType;
|
|
100
|
+
};
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
export type ComponentsInterface = {
|
|
@@ -77,8 +77,8 @@ const DefaultConfig = {
|
|
|
77
77
|
CHAT_ORG_NAME: '',
|
|
78
78
|
CHAT_APP_NAME: '',
|
|
79
79
|
CHAT_URL: '',
|
|
80
|
-
CLI_VERSION: '3.1.4
|
|
81
|
-
CORE_VERSION: '4.1.4
|
|
80
|
+
CLI_VERSION: '3.1.4',
|
|
81
|
+
CORE_VERSION: '4.1.4',
|
|
82
82
|
DISABLE_LANDSCAPE_MODE: false,
|
|
83
83
|
STT_AUTO_START: false,
|
|
84
84
|
CLOUD_RECORDING_AUTO_START: false,
|
|
@@ -49,6 +49,7 @@ export interface ActionMenuItem {
|
|
|
49
49
|
disabled?: boolean;
|
|
50
50
|
iconSize?: number;
|
|
51
51
|
hide?: ToolbarItemHide;
|
|
52
|
+
type?: string;
|
|
52
53
|
}
|
|
53
54
|
export interface ActionMenuProps {
|
|
54
55
|
from: string;
|
|
@@ -200,6 +201,7 @@ const ActionMenu = (props: ActionMenuProps) => {
|
|
|
200
201
|
onHoverContent = undefined,
|
|
201
202
|
iconSize = 20,
|
|
202
203
|
titleStyle = {},
|
|
204
|
+
type = '',
|
|
203
205
|
} = item;
|
|
204
206
|
return (
|
|
205
207
|
<PlatformWrapper key={props.from + '_' + title + index}>
|
|
@@ -232,6 +234,7 @@ const ActionMenu = (props: ActionMenuProps) => {
|
|
|
232
234
|
closeActionMenu={closeActionMenu}
|
|
233
235
|
targetUid={uid}
|
|
234
236
|
hostMeetingId={roomId?.host}
|
|
237
|
+
targetUidType={type}
|
|
235
238
|
/>
|
|
236
239
|
</TouchableOpacity>
|
|
237
240
|
) : (
|
|
@@ -57,6 +57,7 @@ export type AttendeeRemoteActionKeys = 'view-in-large' | 'message-privately';
|
|
|
57
57
|
export interface UserActionMenuDefaultItem {
|
|
58
58
|
hide?: boolean;
|
|
59
59
|
order?: number;
|
|
60
|
+
disabled?: boolean;
|
|
60
61
|
onPress?: () => void; // replace existing logic
|
|
61
62
|
onAction?: (uid?: UidType, hostMeetingId?: string) => void; // add additional logic
|
|
62
63
|
visibility?: ActionVisibility[]; // to whom custom action item should be visible , build in actions menu is already handled
|
|
@@ -64,6 +65,7 @@ export interface UserActionMenuDefaultItem {
|
|
|
64
65
|
closeActionMenu: () => void;
|
|
65
66
|
targetUid: UidType;
|
|
66
67
|
hostMeetingId?: string;
|
|
68
|
+
targetUidType: string;
|
|
67
69
|
}>; // to override default component or add new
|
|
68
70
|
}
|
|
69
71
|
export type UserActionDefaultItemsConfig = {
|
|
@@ -16,12 +16,13 @@ import useRemoteMute, {MUTE_REMOTE_TYPE} from '../utils/useRemoteMute';
|
|
|
16
16
|
import TertiaryButton from '../atoms/TertiaryButton';
|
|
17
17
|
import Spacer from '../atoms/Spacer';
|
|
18
18
|
import RemoteMutePopup from '../subComponents/RemoteMutePopup';
|
|
19
|
-
import {calculatePosition} from '../utils/common';
|
|
19
|
+
import {calculatePosition, isValidReactComponent} from '../utils/common';
|
|
20
20
|
import {
|
|
21
21
|
I18nMuteType,
|
|
22
22
|
peoplePanelMuteAllMicBtnText,
|
|
23
23
|
peoplePanelTurnoffAllCameraBtnText,
|
|
24
24
|
} from '../language/default-labels/videoCallScreenLabels';
|
|
25
|
+
import {useCustomization} from 'customization-implementation';
|
|
25
26
|
|
|
26
27
|
export interface MuteAllAudioButtonProps {
|
|
27
28
|
render?: (onPress: () => void) => JSX.Element;
|
|
@@ -145,17 +146,52 @@ export const MuteAllVideoButton = (props: MuteAllVideoButtonProps) => {
|
|
|
145
146
|
};
|
|
146
147
|
|
|
147
148
|
const HostControlView = () => {
|
|
149
|
+
const {AudioControlComponent, VideoControlComponent} = useCustomization(
|
|
150
|
+
data => {
|
|
151
|
+
let components: {
|
|
152
|
+
AudioControlComponent: React.ComponentType;
|
|
153
|
+
VideoControlComponent: React.ComponentType;
|
|
154
|
+
} = {
|
|
155
|
+
AudioControlComponent:
|
|
156
|
+
MuteAllAudioButton as React.ComponentType<MuteAllAudioButtonProps>,
|
|
157
|
+
VideoControlComponent:
|
|
158
|
+
MuteAllVideoButton as React.ComponentType<MuteAllVideoButtonProps>,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
if (
|
|
162
|
+
data?.components?.videoCall?.hostControls?.audioControl &&
|
|
163
|
+
isValidReactComponent(
|
|
164
|
+
data?.components?.videoCall?.hostControls?.audioControl,
|
|
165
|
+
)
|
|
166
|
+
) {
|
|
167
|
+
components.AudioControlComponent =
|
|
168
|
+
data?.components?.videoCall?.hostControls?.audioControl;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (
|
|
172
|
+
data?.components?.videoCall?.hostControls?.videoControl &&
|
|
173
|
+
isValidReactComponent(
|
|
174
|
+
data?.components?.videoCall?.hostControls?.videoControl,
|
|
175
|
+
)
|
|
176
|
+
) {
|
|
177
|
+
components.VideoControlComponent =
|
|
178
|
+
data?.components?.videoCall?.hostControls?.videoControl;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return components;
|
|
182
|
+
},
|
|
183
|
+
);
|
|
148
184
|
return (
|
|
149
185
|
// <View style={style.container}>
|
|
150
186
|
<>
|
|
151
187
|
{!$config.AUDIO_ROOM && (
|
|
152
188
|
<View style={{display: 'flex', flex: 1}}>
|
|
153
|
-
<
|
|
189
|
+
<VideoControlComponent />
|
|
154
190
|
</View>
|
|
155
191
|
)}
|
|
156
192
|
<Spacer horizontal size={16} />
|
|
157
193
|
<View style={{display: 'flex', flex: 1}}>
|
|
158
|
-
<
|
|
194
|
+
<AudioControlComponent />
|
|
159
195
|
</View>
|
|
160
196
|
</>
|
|
161
197
|
// </View>
|
|
@@ -206,8 +206,8 @@ export default function UserActionMenuOptionsOptions(
|
|
|
206
206
|
if (!viewInLargeConfig.hide && !isPinned) {
|
|
207
207
|
items.push({
|
|
208
208
|
key: viewInLargeKey,
|
|
209
|
-
disabled: isOnlyOneActive,
|
|
210
|
-
order: viewInLargeConfig.order ??
|
|
209
|
+
disabled: viewInLargeConfig.disabled ?? isOnlyOneActive,
|
|
210
|
+
order: viewInLargeConfig.order ?? 0,
|
|
211
211
|
icon: isPinned ? 'unpin-outlined' : 'pin-outlined',
|
|
212
212
|
onHoverIcon: isPinned ? 'unpin-filled' : 'pin-filled',
|
|
213
213
|
iconColor: $config.SECONDARY_ACTION_COLOR,
|
|
@@ -268,8 +268,8 @@ export default function UserActionMenuOptionsOptions(
|
|
|
268
268
|
if (!pinToTopConfig.hide) {
|
|
269
269
|
items.push({
|
|
270
270
|
key: pinToTopKey,
|
|
271
|
-
disabled: isOnlyOneActive,
|
|
272
|
-
order: pinToTopConfig.order ??
|
|
271
|
+
disabled: pinToTopConfig.disabled ?? isOnlyOneActive,
|
|
272
|
+
order: pinToTopConfig.order ?? 1,
|
|
273
273
|
icon: isPinnedToTop ? 'unpin-outlined' : 'pin-outlined',
|
|
274
274
|
onHoverIcon: isPinnedToTop ? 'unpin-filled' : 'pin-filled',
|
|
275
275
|
iconColor: $config.SECONDARY_ACTION_COLOR,
|
|
@@ -359,6 +359,7 @@ export default function UserActionMenuOptionsOptions(
|
|
|
359
359
|
if (!messageConfig.hide && $config.CHAT) {
|
|
360
360
|
items.push({
|
|
361
361
|
key: messageKey,
|
|
362
|
+
disabled: messageConfig.disable ?? false,
|
|
362
363
|
order: messageConfig.order ?? 2,
|
|
363
364
|
icon: 'chat-outlined',
|
|
364
365
|
onHoverIcon: 'chat-filled',
|
|
@@ -430,6 +431,7 @@ export default function UserActionMenuOptionsOptions(
|
|
|
430
431
|
if (!muteAudioConfig.hide) {
|
|
431
432
|
items.push({
|
|
432
433
|
key: muteAudioKey,
|
|
434
|
+
disabled: muteAudioConfig.disabled ?? false,
|
|
433
435
|
order: muteAudioConfig.order ?? 3,
|
|
434
436
|
icon: isMuted ? 'mic-off-outlined' : 'mic-on-outlined',
|
|
435
437
|
onHoverIcon: isMuted ? 'mic-off-filled' : 'mic-on-filled',
|
|
@@ -456,6 +458,7 @@ export default function UserActionMenuOptionsOptions(
|
|
|
456
458
|
if (!$config.AUDIO_ROOM && !muteVideoConfig.hide) {
|
|
457
459
|
items.push({
|
|
458
460
|
key: muteVideoKey,
|
|
461
|
+
disabled: muteVideoConfig.disabled ?? false,
|
|
459
462
|
order: muteVideoConfig.order ?? 4,
|
|
460
463
|
icon: isVideoMuted ? 'video-off-outlined' : 'video-on-outlined',
|
|
461
464
|
onHoverIcon: isVideoMuted
|
|
@@ -544,7 +547,8 @@ export default function UserActionMenuOptionsOptions(
|
|
|
544
547
|
if (!removeConfig.hide) {
|
|
545
548
|
items.push({
|
|
546
549
|
key: removeKey,
|
|
547
|
-
|
|
550
|
+
disabled: removeConfig.disabled ?? false,
|
|
551
|
+
order: removeConfig.order ?? 5,
|
|
548
552
|
icon: 'remove-meeting',
|
|
549
553
|
iconColor: $config.SEMANTIC_ERROR,
|
|
550
554
|
textColor: $config.SEMANTIC_ERROR,
|
|
@@ -586,7 +590,8 @@ export default function UserActionMenuOptionsOptions(
|
|
|
586
590
|
) {
|
|
587
591
|
items.push({
|
|
588
592
|
key: changeNameKey,
|
|
589
|
-
|
|
593
|
+
disabled: changeNameConfig.disabled ?? false,
|
|
594
|
+
order: changeNameConfig.order ?? 6,
|
|
590
595
|
icon: 'pencil-outlined',
|
|
591
596
|
onHoverIcon: 'pencil-filled',
|
|
592
597
|
iconColor: $config.SECONDARY_ACTION_COLOR,
|
|
@@ -635,7 +640,8 @@ export default function UserActionMenuOptionsOptions(
|
|
|
635
640
|
) {
|
|
636
641
|
items.push({
|
|
637
642
|
key: removeScreenshareKey,
|
|
638
|
-
|
|
643
|
+
disabled: removeScreenshareConfig.disabled ?? false,
|
|
644
|
+
order: removeScreenshareConfig.order ?? 7,
|
|
639
645
|
icon: 'remove-meeting',
|
|
640
646
|
iconColor: $config.SEMANTIC_ERROR,
|
|
641
647
|
textColor: $config.SEMANTIC_ERROR,
|
|
@@ -679,12 +685,14 @@ export default function UserActionMenuOptionsOptions(
|
|
|
679
685
|
}
|
|
680
686
|
return {
|
|
681
687
|
key,
|
|
682
|
-
order: config.order ??
|
|
688
|
+
order: config.order ?? 8,
|
|
683
689
|
component: config.component,
|
|
684
690
|
closeActionMenu: () => {
|
|
685
691
|
setActionMenuVisible(false);
|
|
686
692
|
},
|
|
687
693
|
uid: user.uid,
|
|
694
|
+
disabled: config.disabled ?? false,
|
|
695
|
+
type: user.type,
|
|
688
696
|
};
|
|
689
697
|
});
|
|
690
698
|
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import React, {createContext, useContext, useState, useEffect} from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
UidType,
|
|
4
|
+
UserActionMenuItemsConfig,
|
|
5
|
+
DispatchContext,
|
|
6
|
+
useLayout,
|
|
7
|
+
} from 'customization-api';
|
|
8
|
+
import {
|
|
9
|
+
getGridLayoutName,
|
|
10
|
+
getPinnedLayoutName,
|
|
11
|
+
} from '../pages/video-call/DefaultLayouts';
|
|
3
12
|
|
|
4
13
|
interface UserActionMenuContextType {
|
|
5
14
|
userActionMenuItems: UserActionMenuItemsConfig;
|
|
6
15
|
updateUserActionMenuItems: React.Dispatch<
|
|
7
16
|
React.SetStateAction<UserActionMenuItemsConfig>
|
|
8
17
|
>;
|
|
18
|
+
pinForEveryone: (uid: UidType) => void;
|
|
19
|
+
unPinForEveryone: () => void;
|
|
9
20
|
}
|
|
10
21
|
|
|
11
22
|
const UserActionMenuContext = createContext<UserActionMenuContextType>({
|
|
12
23
|
userActionMenuItems: {},
|
|
13
24
|
updateUserActionMenuItems: () => {},
|
|
25
|
+
pinForEveryone: () => {},
|
|
26
|
+
unPinForEveryone: () => {},
|
|
14
27
|
});
|
|
15
28
|
|
|
16
29
|
export const UserActionMenuProvider: React.FC<{children: React.ReactNode}> = ({
|
|
@@ -18,10 +31,33 @@ export const UserActionMenuProvider: React.FC<{children: React.ReactNode}> = ({
|
|
|
18
31
|
}) => {
|
|
19
32
|
const [userActionMenuItems, updateUserActionMenuItems] =
|
|
20
33
|
useState<UserActionMenuItemsConfig>({});
|
|
34
|
+
const {dispatch} = useContext(DispatchContext);
|
|
35
|
+
const {setLayout} = useLayout();
|
|
36
|
+
|
|
37
|
+
const pinForEveryone = (uid: UidType) => {
|
|
38
|
+
dispatch({
|
|
39
|
+
type: 'UserPin',
|
|
40
|
+
value: [uid],
|
|
41
|
+
});
|
|
42
|
+
setLayout(getPinnedLayoutName());
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const unPinForEveryone = () => {
|
|
46
|
+
dispatch({
|
|
47
|
+
type: 'UserPin',
|
|
48
|
+
value: [0],
|
|
49
|
+
});
|
|
50
|
+
setLayout(getGridLayoutName());
|
|
51
|
+
};
|
|
21
52
|
|
|
22
53
|
return (
|
|
23
54
|
<UserActionMenuContext.Provider
|
|
24
|
-
value={{
|
|
55
|
+
value={{
|
|
56
|
+
userActionMenuItems,
|
|
57
|
+
updateUserActionMenuItems,
|
|
58
|
+
pinForEveryone,
|
|
59
|
+
unPinForEveryone,
|
|
60
|
+
}}>
|
|
25
61
|
{children}
|
|
26
62
|
</UserActionMenuContext.Provider>
|
|
27
63
|
);
|
|
@@ -80,6 +80,11 @@ const ChatParticipants = (props: any) => {
|
|
|
80
80
|
} else {
|
|
81
81
|
const userId = i;
|
|
82
82
|
const userInfo = defaultContent[userId];
|
|
83
|
+
|
|
84
|
+
// if user is not in active uids, then skip it
|
|
85
|
+
if (!activeUids.includes(userId)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
83
88
|
//video meeting with waiting room
|
|
84
89
|
if (
|
|
85
90
|
$config.ENABLE_WAITING_ROOM &&
|