agora-appbuilder-core 4.0.0-api.3 → 4.0.0-api.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "4.0.0-api.3",
3
+ "version": "4.0.0-api.5",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -55,8 +55,7 @@ export type layoutComponent = React.ComponentType<{
55
55
  export interface layoutItem {
56
56
  name: string;
57
57
  label: string;
58
- //todo: hari change iconName into icon and refactor icon lib
59
- iconName: keyof IconsInterface;
58
+ icon: string;
60
59
  component: layoutComponent;
61
60
  }
62
61
 
@@ -17,7 +17,8 @@ import hexadecimalTransparency from '../utils/hexadecimalTransparency';
17
17
 
18
18
  export interface ImageIconProps {
19
19
  tintColor?: string;
20
- name: keyof IconsInterface;
20
+ name?: keyof IconsInterface;
21
+ icon?: string;
21
22
  iconSize?: number;
22
23
  iconContainerStyle?: ViewStyle;
23
24
  iconBackgroundColor?: string;
@@ -33,6 +34,7 @@ export interface ImageIconProps {
33
34
  const ImageIcon = (props: ImageIconProps) => {
34
35
  const {
35
36
  name,
37
+ icon = undefined,
36
38
  iconSize = 26,
37
39
  tintColor,
38
40
  base64 = false,
@@ -80,8 +82,16 @@ const ImageIcon = (props: ImageIconProps) => {
80
82
  name={name}
81
83
  style={{width: iconSize, height: iconSize}}
82
84
  />
83
- ) : (
85
+ ) : icon ? (
86
+ <UIKitImageIcon
87
+ tintColor={tintColor}
88
+ icon={icon}
89
+ style={{width: iconSize, height: iconSize}}
90
+ />
91
+ ) : name ? (
84
92
  <CustomIcon name={name} color={tintColor} size={iconSize} />
93
+ ) : (
94
+ <></>
85
95
  )}
86
96
  </View>
87
97
  </View>
@@ -21,7 +21,7 @@ export default RecordingInfo;
21
21
  const styles = StyleSheet.create({
22
22
  recordingView: {
23
23
  padding: 12,
24
- paddingVertical: isMobileUA() ? 5 : 12,
24
+ paddingVertical: isMobileUA() ? 10 : 12,
25
25
  flexDirection: 'row',
26
26
  alignItems: 'center',
27
27
  alignContent: 'center',
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import {View, ViewProps, ViewStyle, StyleSheet} from 'react-native';
3
3
  import {ToolbarPosition, useToolbar} from '../utils/useToolbar';
4
- import {isWebInternal} from '../utils/common';
4
+ import {isMobileUA, isWebInternal} from '../utils/common';
5
5
 
6
6
  export interface ToolbarItemProps extends ViewProps {
7
7
  style?: ViewStyle;
@@ -13,31 +13,47 @@ const ToolbarItem = (props: ToolbarItemProps) => {
13
13
  //isHorizontal false -> left/right bar
14
14
  // todo hari - first item shouldnot contain the margin right
15
15
  // todo hari - last item shouldnot contain the margin right
16
- return (
17
- <View
18
- {...props}
19
- style={[
20
- props?.style,
21
- // isHorizontal ? {flexDirection: 'column'} : {flexDirection: 'row'},
22
- position === ToolbarPosition.left
23
- ? toolbarItemStyles.leftBarItemStyle
24
- : position === ToolbarPosition.right
25
- ? toolbarItemStyles.rightBarItemStyle
26
- : position === ToolbarPosition.bottom
27
- ? toolbarItemStyles.bottomBarItemStyle
28
- : isWebInternal() && position === ToolbarPosition.top
29
- ? toolbarItemStyles.topBarItemNonNativeStyle
30
- : !isWebInternal() && position === ToolbarPosition.top
31
- ? toolbarItemStyles.topBarItemNativeStyle
32
- : {},
33
- ]}>
34
- {props?.children}
35
- </View>
36
- );
16
+
17
+ //action sheet
18
+ if (isMobileUA() && position === ToolbarPosition.bottom) {
19
+ return (
20
+ <View {...props} style={toolbarItemStyles.iconWithText}>
21
+ {props?.children}
22
+ </View>
23
+ );
24
+ } else {
25
+ return (
26
+ <View
27
+ {...props}
28
+ style={[
29
+ props?.style,
30
+ // isHorizontal ? {flexDirection: 'column'} : {flexDirection: 'row'},
31
+ position === ToolbarPosition.left
32
+ ? toolbarItemStyles.leftBarItemStyle
33
+ : position === ToolbarPosition.right
34
+ ? toolbarItemStyles.rightBarItemStyle
35
+ : position === ToolbarPosition.bottom
36
+ ? toolbarItemStyles.bottomBarItemStyle
37
+ : isWebInternal() && position === ToolbarPosition.top
38
+ ? toolbarItemStyles.topBarItemNonNativeStyle
39
+ : !isWebInternal() && position === ToolbarPosition.top
40
+ ? toolbarItemStyles.topBarItemNativeStyle
41
+ : {},
42
+ ]}>
43
+ {props?.children}
44
+ </View>
45
+ );
46
+ }
37
47
  };
38
48
  export default ToolbarItem;
39
49
 
40
50
  const toolbarItemStyles = StyleSheet.create({
51
+ iconWithText: {
52
+ justifyContent: 'center',
53
+ alignItems: 'center',
54
+ flexBasis: '25%',
55
+ paddingBottom: 24,
56
+ },
41
57
  topBarItemNativeStyle: {},
42
58
  topBarItemNonNativeStyle: {
43
59
  marginTop: 8,
@@ -3,6 +3,9 @@ import Navbar from '../components/Navbar';
3
3
  import Controls from '../components/Controls';
4
4
  import Leftbar from '../components/Leftbar';
5
5
  import Rightbar from '../components/Rightbar';
6
+ import {isMobileUA} from '../utils/common';
7
+ import NavbarMobile from '../components/NavbarMobile';
8
+ import ActionSheet from '../pages/video-call/ActionSheet';
6
9
 
7
10
  export interface ToolbarCustomItem {
8
11
  component: () => JSX.Element;
@@ -25,13 +28,31 @@ const ToolbarPreset = (props: ToolbarPresetProps) => {
25
28
  return null;
26
29
  }
27
30
  if (align === 'left') {
28
- return <Leftbar customItems={props?.customItems} />;
31
+ return (
32
+ <Leftbar customItems={props?.customItems} includeDefaultItems={true} />
33
+ );
29
34
  } else if (align === 'right') {
30
- return <Rightbar customItems={props?.customItems} />;
35
+ return (
36
+ <Rightbar customItems={props?.customItems} includeDefaultItems={true} />
37
+ );
31
38
  } else if (align === 'top') {
32
- return <Navbar customItems={props?.customItems} />;
39
+ return isMobileUA() ? (
40
+ <NavbarMobile
41
+ customItems={props?.customItems}
42
+ includeDefaultItems={true}
43
+ />
44
+ ) : (
45
+ <Navbar customItems={props?.customItems} includeDefaultItems={true} />
46
+ );
33
47
  } else if (align === 'bottom') {
34
- return <Controls customItems={props?.customItems} />;
48
+ return isMobileUA() ? (
49
+ <ActionSheet
50
+ customItems={props?.customItems}
51
+ includeDefaultItems={true}
52
+ />
53
+ ) : (
54
+ <Controls customItems={props?.customItems} includeDefaultItems={true} />
55
+ );
35
56
  } else {
36
57
  return null;
37
58
  }
@@ -453,9 +453,10 @@ const defaultEndItems: ToolbarCustomItem[] = [];
453
453
 
454
454
  export interface ControlsProps {
455
455
  customItems?: ToolbarCustomItem[];
456
+ includeDefaultItems?: boolean;
456
457
  }
457
458
  const Controls = (props: ControlsProps) => {
458
- const {customItems = []} = props;
459
+ const {customItems = [], includeDefaultItems = true} = props;
459
460
  const {width} = useWindowDimensions();
460
461
 
461
462
  const isHidden = (i) => {
@@ -463,17 +464,17 @@ const Controls = (props: ControlsProps) => {
463
464
  };
464
465
  const customStartItems = customItems
465
466
  ?.filter((i) => i?.align === 'start' && !isHidden(i))
466
- ?.concat(defaultStartItems)
467
+ ?.concat(includeDefaultItems ? defaultStartItems : [])
467
468
  ?.sort((a, b) => a?.order - b?.order);
468
469
 
469
470
  const customCenterItems = customItems
470
471
  ?.filter((i) => i?.align === 'center' && !isHidden(i))
471
- ?.concat(defaultCenterItems)
472
+ ?.concat(includeDefaultItems ? defaultCenterItems : [])
472
473
  ?.sort((a, b) => a?.order - b?.order);
473
474
 
474
475
  const customEndItems = customItems
475
476
  ?.filter((i) => i?.align === 'end' && !isHidden(i))
476
- ?.concat(defaultEndItems)
477
+ ?.concat(includeDefaultItems ? defaultEndItems : [])
477
478
  ?.sort((a, b) => a?.order - b?.order);
478
479
 
479
480
  const renderContent = (
@@ -20,25 +20,26 @@ const defaultEndItems: ToolbarCustomItem[] = [];
20
20
 
21
21
  export interface LeftbarProps {
22
22
  customItems?: ToolbarCustomItem[];
23
+ includeDefaultItems?: boolean;
23
24
  }
24
25
  const Leftbar = (props: LeftbarProps) => {
25
- const {customItems = []} = props;
26
+ const {customItems = [], includeDefaultItems = true} = props;
26
27
  const isHidden = (i) => {
27
28
  return i?.hide === 'yes';
28
29
  };
29
30
  const customStartItems = customItems
30
31
  ?.filter((i) => i?.align === 'start' && !isHidden(i))
31
- ?.concat(defaultStartItems)
32
+ ?.concat(includeDefaultItems ? defaultStartItems : [])
32
33
  ?.sort((a, b) => a?.order - b?.order);
33
34
 
34
35
  const customCenterItems = customItems
35
36
  ?.filter((i) => i?.align === 'center' && !isHidden(i))
36
- ?.concat(defaultCenterItems)
37
+ ?.concat(includeDefaultItems ? defaultCenterItems : [])
37
38
  ?.sort((a, b) => a?.order - b?.order);
38
39
 
39
40
  const customEndItems = customItems
40
41
  ?.filter((i) => i?.align === 'end' && !isHidden(i))
41
- ?.concat(defaultEndItems)
42
+ ?.concat(includeDefaultItems ? defaultEndItems : [])
42
43
  ?.sort((a, b) => a?.order - b?.order);
43
44
 
44
45
  const renderContent = (
@@ -437,11 +437,12 @@ const defaultEndItems: ToolbarCustomItem[] = [
437
437
 
438
438
  export interface NavbarProps {
439
439
  customItems?: ToolbarCustomItem[];
440
+ includeDefaultItems?: boolean;
440
441
  }
441
442
  const Navbar = (props: NavbarProps) => {
442
443
  //commented for v1 release
443
444
  //const recordingLabel = useString('recordingLabel')();
444
- const {customItems = []} = props;
445
+ const {customItems = [], includeDefaultItems = true} = props;
445
446
  const {width} = useWindowDimensions();
446
447
 
447
448
  const isHidden = (i) => {
@@ -450,17 +451,17 @@ const Navbar = (props: NavbarProps) => {
450
451
 
451
452
  const customStartItems = customItems
452
453
  ?.filter((i) => i.align === 'start' && !isHidden(i))
453
- ?.concat(defaultStartItems)
454
+ ?.concat(includeDefaultItems ? defaultStartItems : [])
454
455
  ?.sort((a, b) => a?.order - b?.order);
455
456
 
456
457
  const customCenterItems = customItems
457
458
  ?.filter((i) => i.align === 'center' && !isHidden(i))
458
- ?.concat(defaultCenterItems)
459
+ ?.concat(includeDefaultItems ? defaultCenterItems : [])
459
460
  ?.sort((a, b) => a?.order - b?.order);
460
461
 
461
462
  const customEndItems = customItems
462
463
  ?.filter((i) => i.align === 'end' && !isHidden(i))
463
- ?.concat(defaultEndItems)
464
+ ?.concat(includeDefaultItems ? defaultEndItems : [])
464
465
  ?.sort((a, b) => a?.order - b?.order);
465
466
 
466
467
  const renderContent = (
@@ -0,0 +1,108 @@
1
+ import React from 'react';
2
+ import {View, StyleSheet} from 'react-native';
3
+ import Toolbar from '../atoms/Toolbar';
4
+ import {ToolbarCustomItem} from '../atoms/ToolbarPreset';
5
+ import {
6
+ MeetingTitleToolbarItem,
7
+ ParticipantCountToolbarItem,
8
+ RecordingStatusToolbarItem,
9
+ } from './Navbar';
10
+
11
+ export interface NavbarProps {
12
+ customItems?: ToolbarCustomItem[];
13
+ includeDefaultItems?: boolean;
14
+ }
15
+
16
+ const defaultStartItems: ToolbarCustomItem[] = [
17
+ {
18
+ align: 'start',
19
+ component: MeetingTitleToolbarItem,
20
+ order: 0,
21
+ hide: 'no',
22
+ },
23
+ {
24
+ align: 'start',
25
+ component: ParticipantCountToolbarItem,
26
+ order: 1,
27
+ hide: 'no',
28
+ },
29
+ {
30
+ align: 'start',
31
+ component: RecordingStatusToolbarItem,
32
+ order: 2,
33
+ hide: 'no',
34
+ },
35
+ ];
36
+ const defaultCenterItems: ToolbarCustomItem[] = [];
37
+ const defaultEndItems: ToolbarCustomItem[] = [];
38
+ const NavbarMobile = (props: NavbarProps) => {
39
+ const {customItems = [], includeDefaultItems = true} = props;
40
+ const isHidden = (i) => {
41
+ return i?.hide === 'yes';
42
+ };
43
+
44
+ const customStartItems = customItems
45
+ ?.filter((i) => i.align === 'start' && !isHidden(i))
46
+ ?.concat(includeDefaultItems ? defaultStartItems : [])
47
+ ?.sort((a, b) => a?.order - b?.order);
48
+
49
+ const customCenterItems = customItems
50
+ ?.filter((i) => i.align === 'center' && !isHidden(i))
51
+ ?.concat(includeDefaultItems ? defaultCenterItems : [])
52
+ ?.sort((a, b) => a?.order - b?.order);
53
+
54
+ const customEndItems = customItems
55
+ ?.filter((i) => i.align === 'end' && !isHidden(i))
56
+ ?.concat(includeDefaultItems ? defaultEndItems : [])
57
+ ?.sort((a, b) => a?.order - b?.order);
58
+
59
+ const renderContent = (
60
+ items: ToolbarCustomItem[],
61
+ type: 'start' | 'center' | 'end',
62
+ ) => {
63
+ return items?.map((item, index) => {
64
+ const ToolbarItem = item?.component;
65
+ if (ToolbarItem) {
66
+ return <ToolbarItem key={`top-toolbar-${type}` + index} />;
67
+ } else {
68
+ return null;
69
+ }
70
+ });
71
+ };
72
+ return (
73
+ <Toolbar>
74
+ <View style={style.startContent}>
75
+ {renderContent(customStartItems, 'start')}
76
+ </View>
77
+ <View style={style.centerContent}>
78
+ {renderContent(customCenterItems, 'center')}
79
+ </View>
80
+ <View style={style.endContent}>
81
+ {renderContent(customEndItems, 'end')}
82
+ </View>
83
+ </Toolbar>
84
+ );
85
+ };
86
+ export default NavbarMobile;
87
+ const style = StyleSheet.create({
88
+ startContent: {
89
+ flex: 1,
90
+ flexDirection: 'row',
91
+ justifyContent: 'flex-start',
92
+ alignItems: 'center',
93
+ },
94
+ centerContent: {
95
+ zIndex: 2,
96
+ flex: 1,
97
+ flexDirection: 'row',
98
+ justifyContent: 'center',
99
+ alignItems: 'center',
100
+ },
101
+ endContent: {
102
+ flex: 1,
103
+ zIndex: 9,
104
+ flexDirection: 'row',
105
+ justifyContent: 'flex-end',
106
+ alignItems: 'center',
107
+ },
108
+ });
@@ -20,9 +20,10 @@ const defaultEndItems: ToolbarCustomItem[] = [];
20
20
 
21
21
  export interface RightbarProps {
22
22
  customItems?: ToolbarCustomItem[];
23
+ includeDefaultItems?: boolean;
23
24
  }
24
25
  const Rightbar = (props: RightbarProps) => {
25
- const {customItems = []} = props;
26
+ const {customItems = [], includeDefaultItems = true} = props;
26
27
 
27
28
  const isHidden = (i) => {
28
29
  return i?.hide === 'yes';
@@ -30,17 +31,17 @@ const Rightbar = (props: RightbarProps) => {
30
31
 
31
32
  const customStartItems = customItems
32
33
  ?.filter((i) => i?.align === 'start' && !isHidden(i))
33
- ?.concat(defaultStartItems)
34
+ ?.concat(includeDefaultItems ? defaultStartItems : [])
34
35
  ?.sort((a, b) => a?.order - b?.order);
35
36
 
36
37
  const customCenterItems = customItems
37
38
  ?.filter((i) => i?.align === 'center' && !isHidden(i))
38
- ?.concat(defaultCenterItems)
39
+ ?.concat(includeDefaultItems ? defaultCenterItems : [])
39
40
  ?.sort((a, b) => a?.order - b?.order);
40
41
 
41
42
  const customEndItems = customItems
42
43
  ?.filter((i) => i?.align === 'end' && !isHidden(i))
43
- ?.concat(defaultEndItems)
44
+ ?.concat(includeDefaultItems ? defaultEndItems : [])
44
45
  ?.sort((a, b) => a?.order - b?.order);
45
46
 
46
47
  const renderContent = (
@@ -26,7 +26,7 @@ import Spacer from '../../atoms/Spacer';
26
26
 
27
27
  //topbar btn template is used to show icons without label text (as in desktop : bottomBar)
28
28
 
29
- const ActionSheet = () => {
29
+ const ActionSheet = (props) => {
30
30
  const [isExpanded, setIsExpanded] = React.useState(false);
31
31
  const {sidePanel, setSidePanel} = useSidePanel();
32
32
  const bottomSheetRef = useRef<BottomSheetModal>(null);
@@ -106,6 +106,7 @@ const ActionSheet = () => {
106
106
  handleIndicatorStyle={styles.handleIndicatorStyle}>
107
107
  <BottomSheetView>
108
108
  <ActionSheetContent
109
+ {...props}
109
110
  handleSheetChanges={handleSheetChanges}
110
111
  isExpanded={isExpanded}
111
112
  />
@@ -16,7 +16,7 @@ import {useToast} from '../../components/useToast';
16
16
  import ActionSheetHandle from './ActionSheetHandle';
17
17
  import Spacer from '../../atoms/Spacer';
18
18
 
19
- const ActionSheet = () => {
19
+ const ActionSheet = (props) => {
20
20
  const {setActionSheetVisible} = useToast();
21
21
  const [isExpanded, setIsExpanded] = React.useState(false);
22
22
  const [isChatOpen, setIsChatOpen] = React.useState(false);
@@ -152,6 +152,7 @@ const ActionSheet = () => {
152
152
  }
153
153
  blocking={false}>
154
154
  <ActionSheetContent
155
+ {...props}
155
156
  handleSheetChanges={handleSheetChanges}
156
157
  isExpanded={isExpanded}
157
158
  />
@@ -33,7 +33,11 @@ import {useChatNotification} from '../../components/chat-notification/useChatNot
33
33
  import {SidePanelType} from '../../subComponents/SidePanelEnum';
34
34
  import {useSidePanel} from '../../utils/useSidePanel';
35
35
  import Settings from '../../components/Settings';
36
- import {useLocalUserInfo} from 'customization-api';
36
+ import {
37
+ ToolbarCustomItem,
38
+ ToolbarItem,
39
+ useLocalUserInfo,
40
+ } from 'customization-api';
37
41
  import LayoutIconButton from '../../subComponents/LayoutIconButton';
38
42
 
39
43
  //Icon for expanding Action Sheet
@@ -45,7 +49,7 @@ interface ShowMoreIconProps {
45
49
  const ShowMoreIcon = (props: ShowMoreIconProps) => {
46
50
  const {isExpanded, onPress, showNotification} = props;
47
51
  return (
48
- <View style={styles.iconWithText}>
52
+ <ToolbarItem>
49
53
  <View style={styles.iconContainer}>
50
54
  <TouchableOpacity onPress={onPress}>
51
55
  <ImageIcon
@@ -55,7 +59,7 @@ const ShowMoreIcon = (props: ShowMoreIconProps) => {
55
59
  </TouchableOpacity>
56
60
  {showNotification && <View style={styles.notification} />}
57
61
  </View>
58
- </View>
62
+ </ToolbarItem>
59
63
  );
60
64
  };
61
65
 
@@ -67,7 +71,7 @@ interface LiveStreamIconProps {
67
71
  const LiveStreamIcon = (props: LiveStreamIconProps) => {
68
72
  const {isHandRaised, showLabel = $config.ICON_TEXT} = props;
69
73
  return (
70
- <View style={styles.iconWithText}>
74
+ <ToolbarItem>
71
75
  <View style={styles.iconContainer}>
72
76
  <LiveStreamControls
73
77
  showControls={true}
@@ -80,7 +84,7 @@ const LiveStreamIcon = (props: LiveStreamIconProps) => {
80
84
  {isHandRaised ? 'Lower\nHand' : 'Raise\nHand'}
81
85
  </Text>
82
86
  )}
83
- </View>
87
+ </ToolbarItem>
84
88
  );
85
89
  };
86
90
 
@@ -91,12 +95,12 @@ interface ChatIconProps {
91
95
  const ChatIcon = (props: ChatIconProps) => {
92
96
  const {showLabel = $config.ICON_TEXT} = props;
93
97
  return (
94
- <View style={styles.iconWithText}>
98
+ <ToolbarItem>
95
99
  <View style={styles.iconContainer}>
96
100
  <ChatIconButton isOnActionSheet={true} />
97
101
  </View>
98
102
  {showLabel && <Text style={styles.iconText}>Chat</Text>}
99
- </View>
103
+ </ToolbarItem>
100
104
  );
101
105
  };
102
106
 
@@ -107,13 +111,12 @@ interface ParticipantsIconProps {
107
111
  const ParticipantsIcon = (props: ParticipantsIconProps) => {
108
112
  const {showNotification} = props;
109
113
  return (
110
- <View style={styles.iconWithText}>
114
+ <ToolbarItem>
111
115
  <View style={styles.iconContainer}>
112
116
  <ParticipantsIconButton isOnActionSheet={true} />
113
117
  </View>
114
118
  {$config.ICON_TEXT && <Text style={styles.iconText}>People</Text>}
115
- {/* {showNotification && <View style={styles.notification} />} */}
116
- </View>
119
+ </ToolbarItem>
117
120
  );
118
121
  };
119
122
 
@@ -124,12 +127,12 @@ interface RecordingIconProps {
124
127
  const RecordingIcon = (props: RecordingIconProps) => {
125
128
  const {showLabel = $config.ICON_TEXT} = props;
126
129
  return (
127
- <View style={styles.iconWithText}>
130
+ <ToolbarItem>
128
131
  <View style={styles.iconContainer}>
129
132
  <Recording showLabel={false} isOnActionSheet={true} />
130
133
  </View>
131
134
  {showLabel && <Text style={styles.iconText}>Record</Text>}
132
- </View>
135
+ </ToolbarItem>
133
136
  );
134
137
  };
135
138
 
@@ -139,7 +142,7 @@ interface SwitchCameraIconProps {
139
142
  const SwitchCameraIcon = (props: SwitchCameraIconProps) => {
140
143
  const {disabled} = props;
141
144
  return (
142
- <View style={styles.iconWithText}>
145
+ <ToolbarItem>
143
146
  <View style={styles.iconContainer}>
144
147
  <LocalSwitchCamera showLabel={false} disabled={disabled} />
145
148
  </View>
@@ -166,7 +169,7 @@ const SwitchCameraIcon = (props: SwitchCameraIconProps) => {
166
169
  </Text>
167
170
  </View>
168
171
  )}
169
- </View>
172
+ </ToolbarItem>
170
173
  );
171
174
  };
172
175
 
@@ -176,7 +179,7 @@ interface SettingsIconProps {
176
179
  const SettingsIcon = (props: SettingsIconProps) => {
177
180
  const {onPress} = props;
178
181
  return (
179
- <View style={styles.iconWithText}>
182
+ <ToolbarItem>
180
183
  <TouchableOpacity style={styles.iconContainer} onPress={onPress}>
181
184
  <ImageIcon
182
185
  name={'settings'}
@@ -184,18 +187,18 @@ const SettingsIcon = (props: SettingsIconProps) => {
184
187
  />
185
188
  </TouchableOpacity>
186
189
  {$config.ICON_TEXT && <Text style={styles.iconText}>Settings</Text>}
187
- </View>
190
+ </ToolbarItem>
188
191
  );
189
192
  };
190
193
 
191
194
  const ShareIcon = () => {
192
195
  return (
193
- <View style={styles.iconWithText}>
196
+ <ToolbarItem>
194
197
  <View style={styles.iconContainer}>
195
198
  <CopyJoinInfo showLabel={false} isOnActionSheet={true} />
196
199
  </View>
197
200
  {$config.ICON_TEXT && <Text style={styles.iconText}>Invite</Text>}
198
- </View>
201
+ </ToolbarItem>
199
202
  );
200
203
  };
201
204
 
@@ -207,11 +210,11 @@ interface AudioIconProps {
207
210
  }
208
211
  const AudioIcon = (props: AudioIconProps) => {
209
212
  return (
210
- <View style={styles.iconWithText}>
213
+ <ToolbarItem>
211
214
  <View style={styles.iconContainer}>
212
215
  <LocalAudioMute {...props} />
213
216
  </View>
214
- </View>
217
+ </ToolbarItem>
215
218
  );
216
219
  };
217
220
 
@@ -223,11 +226,11 @@ interface CamIconProps {
223
226
  }
224
227
  const CamIcon = (props: CamIconProps) => {
225
228
  return (
226
- <View style={styles.iconWithText}>
229
+ <ToolbarItem>
227
230
  <View style={styles.iconContainer}>
228
231
  <LocalVideoMute {...props} />
229
232
  </View>
230
- </View>
233
+ </ToolbarItem>
231
234
  );
232
235
  };
233
236
 
@@ -237,7 +240,7 @@ interface EndCallIconProps {
237
240
  }
238
241
  const EndCallIcon = (props: EndCallIconProps) => {
239
242
  return (
240
- <View style={styles.iconWithText}>
243
+ <ToolbarItem>
241
244
  <View
242
245
  style={[
243
246
  styles.iconContainer,
@@ -245,7 +248,7 @@ const EndCallIcon = (props: EndCallIconProps) => {
245
248
  ]}>
246
249
  <LocalEndcall {...props} />
247
250
  </View>
248
- </View>
251
+ </ToolbarItem>
249
252
  );
250
253
  };
251
254
 
@@ -255,12 +258,12 @@ interface LayoutIconProps {
255
258
  const LayoutIcon = (props: LayoutIconProps) => {
256
259
  const {showLabel = $config.ICON_TEXT} = props;
257
260
  return (
258
- <View style={styles.iconWithText}>
261
+ <ToolbarItem>
259
262
  <View style={styles.iconContainer}>
260
263
  <LayoutIconButton showLabel={false} />
261
264
  </View>
262
265
  {showLabel && <Text style={styles.iconText}>Layout</Text>}
263
- </View>
266
+ </ToolbarItem>
264
267
  );
265
268
  };
266
269
 
@@ -293,7 +296,12 @@ export const ActionSheetComponentsArray: ActionSheetComponentsProps = [
293
296
  ];
294
297
 
295
298
  const ActionSheetContent = (props) => {
296
- const {handleSheetChanges, isExpanded} = props;
299
+ const {
300
+ handleSheetChanges,
301
+ isExpanded,
302
+ customItems = [],
303
+ includeDefaultItems = true,
304
+ } = props;
297
305
  const {onlineUsersCount, localUid} = useContext(ChatContext);
298
306
  const layouts = useLayoutsData();
299
307
  const {currentLayout} = useLayout();
@@ -327,106 +335,212 @@ const ActionSheetContent = (props) => {
327
335
  const isAudioVideoControlsDisabled =
328
336
  isAudience && $config.EVENT_MODE && !$config.RAISE_HAND;
329
337
  const isVideoDisabled = useLocalUserInfo().video === ToggleState.disabled;
330
- return (
331
- <View>
332
- {/* Row Always Visible */}
333
- <View
334
- style={[
335
- styles.row,
336
- {borderBottomWidth: 1, paddingTop: 4, justifyContent: 'center'},
337
- ]}>
338
- {isAudioVideoControlsDisabled ? null : (
339
- <AudioIcon
340
- isMobileView={true}
341
- isOnActionSheet={true}
342
- showLabel={false}
343
- disabled={isLiveStream && isAudience && !isBroadCasting}
344
- />
345
- )}
346
338
 
347
- {/*For AudioCast Host:Chat ,Attendee:Raise Hand
339
+ const defaultItems = [
340
+ {
341
+ default: true,
342
+ order: 0,
343
+ hide: 'no',
344
+ align: 'start',
345
+ component: isAudioVideoControlsDisabled ? null : (
346
+ <AudioIcon
347
+ isMobileView={true}
348
+ isOnActionSheet={true}
349
+ showLabel={false}
350
+ disabled={isLiveStream && isAudience && !isBroadCasting}
351
+ />
352
+ ),
353
+ },
354
+ {
355
+ default: true,
356
+ order: 0,
357
+ hide: 'no',
358
+ align: 'start',
359
+ /*For AudioCast Host:Chat ,Attendee:Raise Hand
348
360
  For VoiceChat Host:Chat, Attendee:Chat
349
- */}
350
-
351
- {(isAudioCastHost || isVoiceChatHost || isVoiceChatAudience) && (
352
- <ChatIcon showLabel={false} />
353
- )}
354
- {(isAudioCastAudience && isLiveStream && isAudience) ||
361
+ */
362
+ component: (isAudioCastHost ||
363
+ isVoiceChatHost ||
364
+ isVoiceChatAudience) && <ChatIcon showLabel={false} />,
365
+ },
366
+
367
+ {
368
+ default: true,
369
+ order: 0,
370
+ hide: 'no',
371
+ align: 'start',
372
+ component:
373
+ (isAudioCastAudience && isLiveStream && isAudience) ||
355
374
  (isBroadCasting && !isHost) ? (
356
375
  $config.RAISE_HAND && isAudioRoom ? (
357
376
  <LiveStreamIcon isHandRaised={isHandRaised} showLabel={false} />
358
377
  ) : null
359
- ) : null}
360
-
361
- {!isAudioRoom &&
362
- (isAudioVideoControlsDisabled ? null : (
363
- <CamIcon
364
- isOnActionSheet={true}
365
- isMobileView={true}
366
- showLabel={false}
367
- disabled={isLiveStream && isAudience && !isBroadCasting}
368
- />
369
- ))}
370
-
371
- <EndCallIcon showLabel={false} isOnActionSheet={true} />
372
-
373
- <ShowMoreIcon
374
- isExpanded={isExpanded}
375
- showNotification={
376
- (!isExpanded && totalUnreadCount !== 0) ||
377
- ($config.EVENT_MODE && isPendingRequestToReview)
378
- }
379
- onPress={() => handleSheetChanges(isExpanded ? 0 : 1)}
380
- />
381
- </View>
382
-
383
- {/* Rest Of Controls */}
384
- <View style={styles.row}>
385
- {/**
386
- * In event mode when raise hand feature is active
387
- * and audience is promoted to host, the audience can also
388
- * demote himself
389
- */}
390
- {(isLiveStream && isAudience) || (isBroadCasting && !isHost) ? (
378
+ ) : null,
379
+ },
380
+ {
381
+ default: true,
382
+ order: 1,
383
+ hide: 'no',
384
+ align: 'start',
385
+ component:
386
+ !isAudioRoom &&
387
+ (isAudioVideoControlsDisabled ? null : (
388
+ <CamIcon
389
+ isOnActionSheet={true}
390
+ isMobileView={true}
391
+ showLabel={false}
392
+ disabled={isLiveStream && isAudience && !isBroadCasting}
393
+ />
394
+ )),
395
+ },
396
+ {
397
+ default: true,
398
+ order: 2,
399
+ hide: 'no',
400
+ align: 'start',
401
+ component: <EndCallIcon showLabel={false} isOnActionSheet={true} />,
402
+ },
403
+ //reset of the controls
404
+ {
405
+ default: true,
406
+ order: 4,
407
+ hide: 'no',
408
+ align: 'start',
409
+ component:
410
+ (isLiveStream && isAudience) || (isBroadCasting && !isHost) ? (
391
411
  $config.RAISE_HAND && !isAudioRoom ? (
392
412
  <LiveStreamIcon isHandRaised={isHandRaised} />
393
413
  ) : null
394
- ) : null}
395
-
396
- {/* Layout view */}
397
- <LayoutIcon />
398
-
399
- {/* chat */}
400
- {!(isAudioCastHost || isVoiceChatHost || isVoiceChatAudience) && (
401
- <ChatIcon />
402
- )}
403
- {/* participants */}
414
+ ) : null,
415
+ },
416
+ {
417
+ default: true,
418
+ order: 5,
419
+ hide: 'no',
420
+ align: 'start',
421
+ component: <LayoutIcon />,
422
+ },
423
+ {
424
+ default: true,
425
+ order: 6,
426
+ hide: 'no',
427
+ align: 'start',
428
+ component: !(
429
+ isAudioCastHost ||
430
+ isVoiceChatHost ||
431
+ isVoiceChatAudience
432
+ ) && <ChatIcon />,
433
+ },
434
+ {
435
+ default: true,
436
+ order: 7,
437
+ hide: 'no',
438
+ align: 'start',
439
+ component: (
404
440
  <ParticipantsIcon
405
441
  showNotification={$config.EVENT_MODE && isPendingRequestToReview}
406
442
  />
407
- {/* record */}
408
- {isHost && $config.CLOUD_RECORDING ? <RecordingIcon /> : null}
409
-
410
- {/* switch camera */}
411
- {!isAudioRoom &&
412
- (isAudioVideoControlsDisabled ? null : (
413
- <SwitchCameraIcon
414
- disabled={
415
- (isLiveStream && isAudience && !isBroadCasting) ||
416
- isVideoDisabled
417
- }
418
- />
419
- ))}
420
-
421
- {/* settings */}
443
+ ),
444
+ },
445
+ {
446
+ default: true,
447
+ order: 8,
448
+ hide: 'no',
449
+ align: 'start',
450
+ component: isHost && $config.CLOUD_RECORDING ? <RecordingIcon /> : null,
451
+ },
452
+ {
453
+ default: true,
454
+ order: 9,
455
+ hide: 'no',
456
+ align: 'start',
457
+ component:
458
+ !isAudioRoom &&
459
+ (isAudioVideoControlsDisabled ? null : (
460
+ <SwitchCameraIcon
461
+ disabled={
462
+ (isLiveStream && isAudience && !isBroadCasting) || isVideoDisabled
463
+ }
464
+ />
465
+ )),
466
+ },
467
+ {
468
+ default: true,
469
+ order: 10,
470
+ hide: 'no',
471
+ align: 'start',
472
+ component: (
422
473
  <SettingsIcon
423
474
  onPress={() => {
424
475
  setSidePanel(SidePanelType.Settings);
425
476
  }}
426
477
  />
478
+ ),
479
+ },
480
+ {
481
+ default: true,
482
+ order: 11,
483
+ hide: 'no',
484
+ align: 'start',
485
+ component: <ShareIcon />,
486
+ },
487
+ ];
488
+
489
+ const isHidden = (i) => {
490
+ return i?.hide === 'yes';
491
+ };
492
+ const combinedItems = customItems
493
+ ?.filter((i) => !isHidden(i))
494
+ ?.concat(includeDefaultItems ? defaultItems : [])
495
+ //to filter empty component because of some condition array will have empty component
496
+ ?.filter((i) => i?.component)
497
+ ?.sort((a, b) => a?.order - b?.order);
498
+
499
+ return (
500
+ <View>
501
+ {/* Row Always Visible */}
502
+ <View
503
+ style={[
504
+ styles.row,
505
+ {borderBottomWidth: 1, paddingTop: 4, justifyContent: 'center'},
506
+ ]}>
507
+ {/**If no items more than 4 then render firstrender first 3 items and render show more icon */}
508
+ {/**If no items more less or equal to 4 then render n items and don't show more icon */}
509
+ {combinedItems
510
+ ?.slice(0, combinedItems?.length >= 4 ? 3 : 4)
511
+ ?.map((i) => {
512
+ const Component = i?.component;
513
+ if (Component) {
514
+ return i?.default ? Component : <Component />;
515
+ } else {
516
+ return null;
517
+ }
518
+ })}
519
+ {combinedItems && combinedItems?.length >= 4 ? (
520
+ <ShowMoreIcon
521
+ isExpanded={isExpanded}
522
+ showNotification={
523
+ (!isExpanded && totalUnreadCount !== 0) ||
524
+ ($config.EVENT_MODE && isPendingRequestToReview)
525
+ }
526
+ onPress={() => handleSheetChanges(isExpanded ? 0 : 1)}
527
+ />
528
+ ) : (
529
+ <></>
530
+ )}
531
+ </View>
427
532
 
428
- {/* invite */}
429
- <ShareIcon />
533
+ {/* Rest Of Controls */}
534
+ <View style={styles.row}>
535
+ {combinedItems?.length > 3 &&
536
+ combinedItems?.slice(3, combinedItems?.length)?.map((i) => {
537
+ const Component = i?.component;
538
+ if (Component) {
539
+ return i?.default ? Component : <Component />;
540
+ } else {
541
+ return null;
542
+ }
543
+ })}
430
544
  </View>
431
545
  </View>
432
546
  );
@@ -3,18 +3,24 @@ import GridVideo from '../../components/GridVideo';
3
3
  import PinnedVideo from '../../components/PinnedVideo';
4
4
  import useLayoutsData from './useLayoutsData';
5
5
  import {useLayout} from '../../utils/useLayout';
6
-
6
+ import {isMobileUA} from '../../utils/common';
7
+ const isMobileView = isMobileUA();
7
8
  export const DefaultLayouts: layoutItem[] = [
8
9
  {
9
10
  name: 'grid',
10
11
  label: 'Grid',
11
- iconName: 'grid',
12
+ //iconName: 'grid',
13
+ icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAFOSURBVHgB7drBTcNAEIXhWVeQEkwJVIDohA6gA2iBigIVhA6cEuhgGGNfd1+kZK1x9H/SyidbT0/ry+6YAQBwt9z9EOs91tFv4xTrZW8ZasHGWJP3Mc3fz56hiHBTPEbr5xzrsZTya0kzDLW3fNmCo/U1xnqzxBmG+nv2att4ssQZqr/Y/IPaRmJ7l6wZBkMTBQkUJFCQQEECBQkUJFCQQEECBQkUJFCQQEECBQkUJFCQ0Croy7bxY4kztAr6tm18WuIMrSPXQzxO1vlGIU46HyxxhuoOWq9Bnm25FunhvH7fMme4yHz94stt5C0cY32su2NXGQAAuDPOAFUzGANUIhwDVLW3nAGqfwxQiQwMUIkMnCgKFCRQkEBBAgUJFCRQkEBBAgUJFCRQkEBBAgUJFCRQkEBBAgNUIgMDVCIDA1QMUF2X4SLOABUAADv0Bxz9l6sMoGOZAAAAAElFTkSuQmCC',
12
14
  component: GridVideo,
13
15
  },
14
16
  {
15
17
  name: 'pinned',
16
18
  label: 'Pinned',
17
- iconName: 'pinned',
19
+ //iconName: 'pinned',
20
+ //for mobile view top pinned icon and desktop left pinned icon
21
+ icon: isMobileView
22
+ ? 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAFFSURBVHgB7dzhTcJQFEDhWybQDeoIjuAoTqKO4ASOAk6gG9gNZIN6TTUhhvdOAo9Iy/mSF3689JKeFH40lAhJkhZpHMc+1zrX53igP/OaaDjzJVdfa9DV4uTLOlcfR+jSzswxGmg8c8h1myO3+zZXlQMf4sg4M9Hneixt1q6gj2gQaAZX0Ldtjrze+16lI874ZE4+c9cqVGUgYCBgIGAgYCBgIGAgYCBgIGAgYCBgIEn/6eQ3zObCG2YHMhAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEDAQMBAwEKgF2sTleC9t1AK9xuV4Lm3UfqN4lS9vsfxHw4eu625Km8Ur6OdB+7uYHrxfqiGmcyyqfklnpN+691H5nM7QJtdTTP+4MIQkSYv0BZfkCSDYSwACAAAAAElFTkSuQmCC'
23
+ : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGCSURBVHgB7drdTYRAFIbhM1SwJWAJVmC2E61AO1BLsCKwgrUDKMEOxkPAS+a7YeCweZ9ksle7OXn3jzBjBgDA3co5X3y9++ryNm6+ns82w9pgra8h1zFMrx99hiSGG/yhtXpGX48ppV8LOkOz9qw8fwRbq6v19WaBZ2jWn2evto8nCzzD6lds+oLaTvzjnaLO0BiKCCQQSCCQQCCBQAKBBAIJBBIIJBBIIJBAIIFAAoEEAgmlQL3t48cCKwX6tn18WWClW64Xf7hZ5R0Fv9P5YOszxL3lumyDXG3eFqlhXF4/tOKPtEf6f4dfbLvfit7Xp817UaMFlywwdjVOgEACgQQCCQQSZKAc9fDSTtT5oNYfOqtzNT36upauhSL8zYc+QBX6OijC4aUIoh+gOhwHqMQM/M0LBBIIJBBIIJBAIIFAAoEEAgkEEggkEEggkEAggUACgYToB6h6O3iG6AeoDp8h+gGqw2cIfYDqNIe4pi2gZUd0C52vj+XTcaoZAAA4lz9x+tmcZ0GmbAAAAABJRU5ErkJggg==',
18
24
  component: PinnedVideo,
19
25
  },
20
26
  ];
@@ -10,9 +10,22 @@ import {useRecording} from '../../subComponents/recording/useRecording';
10
10
  import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
11
11
  import ParticipantsCount from '../../atoms/ParticipantsCount';
12
12
  import RecordingInfo from '../../atoms/RecordingInfo';
13
- import {isAndroid, isWebInternal, trimText} from '../../utils/common';
13
+ import {
14
+ isAndroid,
15
+ isValidReactComponent,
16
+ isWebInternal,
17
+ trimText,
18
+ } from '../../utils/common';
14
19
  import {ToggleState, useLocalUid} from '../../../agora-rn-uikit';
15
- import {useLocalUserInfo, useContent} from 'customization-api';
20
+ import {
21
+ useLocalUserInfo,
22
+ useContent,
23
+ ToolbarCustomItem,
24
+ } from 'customization-api';
25
+ import NavbarMobile, {NavbarProps} from '../../components/NavbarMobile';
26
+ import {useCustomization} from 'customization-implementation';
27
+ import {ToolbarPosition, ToolbarProvider} from '../../utils/useToolbar';
28
+ import {ControlsProps} from 'src/components/Controls';
16
29
 
17
30
  const VideoCallMobileView = () => {
18
31
  const {
@@ -72,9 +85,72 @@ const VideoCallMobileView = () => {
72
85
  // };
73
86
  // }, []);
74
87
 
88
+ const {BottombarComponent, BottombarProps, TopbarComponent, TopbarProps} =
89
+ useCustomization((data) => {
90
+ let components: {
91
+ BottombarComponent: React.ComponentType<ControlsProps>;
92
+ BottombarProps?: ToolbarCustomItem[];
93
+ TopbarComponent: React.ComponentType<NavbarProps>;
94
+ TopbarProps?: ToolbarCustomItem[];
95
+ } = {
96
+ BottombarComponent: ActionSheet,
97
+ BottombarProps: [],
98
+ TopbarComponent: NavbarMobile,
99
+ TopbarProps: [],
100
+ };
101
+ if (
102
+ data?.components?.videoCall &&
103
+ typeof data?.components?.videoCall === 'object'
104
+ ) {
105
+ if (
106
+ data?.components?.videoCall.bottomToolBar &&
107
+ typeof data?.components?.videoCall.bottomToolBar !== 'object' &&
108
+ isValidReactComponent(data?.components?.videoCall.bottomToolBar)
109
+ ) {
110
+ components.BottombarComponent =
111
+ data?.components?.videoCall.bottomToolBar;
112
+ }
113
+ if (
114
+ data?.components?.videoCall.bottomToolBar &&
115
+ typeof data?.components?.videoCall.bottomToolBar === 'object' &&
116
+ data?.components?.videoCall.bottomToolBar.length
117
+ ) {
118
+ components.BottombarProps = data?.components?.videoCall.bottomToolBar;
119
+ }
120
+
121
+ if (
122
+ data?.components?.videoCall.topToolBar &&
123
+ typeof data?.components?.videoCall.topToolBar !== 'object' &&
124
+ isValidReactComponent(data?.components?.videoCall.topToolBar)
125
+ ) {
126
+ components.TopbarComponent = data?.components?.videoCall.topToolBar;
127
+ }
128
+
129
+ if (
130
+ data?.components?.videoCall.topToolBar &&
131
+ typeof data?.components?.videoCall.topToolBar === 'object' &&
132
+ data?.components?.videoCall.topToolBar.length
133
+ ) {
134
+ components.TopbarProps = data?.components?.videoCall.topToolBar;
135
+ }
136
+ }
137
+
138
+ return components;
139
+ });
140
+
75
141
  return (
76
142
  <View style={styles.container}>
77
- <View style={styles.titleBar}>
143
+ <ToolbarProvider value={{position: ToolbarPosition.top}}>
144
+ {TopbarProps?.length ? (
145
+ <TopbarComponent
146
+ customItems={TopbarProps}
147
+ includeDefaultItems={false}
148
+ />
149
+ ) : (
150
+ <TopbarComponent />
151
+ )}
152
+ </ToolbarProvider>
153
+ {/* <View style={styles.titleBar}>
78
154
  <Text style={styles.title}>{trimText(meetingTitle)}</Text>
79
155
  <Spacer size={8} horizontal={false} />
80
156
  <View style={styles.countView}>
@@ -97,12 +173,21 @@ const VideoCallMobileView = () => {
97
173
  <></>
98
174
  )}
99
175
  </View>
100
- </View>
101
- <Spacer size={16} />
176
+ </View> */}
177
+ {/* <Spacer size={16} /> */}
102
178
  <View style={styles.videoView}>
103
179
  <VideoComponent />
104
180
  </View>
105
- <ActionSheet />
181
+ <ToolbarProvider value={{position: ToolbarPosition.bottom}}>
182
+ {BottombarProps?.length ? (
183
+ <BottombarComponent
184
+ customItems={BottombarProps}
185
+ includeDefaultItems={false}
186
+ />
187
+ ) : (
188
+ <BottombarComponent />
189
+ )}
190
+ </ToolbarProvider>
106
191
  </View>
107
192
  );
108
193
  };
@@ -222,11 +222,25 @@ const VideoCallScreen = () => {
222
222
  <VideocallBeforeView />
223
223
  <View style={style.fullRow}>
224
224
  <ToolbarProvider value={{position: ToolbarPosition.left}}>
225
- <LeftbarComponent customItems={LeftbarProps} />
225
+ {LeftbarProps?.length ? (
226
+ <LeftbarComponent
227
+ customItems={LeftbarProps}
228
+ includeDefaultItems={false}
229
+ />
230
+ ) : (
231
+ <LeftbarComponent />
232
+ )}
226
233
  </ToolbarProvider>
227
234
  <View style={style.full}>
228
235
  <ToolbarProvider value={{position: ToolbarPosition.top}}>
229
- <TopbarComponent customItems={TopbarProps} />
236
+ {TopbarProps?.length ? (
237
+ <TopbarComponent
238
+ customItems={TopbarProps}
239
+ includeDefaultItems={false}
240
+ />
241
+ ) : (
242
+ <TopbarComponent />
243
+ )}
230
244
  </ToolbarProvider>
231
245
  <View
232
246
  style={[
@@ -258,12 +272,26 @@ const VideoCallScreen = () => {
258
272
  <></>
259
273
  ) : (
260
274
  <ToolbarProvider value={{position: ToolbarPosition.bottom}}>
261
- <BottombarComponent customItems={BottombarProps} />
275
+ {BottombarProps?.length ? (
276
+ <BottombarComponent
277
+ customItems={BottombarProps}
278
+ includeDefaultItems={false}
279
+ />
280
+ ) : (
281
+ <BottombarComponent />
282
+ )}
262
283
  </ToolbarProvider>
263
284
  )}
264
285
  </View>
265
286
  <ToolbarProvider value={{position: ToolbarPosition.right}}>
266
- <RightbarComponent customItems={RightbarProps} />
287
+ {RightbarProps?.length ? (
288
+ <RightbarComponent
289
+ customItems={RightbarProps}
290
+ includeDefaultItems={false}
291
+ />
292
+ ) : (
293
+ <RightbarComponent />
294
+ )}
267
295
  </ToolbarProvider>
268
296
  </View>
269
297
  <VideocallAfterView />
@@ -67,12 +67,7 @@ const LayoutIconButton = (props: LayoutIconButtonInterface) => {
67
67
  textColor: $config.FONT_COLOR,
68
68
  },
69
69
  };
70
- const iconName =
71
- layouts[layout]?.iconName === 'pinned' && isMobileView
72
- ? 'list-view'
73
- : layouts[layout]?.iconName;
74
-
75
- renderContent.push(
70
+ const iconName = renderContent.push(
76
71
  props?.render ? (
77
72
  props.render(onPress)
78
73
  ) : (
@@ -105,7 +100,7 @@ const LayoutIconButton = (props: LayoutIconButtonInterface) => {
105
100
  }}
106
101
  key={'defaultLayoutIconWithName'}
107
102
  iconProps={{
108
- name: iconName,
103
+ icon: layouts[layout]?.icon,
109
104
  tintColor: $config.SECONDARY_ACTION_COLOR,
110
105
  }}
111
106
  {...iconButtonProps}
@@ -80,10 +80,7 @@ const LayoutIconDropdown = (props: LayoutIconDropdownProps) => {
80
80
  padding: 10,
81
81
  },
82
82
  iconType: 'plain',
83
- name:
84
- item.iconName === 'pinned' && isMobileView
85
- ? 'list-view'
86
- : item.iconName,
83
+ icon: item.icon,
87
84
  tintColor: $config.SECONDARY_ACTION_COLOR,
88
85
  },
89
86
  btnTextProps: {