agora-appbuilder-core 4.1.21 → 4.1.22-beta.2
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/bridge/rtm/web/index.ts +31 -22
- package/template/customization-api/ai-agent.ts +4 -0
- package/template/customization-api/atoms.ts +2 -0
- package/template/customization-api/customEvents.ts +4 -1
- package/template/customization-api/index.ts +1 -0
- package/template/customization-api/typeDefinition.ts +6 -1
- package/template/defaultConfig.js +2 -2
- package/template/src/components/CustomSidePanel.tsx +13 -13
- package/template/src/components/RTMConfigure.tsx +14 -0
- package/template/src/components/participants/UserActionMenuOptions.tsx +28 -1
- package/template/src/pages/Create.tsx +31 -19
- package/template/src/pages/video-call/ActionSheet.native.tsx +2 -0
- package/template/src/pages/video-call/ActionSheet.tsx +2 -0
- package/template/src/pages/video-call/ActionSheetHandle.tsx +1 -0
- package/template/src/pages/video-call/SidePanelHeader.tsx +3 -1
- package/template/src/pages/video-call/VideoCallScreen.tsx +3 -0
- package/template/src/pages/video-call/VideoRenderer.tsx +4 -0
- package/template/src/subComponents/SidePanelHeader.tsx +16 -2
package/package.json
CHANGED
|
@@ -72,12 +72,24 @@ export class RTMWebClient {
|
|
|
72
72
|
private client: RTMClient;
|
|
73
73
|
private appId: string;
|
|
74
74
|
private userId: string;
|
|
75
|
-
private eventsMap = new Map<keyof NativeRTMClientEventMap, CallbackType
|
|
76
|
-
[
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
private eventsMap = new Map<keyof NativeRTMClientEventMap, Set<CallbackType>>(
|
|
76
|
+
[
|
|
77
|
+
['linkState', new Set()],
|
|
78
|
+
['storage', new Set()],
|
|
79
|
+
['presence', new Set()],
|
|
80
|
+
['message', new Set()],
|
|
81
|
+
],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
private emitEvent(event: keyof NativeRTMClientEventMap, data: any) {
|
|
85
|
+
const listeners = this.eventsMap.get(event);
|
|
86
|
+
|
|
87
|
+
if (!listeners) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
listeners.forEach(listener => listener(data));
|
|
92
|
+
}
|
|
81
93
|
|
|
82
94
|
constructor(appId: string, userId: string) {
|
|
83
95
|
this.appId = appId;
|
|
@@ -97,7 +109,7 @@ export class RTMWebClient {
|
|
|
97
109
|
nativeLinkStateMapping.IDLE,
|
|
98
110
|
reasonCode: linkStatusReasonCodeMapping[data.reasonCode] || 0,
|
|
99
111
|
};
|
|
100
|
-
|
|
112
|
+
this.emitEvent('linkState', nativeState);
|
|
101
113
|
});
|
|
102
114
|
|
|
103
115
|
this.client.addEventListener('storage', data => {
|
|
@@ -108,7 +120,7 @@ export class RTMWebClient {
|
|
|
108
120
|
data: convertWebToNativeMetadata(data.data),
|
|
109
121
|
timestamp: data.timestamp,
|
|
110
122
|
};
|
|
111
|
-
|
|
123
|
+
this.emitEvent('storage', nativeStorageEvent);
|
|
112
124
|
});
|
|
113
125
|
|
|
114
126
|
this.client.addEventListener('presence', data => {
|
|
@@ -119,7 +131,7 @@ export class RTMWebClient {
|
|
|
119
131
|
publisher: data.publisher,
|
|
120
132
|
timestamp: data.timestamp,
|
|
121
133
|
};
|
|
122
|
-
|
|
134
|
+
this.emitEvent('presence', nativePresenceEvent);
|
|
123
135
|
});
|
|
124
136
|
|
|
125
137
|
this.client.addEventListener('message', data => {
|
|
@@ -129,7 +141,7 @@ export class RTMWebClient {
|
|
|
129
141
|
messageType: nativeMessageEventTypeMapping[data.messageType],
|
|
130
142
|
message: `${data.message}`,
|
|
131
143
|
};
|
|
132
|
-
|
|
144
|
+
this.emitEvent('message', nativeMessageEvent);
|
|
133
145
|
});
|
|
134
146
|
} catch (error) {
|
|
135
147
|
const contextError = new Error(
|
|
@@ -396,21 +408,18 @@ export class RTMWebClient {
|
|
|
396
408
|
listener: (event: any) => void,
|
|
397
409
|
) {
|
|
398
410
|
if (this.client) {
|
|
399
|
-
//
|
|
400
|
-
|
|
411
|
+
// Web SDK listeners are fixed in the constructor; keep app-level
|
|
412
|
+
// subscribers multiplexed here.
|
|
413
|
+
this.eventsMap.get(event)?.add(listener as CallbackType);
|
|
401
414
|
}
|
|
402
415
|
}
|
|
403
416
|
|
|
404
417
|
removeEventListener(
|
|
405
418
|
event: keyof NativeRTMClientEventMap,
|
|
406
|
-
|
|
419
|
+
listener: (event: any) => void,
|
|
407
420
|
) {
|
|
408
421
|
if (this.client && this.eventsMap.has(event)) {
|
|
409
|
-
|
|
410
|
-
if (prevListener) {
|
|
411
|
-
this.client.removeEventListener(event, prevListener);
|
|
412
|
-
}
|
|
413
|
-
this.eventsMap.set(event, () => null); // reset to no-op
|
|
422
|
+
this.eventsMap.get(event)?.delete(listener as CallbackType);
|
|
414
423
|
}
|
|
415
424
|
}
|
|
416
425
|
|
|
@@ -473,10 +482,10 @@ export class RTMWebClient {
|
|
|
473
482
|
|
|
474
483
|
removeAllListeners() {
|
|
475
484
|
this.eventsMap = new Map([
|
|
476
|
-
['linkState', ()
|
|
477
|
-
['storage', ()
|
|
478
|
-
['presence', ()
|
|
479
|
-
['message', ()
|
|
485
|
+
['linkState', new Set()],
|
|
486
|
+
['storage', new Set()],
|
|
487
|
+
['presence', new Set()],
|
|
488
|
+
['message', new Set()],
|
|
480
489
|
]);
|
|
481
490
|
return this.client.removeAllListeners();
|
|
482
491
|
}
|
|
@@ -8,3 +8,5 @@ export {default as TertiaryButton} from '../src/atoms/TertiaryButton';
|
|
|
8
8
|
export {default as ActionMenu} from '../src/atoms/ActionMenu';
|
|
9
9
|
export {default as IconButton} from '../src/atoms/IconButton';
|
|
10
10
|
export {default as Dropdown} from '../src/atoms/Dropdown';
|
|
11
|
+
export {default as Popup} from '../src/atoms/Popup';
|
|
12
|
+
export {default as Tooltip} from '../src/atoms/Tooltip';
|
|
@@ -5,10 +5,13 @@ import {
|
|
|
5
5
|
PersistanceLevel,
|
|
6
6
|
EventCallback,
|
|
7
7
|
} from '../src/rtm-events-api';
|
|
8
|
+
import LocalEventEmitter, {
|
|
9
|
+
LocalEventsEnum,
|
|
10
|
+
} from '../src/rtm-events-api/LocalEvents';
|
|
8
11
|
|
|
9
12
|
// 2. Initialize with source "fpe"
|
|
10
13
|
const customEvents = new Events(EventSource.fpe);
|
|
11
14
|
|
|
12
15
|
// 3. export
|
|
13
|
-
export {customEvents, PersistanceLevel};
|
|
16
|
+
export {customEvents, PersistanceLevel, LocalEventEmitter, LocalEventsEnum};
|
|
14
17
|
export type {EventCallback};
|
|
@@ -53,6 +53,7 @@ export interface SidePanelItem {
|
|
|
53
53
|
name: string;
|
|
54
54
|
title: string;
|
|
55
55
|
component: React.ComponentType;
|
|
56
|
+
headerRightSlot?: React.ReactNode;
|
|
56
57
|
onClose?: () => void;
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -74,6 +75,10 @@ export type CustomLogger = (
|
|
|
74
75
|
export interface CustomAgentInterfaceProps {
|
|
75
76
|
connectionState: AIAgentState;
|
|
76
77
|
}
|
|
78
|
+
export interface CreateInterface extends BeforeAndAfterInterface {
|
|
79
|
+
headerRightSlot?: React.ComponentType;
|
|
80
|
+
}
|
|
81
|
+
|
|
77
82
|
export interface VideoCallInterface extends BeforeAndAfterInterface {
|
|
78
83
|
// commented for v1 release
|
|
79
84
|
topToolBar?: ToolbarType;
|
|
@@ -109,7 +114,7 @@ export type ComponentsInterface = {
|
|
|
109
114
|
precall?: PreCallInterface;
|
|
110
115
|
preferenceWrapper?: React.ComponentType;
|
|
111
116
|
//precall?: React.ComponentType;
|
|
112
|
-
create?: React.ComponentType;
|
|
117
|
+
create?: React.ComponentType | CreateInterface;
|
|
113
118
|
//share?: React.ComponentType;
|
|
114
119
|
//join?: React.ComponentType;
|
|
115
120
|
videoCall?: VideoCallInterface;
|
|
@@ -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.
|
|
81
|
-
CORE_VERSION: "4.1.
|
|
80
|
+
CLI_VERSION: "3.1.22-beta.2",
|
|
81
|
+
CORE_VERSION: "4.1.22-beta.2",
|
|
82
82
|
DISABLE_LANDSCAPE_MODE: false,
|
|
83
83
|
STT_AUTO_START: false,
|
|
84
84
|
CLOUD_RECORDING_AUTO_START: false,
|
|
@@ -10,23 +10,18 @@
|
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
import React from 'react';
|
|
13
|
-
import {View,
|
|
13
|
+
import {View, StyleSheet, ScrollView} from 'react-native';
|
|
14
14
|
import {isMobileUA, isWebInternal, useIsSmall} from '../utils/common';
|
|
15
15
|
import CommonStyles from './CommonStyles';
|
|
16
|
-
import SidePanelHeader, {
|
|
17
|
-
SidePanelStyles,
|
|
18
|
-
} from '../subComponents/SidePanelHeader';
|
|
19
|
-
import {useLayout} from '../utils/useLayout';
|
|
20
|
-
import {getGridLayoutName} from '../pages/video-call/DefaultLayouts';
|
|
21
16
|
import useCaptionWidth from '../subComponents/caption/useCaptionWidth';
|
|
22
|
-
import {useSidePanel} from '../utils/useSidePanel';
|
|
23
|
-
import {SidePanelType} from '../subComponents/SidePanelEnum';
|
|
24
17
|
import {CustomSidePanelHeader} from '../pages/video-call/SidePanelHeader';
|
|
25
|
-
|
|
18
|
+
import {useLayout} from '../utils/useLayout';
|
|
19
|
+
import {getGridLayoutName} from '../pages/video-call/DefaultLayouts';
|
|
26
20
|
export interface CustomSidePanelViewInterface {
|
|
27
21
|
name: string;
|
|
28
22
|
title?: string;
|
|
29
23
|
content: React.ComponentType;
|
|
24
|
+
headerRightSlot?: React.ReactNode;
|
|
30
25
|
onClose?: () => void;
|
|
31
26
|
showHeader?: boolean;
|
|
32
27
|
}
|
|
@@ -37,12 +32,12 @@ const CustomSidePanelView = (props: CustomSidePanelViewInterface) => {
|
|
|
37
32
|
showHeader = true,
|
|
38
33
|
name,
|
|
39
34
|
title,
|
|
35
|
+
headerRightSlot,
|
|
40
36
|
onClose,
|
|
41
37
|
} = props;
|
|
42
|
-
const {currentLayout} = useLayout();
|
|
43
38
|
const {transcriptHeight} = useCaptionWidth();
|
|
44
|
-
const {setSidePanel} = useSidePanel();
|
|
45
39
|
const isSmall = useIsSmall();
|
|
40
|
+
const {currentLayout} = useLayout();
|
|
46
41
|
|
|
47
42
|
return (
|
|
48
43
|
<View
|
|
@@ -57,13 +52,18 @@ const CustomSidePanelView = (props: CustomSidePanelViewInterface) => {
|
|
|
57
52
|
: // desktop maximized
|
|
58
53
|
CommonStyles.sidePanelContainerWeb,
|
|
59
54
|
isWebInternal() && !isSmall() && currentLayout === getGridLayoutName()
|
|
60
|
-
? {
|
|
55
|
+
? {marginTop: 4}
|
|
61
56
|
: {},
|
|
62
57
|
//@ts-ignore
|
|
63
58
|
transcriptHeight && !isMobileUA() && {height: transcriptHeight},
|
|
64
59
|
]}>
|
|
65
60
|
{showHeader && (
|
|
66
|
-
<CustomSidePanelHeader
|
|
61
|
+
<CustomSidePanelHeader
|
|
62
|
+
name={name}
|
|
63
|
+
title={title}
|
|
64
|
+
headerRightSlot={headerRightSlot}
|
|
65
|
+
onClose={onClose}
|
|
66
|
+
/>
|
|
67
67
|
)}
|
|
68
68
|
<ScrollView contentContainerStyle={[style.bodyContainer]}>
|
|
69
69
|
{CustomSidePanelContent ? <CustomSidePanelContent /> : <></>}
|
|
@@ -950,6 +950,20 @@ const RtmConfigure = (props: any) => {
|
|
|
950
950
|
}
|
|
951
951
|
}
|
|
952
952
|
|
|
953
|
+
if (
|
|
954
|
+
typeof evt !== 'string' ||
|
|
955
|
+
evt.trim() === '' ||
|
|
956
|
+
typeof value === 'undefined'
|
|
957
|
+
) {
|
|
958
|
+
logger.debug(
|
|
959
|
+
LogSource.Events,
|
|
960
|
+
'CUSTOM_EVENTS',
|
|
961
|
+
'Ignoring RTM payload: not an AppBuilder custom-event envelope',
|
|
962
|
+
{data, sender, ts},
|
|
963
|
+
);
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
|
|
953
967
|
try {
|
|
954
968
|
let parsedValue;
|
|
955
969
|
try {
|
|
@@ -87,6 +87,7 @@ interface UserActionMenuOptionsOptionsProps {
|
|
|
87
87
|
spotlightUid?: UidType;
|
|
88
88
|
setSpotlightUid?: (uid: UidType) => void;
|
|
89
89
|
items?: UserActionMenuItemsConfig;
|
|
90
|
+
extraMenuItems?: ActionMenuItem[];
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
export default function UserActionMenuOptionsOptions(
|
|
@@ -102,7 +103,13 @@ export default function UserActionMenuOptionsOptions(
|
|
|
102
103
|
useState(false);
|
|
103
104
|
const [actionMenuitems, setActionMenuitems] = useState<ActionMenuItem[]>([]);
|
|
104
105
|
const {setSidePanel} = useSidePanel();
|
|
105
|
-
const {
|
|
106
|
+
const {
|
|
107
|
+
user,
|
|
108
|
+
actionMenuVisible,
|
|
109
|
+
setActionMenuVisible,
|
|
110
|
+
spotlightUid,
|
|
111
|
+
extraMenuItems,
|
|
112
|
+
} = props;
|
|
106
113
|
const {currentLayout} = useLayout();
|
|
107
114
|
const {pinnedUid, activeUids, customContent, secondaryPinnedUid} =
|
|
108
115
|
useContent();
|
|
@@ -716,6 +723,24 @@ export default function UserActionMenuOptionsOptions(
|
|
|
716
723
|
items.push(...customItems);
|
|
717
724
|
}
|
|
718
725
|
|
|
726
|
+
if (extraMenuItems?.length) {
|
|
727
|
+
items.push(
|
|
728
|
+
...extraMenuItems.map(item => ({
|
|
729
|
+
...item,
|
|
730
|
+
closeActionMenu: () => {
|
|
731
|
+
item.closeActionMenu?.();
|
|
732
|
+
setActionMenuVisible(false);
|
|
733
|
+
},
|
|
734
|
+
onPress: item.onPress
|
|
735
|
+
? () => {
|
|
736
|
+
item.onPress?.();
|
|
737
|
+
setActionMenuVisible(false);
|
|
738
|
+
}
|
|
739
|
+
: item.onPress,
|
|
740
|
+
})),
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
|
|
719
744
|
items.sort((a, b) => (a.order ?? 999) - (b.order ?? 999));
|
|
720
745
|
|
|
721
746
|
setActionMenuitems(items);
|
|
@@ -729,6 +754,8 @@ export default function UserActionMenuOptionsOptions(
|
|
|
729
754
|
secondaryPinnedUid,
|
|
730
755
|
currentLayout,
|
|
731
756
|
spotlightUid,
|
|
757
|
+
extraMenuItems,
|
|
758
|
+
setActionMenuVisible,
|
|
732
759
|
]);
|
|
733
760
|
|
|
734
761
|
const {width: globalWidth, height: globalHeight} = useWindowDimensions();
|
|
@@ -29,7 +29,6 @@ import {useCustomization} from 'customization-implementation';
|
|
|
29
29
|
import {useString} from '../utils/useString';
|
|
30
30
|
import useCreateRoom from '../utils/useCreateRoom';
|
|
31
31
|
import {CreateProvider} from './create/useCreate';
|
|
32
|
-
import useJoinRoom from '../utils/useJoinRoom';
|
|
33
32
|
import {
|
|
34
33
|
RoomInfoDefaultValue,
|
|
35
34
|
useRoomInfo,
|
|
@@ -39,12 +38,10 @@ import Toggle from '../atoms/Toggle';
|
|
|
39
38
|
import Card from '../atoms/Card';
|
|
40
39
|
import Spacer from '../atoms/Spacer';
|
|
41
40
|
import LinkButton from '../atoms/LinkButton';
|
|
42
|
-
import StorageContext from '../components/StorageContext';
|
|
43
41
|
import ThemeConfig from '../theme';
|
|
44
42
|
import Tooltip from '../atoms/Tooltip';
|
|
45
43
|
import ImageIcon from '../atoms/ImageIcon';
|
|
46
44
|
import hexadecimalTransparency from '../utils/hexadecimalTransparency';
|
|
47
|
-
import {randomNameGenerator} from '../utils';
|
|
48
45
|
import {useSetRoomInfo} from '../components/room-info/useSetRoomInfo';
|
|
49
46
|
import IDPLogoutComponent from '../auth/IDPLogoutComponent';
|
|
50
47
|
import isSDK from '../utils/isSDK';
|
|
@@ -67,25 +64,35 @@ import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
|
67
64
|
import SDKEvents from '../utils/SdkEvents';
|
|
68
65
|
|
|
69
66
|
const Create = () => {
|
|
70
|
-
const {CreateComponent} = useCustomization(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
typeof data?.components?.create !== 'object'
|
|
77
|
-
) {
|
|
67
|
+
const {CreateComponent, CreateHeaderRightSlotComponent} = useCustomization(
|
|
68
|
+
data => {
|
|
69
|
+
let components: {
|
|
70
|
+
CreateComponent?: React.ElementType;
|
|
71
|
+
CreateHeaderRightSlotComponent?: React.ElementType;
|
|
72
|
+
} = {};
|
|
78
73
|
if (
|
|
79
74
|
data?.components?.create &&
|
|
80
|
-
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
typeof data?.components?.create !== 'object'
|
|
76
|
+
) {
|
|
77
|
+
if (
|
|
78
|
+
data?.components?.create &&
|
|
79
|
+
isValidReactComponent(data?.components?.create)
|
|
80
|
+
)
|
|
81
|
+
components.CreateComponent = data?.components?.create;
|
|
82
|
+
}
|
|
83
|
+
if (
|
|
84
|
+
data?.components?.create &&
|
|
85
|
+
typeof data?.components?.create === 'object' &&
|
|
86
|
+
data?.components?.create?.headerRightSlot &&
|
|
87
|
+
isValidReactComponent(data?.components?.create?.headerRightSlot)
|
|
88
|
+
) {
|
|
89
|
+
components.CreateHeaderRightSlotComponent =
|
|
90
|
+
data?.components?.create?.headerRightSlot;
|
|
91
|
+
}
|
|
92
|
+
return components;
|
|
93
|
+
},
|
|
94
|
+
);
|
|
86
95
|
|
|
87
|
-
const useJoin = useJoinRoom();
|
|
88
|
-
const {setStore} = useContext(StorageContext);
|
|
89
96
|
const {setGlobalErrorMessage} = useContext(ErrorContext);
|
|
90
97
|
const history = useHistory();
|
|
91
98
|
const [loading, setLoading] = useState(false);
|
|
@@ -313,6 +320,11 @@ const Create = () => {
|
|
|
313
320
|
<View>
|
|
314
321
|
<View style={style.logoContainerStyle}>
|
|
315
322
|
<Logo />
|
|
323
|
+
{CreateHeaderRightSlotComponent ? (
|
|
324
|
+
<CreateHeaderRightSlotComponent />
|
|
325
|
+
) : (
|
|
326
|
+
<></>
|
|
327
|
+
)}
|
|
316
328
|
{isMobileUA() ? (
|
|
317
329
|
<IDPLogoutComponent
|
|
318
330
|
containerStyle={{marginTop: 0, marginRight: 0}}
|
|
@@ -291,6 +291,8 @@ const ActionSheet = props => {
|
|
|
291
291
|
isCustomSidePanel={true}
|
|
292
292
|
customSidePanelProps={{
|
|
293
293
|
title: sidePanelArray[customSidePanelIndex]?.title,
|
|
294
|
+
headerRightSlot:
|
|
295
|
+
sidePanelArray[customSidePanelIndex]?.headerRightSlot,
|
|
294
296
|
onClose: sidePanelArray[customSidePanelIndex]?.onClose,
|
|
295
297
|
name: sidePanelArray[customSidePanelIndex]?.name,
|
|
296
298
|
}}
|
|
@@ -326,6 +326,8 @@ const ActionSheet = props => {
|
|
|
326
326
|
isCustomSidePanel={true}
|
|
327
327
|
customSidePanelProps={{
|
|
328
328
|
title: sidePanelArray[customSidePanelIndex]?.title,
|
|
329
|
+
headerRightSlot:
|
|
330
|
+
sidePanelArray[customSidePanelIndex]?.headerRightSlot,
|
|
329
331
|
onClose: sidePanelArray[customSidePanelIndex]?.onClose,
|
|
330
332
|
name: sidePanelArray[customSidePanelIndex]?.name,
|
|
331
333
|
}}
|
|
@@ -208,6 +208,7 @@ export const VBHeader = () => {
|
|
|
208
208
|
|
|
209
209
|
export const CustomSidePanelHeader = (props: {
|
|
210
210
|
title: string;
|
|
211
|
+
headerRightSlot?: React.ReactNode;
|
|
211
212
|
onClose?: () => void;
|
|
212
213
|
name: string;
|
|
213
214
|
}) => {
|
|
@@ -217,6 +218,7 @@ export const CustomSidePanelHeader = (props: {
|
|
|
217
218
|
centerComponent={
|
|
218
219
|
<Text style={SidePanelStyles.heading}>{props?.title}</Text>
|
|
219
220
|
}
|
|
221
|
+
trailingComponent={props?.headerRightSlot}
|
|
220
222
|
trailingIconName="close"
|
|
221
223
|
trailingIconOnPress={() => {
|
|
222
224
|
setSidePanel(SidePanelType.None);
|
|
@@ -224,7 +226,7 @@ export const CustomSidePanelHeader = (props: {
|
|
|
224
226
|
props?.onClose && props?.onClose();
|
|
225
227
|
} catch (error) {
|
|
226
228
|
console.error(
|
|
227
|
-
`Error on calling onClose in custom side panel ${name}`,
|
|
229
|
+
`Error on calling onClose in custom side panel ${props.name}`,
|
|
228
230
|
);
|
|
229
231
|
}
|
|
230
232
|
}}
|
|
@@ -400,6 +400,9 @@ const VideoCallScreen = () => {
|
|
|
400
400
|
<CustomSidePanelView
|
|
401
401
|
content={SidePanelArray[customSidePanelIndex]?.component}
|
|
402
402
|
title={SidePanelArray[customSidePanelIndex]?.title}
|
|
403
|
+
headerRightSlot={
|
|
404
|
+
SidePanelArray[customSidePanelIndex]?.headerRightSlot
|
|
405
|
+
}
|
|
403
406
|
name={SidePanelArray[customSidePanelIndex]?.name}
|
|
404
407
|
onClose={SidePanelArray[customSidePanelIndex]?.onClose}
|
|
405
408
|
/>
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from './DefaultLayouts';
|
|
26
26
|
import IconButton from '../../atoms/IconButton';
|
|
27
27
|
import UserActionMenuOptionsOptions from '../../components/participants/UserActionMenuOptions';
|
|
28
|
+
import type {ActionMenuItem} from '../../atoms/ActionMenu';
|
|
28
29
|
import {
|
|
29
30
|
isMobileUA,
|
|
30
31
|
isValidReactComponent,
|
|
@@ -60,6 +61,7 @@ export interface VideoRendererProps {
|
|
|
60
61
|
CustomChild?: React.ComponentType;
|
|
61
62
|
avatarRadius?: number;
|
|
62
63
|
hideMenuOptions?: boolean;
|
|
64
|
+
extraMenuItems?: ActionMenuItem[];
|
|
63
65
|
containerStyle?: ViewStyle;
|
|
64
66
|
innerContainerStyle?: ViewStyle;
|
|
65
67
|
}
|
|
@@ -69,6 +71,7 @@ const VideoRenderer: React.FC<VideoRendererProps> = ({
|
|
|
69
71
|
CustomChild,
|
|
70
72
|
avatarRadius = 100,
|
|
71
73
|
hideMenuOptions = false,
|
|
74
|
+
extraMenuItems,
|
|
72
75
|
containerStyle = {},
|
|
73
76
|
innerContainerStyle = {},
|
|
74
77
|
}) => {
|
|
@@ -214,6 +217,7 @@ const VideoRenderer: React.FC<VideoRendererProps> = ({
|
|
|
214
217
|
from={'video-tile'}
|
|
215
218
|
setSpotlightUid={setSpotlightUid}
|
|
216
219
|
spotlightUid={spotlightUid}
|
|
220
|
+
extraMenuItems={extraMenuItems}
|
|
217
221
|
/>
|
|
218
222
|
<PlatformWrapper isHovered={isHovered} setIsHovered={setIsHovered}>
|
|
219
223
|
<View
|
|
@@ -13,6 +13,7 @@ export interface SidePanelHeaderProps {
|
|
|
13
13
|
leadingIconOnPress?: () => void;
|
|
14
14
|
trailingIconName?: keyof IconsInterface;
|
|
15
15
|
trailingIconOnPress?: () => void;
|
|
16
|
+
trailingComponent?: React.ReactNode;
|
|
16
17
|
trailingIconName2?: keyof IconsInterface;
|
|
17
18
|
trailingIconOnPress2?: () => void;
|
|
18
19
|
isChat?: boolean;
|
|
@@ -56,9 +57,21 @@ const SidePanelHeader = React.forwardRef<View, SidePanelHeaderProps>(
|
|
|
56
57
|
<View style={{width: 30, height: 'auto'}}></View>
|
|
57
58
|
) : null}
|
|
58
59
|
{props?.centerComponent ? props.centerComponent : null}
|
|
59
|
-
<View
|
|
60
|
+
<View
|
|
61
|
+
style={
|
|
62
|
+
(props?.trailingIconName2 || props?.trailingComponent) &&
|
|
63
|
+
SidePanelStyles.row
|
|
64
|
+
}>
|
|
65
|
+
{props?.trailingComponent ? props.trailingComponent : null}
|
|
60
66
|
{props?.trailingIconName ? (
|
|
61
|
-
<View
|
|
67
|
+
<View
|
|
68
|
+
ref={ref}
|
|
69
|
+
collapsable={false}
|
|
70
|
+
style={
|
|
71
|
+
props?.trailingIconName2 || props?.trailingComponent
|
|
72
|
+
? {}
|
|
73
|
+
: {flex: 1}
|
|
74
|
+
}>
|
|
62
75
|
<IconButton
|
|
63
76
|
hoverEffect={true}
|
|
64
77
|
hoverEffectStyle={{
|
|
@@ -116,6 +129,7 @@ export const SidePanelStyles = StyleSheet.create({
|
|
|
116
129
|
borderBottomWidth: 1,
|
|
117
130
|
borderBottomColor: $config.CARD_LAYER_3_COLOR,
|
|
118
131
|
position: 'relative',
|
|
132
|
+
zIndex: 1000,
|
|
119
133
|
},
|
|
120
134
|
chatPadding: {
|
|
121
135
|
paddingHorizontal: 16,
|