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

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.2",
3
+ "version": "4.0.0-api.3",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -53,6 +53,7 @@ export {
53
53
  export {default as Toolbar} from '../src/atoms/Toolbar';
54
54
  export {default as ToolbarItem} from '../src/atoms/ToolbarItem';
55
55
  export {default as ToolbarPreset} from '../src/atoms/ToolbarPreset';
56
+ export {default as ToolbarMenu} from '../src/atoms/ToolbarMenu';
56
57
  export type {
57
58
  ToolbarCustomItem,
58
59
  ToolbarPresetProps,
@@ -22,6 +22,7 @@ import {IconsInterface} from '../src/atoms/CustomIcon';
22
22
  export type {ContentInterface, ContentStateInterface, UidType};
23
23
  export type {ChatTextInputProps} from '../src/subComponents/ChatInput';
24
24
  import {ChatTextInputProps} from '../src/subComponents/ChatInput';
25
+ import {ToolbarCustomItem} from './sub-components';
25
26
 
26
27
  export const CUSTOM_ROUTES_PREFIX = '/r/';
27
28
 
@@ -59,12 +60,13 @@ export interface layoutItem {
59
60
  component: layoutComponent;
60
61
  }
61
62
 
63
+ export type ToolbarType = React.ComponentType | Array<ToolbarCustomItem>;
62
64
  export interface VideoCallInterface extends BeforeAndAfterInterface {
63
65
  // commented for v1 release
64
- topToolBar?: React.ComponentType;
65
- bottomToolBar?: React.ComponentType;
66
- leftToolBar?: React.ComponentType;
67
- rightToolBar?: React.ComponentType;
66
+ topToolBar?: ToolbarType;
67
+ bottomToolBar?: ToolbarType;
68
+ leftToolBar?: ToolbarType;
69
+ rightToolBar?: ToolbarType;
68
70
  //settingsPanel?: React.ComponentType;
69
71
  participantsPanel?: React.ComponentType;
70
72
  chat?: ChatCmpInterface;
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import {View, StyleSheet, ViewStyle} from 'react-native';
3
+ import {ToolbarMenuProvider} from '../utils/useMenu';
4
+
5
+ export interface ToolbarMenuProps {
6
+ children: React.ReactNode;
7
+ containerStyle?: ViewStyle;
8
+ }
9
+ const ToolbarMenu = (props: ToolbarMenuProps) => {
10
+ const {children, containerStyle} = props;
11
+ if (!children) {
12
+ return null;
13
+ }
14
+ return (
15
+ <ToolbarMenuProvider>
16
+ <View style={[ToolbarMenuStyle.containerStyle, containerStyle]}>
17
+ {children}
18
+ </View>
19
+ </ToolbarMenuProvider>
20
+ );
21
+ };
22
+ export default ToolbarMenu;
23
+
24
+ const ToolbarMenuStyle = StyleSheet.create({
25
+ containerStyle: {
26
+ flex: 1,
27
+ justifyContent: 'flex-start',
28
+ backgroundColor: $config.CARD_LAYER_4_COLOR,
29
+ borderRadius: 4,
30
+ shadowColor: '#000',
31
+ shadowOffset: {
32
+ width: 0,
33
+ height: 4,
34
+ },
35
+ shadowOpacity: 0.1,
36
+ shadowRadius: 8,
37
+ zIndex: 1,
38
+ elevation: 1,
39
+ },
40
+ });
@@ -0,0 +1,104 @@
1
+ import React, {useState} from 'react';
2
+ import {
3
+ View,
4
+ StyleSheet,
5
+ TouchableOpacityProps,
6
+ TouchableOpacity,
7
+ Text,
8
+ } from 'react-native';
9
+ import ThemeConfig from '../theme';
10
+ import ImageIcon from './ImageIcon';
11
+ import {IconButtonProps} from './IconButton';
12
+ import {isWebInternal} from '../utils/common';
13
+ import hexadecimalTransparency from '../utils/hexadecimalTransparency';
14
+
15
+ export interface ToolbarMenuItemProps extends IconButtonProps {
16
+ // disabled?: boolean;
17
+ // onPress: TouchableOpacityProps['onPress'];
18
+ // isHovered?: boolean;
19
+ // menuIcon?: string;
20
+ // menuText?: string;
21
+ // menuIconColor?: string;
22
+ }
23
+ const ToolbarMenuItem = (props: ToolbarMenuItemProps) => {
24
+ return (
25
+ <PlatformWrapper>
26
+ {(isHovered: boolean) => (
27
+ <>
28
+ <TouchableOpacity
29
+ disabled={props.disabled}
30
+ style={[
31
+ props.disabled ? {opacity: 0.4} : {},
32
+ isHovered
33
+ ? {
34
+ backgroundColor:
35
+ $config.CARD_LAYER_5_COLOR +
36
+ hexadecimalTransparency['15%'],
37
+ }
38
+ : {},
39
+ ToolbarMenuItemStyles.container,
40
+ ]}
41
+ onPress={props.onPress}>
42
+ <View style={ToolbarMenuItemStyles.iconContainer}>
43
+ <ImageIcon
44
+ base64={false}
45
+ iconType="plain"
46
+ iconSize={20}
47
+ name={props?.iconProps?.name}
48
+ tintColor={props?.iconProps?.tintColor}
49
+ />
50
+ </View>
51
+ <Text
52
+ style={[
53
+ ToolbarMenuItemStyles.textStyle,
54
+ props?.btnTextProps?.textStyle,
55
+ props?.btnTextProps?.textColor
56
+ ? {color: props?.btnTextProps?.textColor}
57
+ : {},
58
+ ]}>
59
+ {props?.btnTextProps?.text}
60
+ </Text>
61
+ </TouchableOpacity>
62
+ </>
63
+ )}
64
+ </PlatformWrapper>
65
+ );
66
+ };
67
+ export default ToolbarMenuItem;
68
+ const PlatformWrapper = ({children}) => {
69
+ const [isHovered, setIsHovered] = useState(false);
70
+ return isWebInternal() ? (
71
+ <div
72
+ onMouseEnter={() => {
73
+ setIsHovered(true);
74
+ }}
75
+ onMouseLeave={() => {
76
+ setIsHovered(false);
77
+ }}>
78
+ {children(isHovered)}
79
+ </div>
80
+ ) : (
81
+ <>{children(false)}</>
82
+ );
83
+ };
84
+ const ToolbarMenuItemStyles = StyleSheet.create({
85
+ container: {
86
+ flexDirection: 'row',
87
+ borderBottomWidth: 1,
88
+ borderBottomColor: $config.CARD_LAYER_3_COLOR,
89
+ },
90
+ iconContainer: {
91
+ justifyContent: 'center',
92
+ alignItems: 'center',
93
+ marginRight: 8,
94
+ marginVertical: 12,
95
+ marginLeft: 12,
96
+ },
97
+ textStyle: {
98
+ paddingVertical: 14,
99
+ color: $config.SECONDARY_ACTION_COLOR,
100
+ fontSize: ThemeConfig.FontSize.normal,
101
+ fontWeight: '400',
102
+ fontFamily: ThemeConfig.FontFamily.sansPro,
103
+ },
104
+ });
@@ -41,7 +41,7 @@ import {useScreenshare} from '../subComponents/screenshare/useScreenshare';
41
41
  import LayoutIconDropdown from '../subComponents/LayoutIconDropdown';
42
42
  import Toolbar from '../atoms/Toolbar';
43
43
  import ToolbarItem from '../atoms/ToolbarItem';
44
- import {ToolbarCustomItem} from 'src/atoms/ToolbarPreset';
44
+ import {ToolbarCustomItem} from '../atoms/ToolbarPreset';
45
45
 
46
46
  const MoreButton = () => {
47
47
  const {rtcProps} = useContext(PropsContext);
@@ -61,6 +61,8 @@ import RecordingInfo from '../atoms/RecordingInfo';
61
61
  import Toolbar from '../atoms/Toolbar';
62
62
  import ToolbarItem from '../atoms/ToolbarItem';
63
63
  import {ToolbarCustomItem} from '../atoms/ToolbarPreset';
64
+ import {useToolbarMenu} from '../utils/useMenu';
65
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
64
66
 
65
67
  export const ParticipantsCountView = ({
66
68
  isMobileView = false,
@@ -100,6 +102,7 @@ export interface ParticipantsIconButtonProps {
100
102
  render?: (onPress: () => void, isPanelActive: boolean) => JSX.Element;
101
103
  }
102
104
  export const ParticipantsIconButton = (props: ParticipantsIconButtonProps) => {
105
+ const {isToolbarMenuItem} = useToolbarMenu();
103
106
  const {
104
107
  liveStreamingRequestAlertIconPosition = {
105
108
  top: 0,
@@ -148,22 +151,30 @@ export const ParticipantsIconButton = (props: ParticipantsIconButtonProps) => {
148
151
  props.render(onPress, isPanelActive)
149
152
  ) : (
150
153
  <>
151
- <View>
152
- <IconButton {...iconButtonProps} />
153
- </View>
154
- {$config.EVENT_MODE && $config.RAISE_HAND && isPendingRequestToReview && (
155
- <View
156
- style={{
157
- position: 'absolute',
158
- top: liveStreamingRequestAlertIconPosition.top,
159
- bottom: liveStreamingRequestAlertIconPosition.bottom,
160
- right: liveStreamingRequestAlertIconPosition.right,
161
- left: liveStreamingRequestAlertIconPosition.left,
162
- backgroundColor: $config.SEMANTIC_ERROR,
163
- width: 12,
164
- height: 12,
165
- borderRadius: 10,
166
- }}></View>
154
+ {isToolbarMenuItem ? (
155
+ <ToolbarMenuItem {...iconButtonProps} />
156
+ ) : (
157
+ <>
158
+ <View>
159
+ <IconButton {...iconButtonProps} />
160
+ </View>
161
+ {$config.EVENT_MODE &&
162
+ $config.RAISE_HAND &&
163
+ isPendingRequestToReview && (
164
+ <View
165
+ style={{
166
+ position: 'absolute',
167
+ top: liveStreamingRequestAlertIconPosition.top,
168
+ bottom: liveStreamingRequestAlertIconPosition.bottom,
169
+ right: liveStreamingRequestAlertIconPosition.right,
170
+ left: liveStreamingRequestAlertIconPosition.left,
171
+ backgroundColor: $config.SEMANTIC_ERROR,
172
+ width: 12,
173
+ height: 12,
174
+ borderRadius: 10,
175
+ }}></View>
176
+ )}
177
+ </>
167
178
  )}
168
179
  </>
169
180
  );
@@ -188,6 +199,7 @@ export interface ChatIconButtonProps {
188
199
 
189
200
  export const ChatIconButton = (props: ChatIconButtonProps) => {
190
201
  const {sidePanel, setSidePanel} = useSidePanel();
202
+ const {isToolbarMenuItem} = useToolbarMenu();
191
203
  const {
192
204
  badgeContainerPosition = {
193
205
  top: 0,
@@ -288,8 +300,14 @@ export const ChatIconButton = (props: ChatIconButtonProps) => {
288
300
  ) : (
289
301
  <>
290
302
  <View>
291
- <IconButton {...iconButtonProps} />
292
- {totalUnreadCount !== 0 && renderUnreadMessageIndicator()}
303
+ {isToolbarMenuItem ? (
304
+ <ToolbarMenuItem {...iconButtonProps} />
305
+ ) : (
306
+ <>
307
+ <IconButton {...iconButtonProps} />
308
+ {totalUnreadCount !== 0 && renderUnreadMessageIndicator()}
309
+ </>
310
+ )}
293
311
  </View>
294
312
  </>
295
313
  );
@@ -16,6 +16,8 @@ import {SidePanelType} from '../subComponents/SidePanelEnum';
16
16
  import {useSidePanel} from '../utils/useSidePanel';
17
17
  import {useString} from '../utils/useString';
18
18
  import IconButton, {IconButtonProps} from '../atoms/IconButton';
19
+ import {useToolbarMenu} from '../utils/useMenu';
20
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
19
21
 
20
22
  export interface SettingsIconButtonProps {
21
23
  render?: (onPress: () => void, isPanelActive: boolean) => JSX.Element;
@@ -23,6 +25,7 @@ export interface SettingsIconButtonProps {
23
25
 
24
26
  const Settings = (props: SettingsIconButtonProps) => {
25
27
  const {sidePanel, setSidePanel} = useSidePanel();
28
+ const {isToolbarMenuItem} = useToolbarMenu();
26
29
  //commented for v1 release
27
30
  //const settingsLabel = useString('settingsLabel')();
28
31
  const settingsLabel = 'Settings';
@@ -55,7 +58,11 @@ const Settings = (props: SettingsIconButtonProps) => {
55
58
  ) : (
56
59
  <>
57
60
  <View>
58
- <IconButton {...iconButtonProps} />
61
+ {isToolbarMenuItem ? (
62
+ <ToolbarMenuItem {...iconButtonProps} />
63
+ ) : (
64
+ <IconButton {...iconButtonProps} />
65
+ )}
59
66
  </View>
60
67
  </>
61
68
  );
@@ -25,7 +25,11 @@ import {videoView} from '../../../theme.json';
25
25
  import {ToolbarProvider, ToolbarPosition} from '../../utils/useToolbar';
26
26
  import SDKEvents from '../../utils/SdkEvents';
27
27
  import {useRoomInfo} from '../../components/room-info/useRoomInfo';
28
- import {controlMessageEnum, useUserName} from 'customization-api';
28
+ import {
29
+ ToolbarCustomItem,
30
+ controlMessageEnum,
31
+ useUserName,
32
+ } from 'customization-api';
29
33
  import events, {PersistanceLevel} from '../../rtm-events-api';
30
34
  import VideoCallMobileView from './VideoCallMobileView';
31
35
  import Leftbar, {LeftbarProps} from '../../components/Leftbar';
@@ -48,6 +52,10 @@ const VideoCallScreen = () => {
48
52
  VideocallAfterView,
49
53
  LeftbarComponent,
50
54
  RightbarComponent,
55
+ BottombarProps,
56
+ TopbarProps,
57
+ LeftbarProps,
58
+ RightbarProps,
51
59
  } = useCustomization((data) => {
52
60
  let components: {
53
61
  VideocallComponent?: React.ComponentType;
@@ -60,6 +68,10 @@ const VideoCallScreen = () => {
60
68
  VideocallAfterView: React.ComponentType;
61
69
  LeftbarComponent: React.ComponentType<LeftbarProps>;
62
70
  RightbarComponent: React.ComponentType<RightbarProps>;
71
+ BottombarProps?: ToolbarCustomItem[];
72
+ TopbarProps?: ToolbarCustomItem[];
73
+ LeftbarProps?: ToolbarCustomItem[];
74
+ RightbarProps?: ToolbarCustomItem[];
63
75
  } = {
64
76
  BottombarComponent: Controls,
65
77
  TopbarComponent: Navbar,
@@ -70,6 +82,10 @@ const VideoCallScreen = () => {
70
82
  VideocallBeforeView: React.Fragment,
71
83
  LeftbarComponent: Leftbar,
72
84
  RightbarComponent: Rightbar,
85
+ BottombarProps: [],
86
+ TopbarProps: [],
87
+ LeftbarProps: [],
88
+ RightbarProps: [],
73
89
  };
74
90
  if (
75
91
  data?.components?.videoCall &&
@@ -140,6 +156,35 @@ const VideoCallScreen = () => {
140
156
  components.RightbarComponent = data?.components?.videoCall.rightToolBar;
141
157
  }
142
158
 
159
+ if (
160
+ data?.components?.videoCall.bottomToolBar &&
161
+ typeof data?.components?.videoCall.bottomToolBar === 'object' &&
162
+ data?.components?.videoCall.bottomToolBar.length
163
+ ) {
164
+ components.BottombarProps = data?.components?.videoCall.bottomToolBar;
165
+ }
166
+ if (
167
+ data?.components?.videoCall.topToolBar &&
168
+ typeof data?.components?.videoCall.topToolBar === 'object' &&
169
+ data?.components?.videoCall.topToolBar.length
170
+ ) {
171
+ components.TopbarProps = data?.components?.videoCall.topToolBar;
172
+ }
173
+ if (
174
+ data?.components?.videoCall.rightToolBar &&
175
+ typeof data?.components?.videoCall.rightToolBar === 'object' &&
176
+ data?.components?.videoCall.rightToolBar.length
177
+ ) {
178
+ components.RightbarProps = data?.components?.videoCall.rightToolBar;
179
+ }
180
+ if (
181
+ data?.components?.videoCall.leftToolBar &&
182
+ typeof data?.components?.videoCall.leftToolBar === 'object' &&
183
+ data?.components?.videoCall.leftToolBar.length
184
+ ) {
185
+ components.LeftbarProps = data?.components?.videoCall.leftToolBar;
186
+ }
187
+
143
188
  if (
144
189
  data?.components?.videoCall.participantsPanel &&
145
190
  typeof data?.components?.videoCall.participantsPanel !== 'object' &&
@@ -177,11 +222,11 @@ const VideoCallScreen = () => {
177
222
  <VideocallBeforeView />
178
223
  <View style={style.fullRow}>
179
224
  <ToolbarProvider value={{position: ToolbarPosition.left}}>
180
- <LeftbarComponent />
225
+ <LeftbarComponent customItems={LeftbarProps} />
181
226
  </ToolbarProvider>
182
227
  <View style={style.full}>
183
228
  <ToolbarProvider value={{position: ToolbarPosition.top}}>
184
- <TopbarComponent />
229
+ <TopbarComponent customItems={TopbarProps} />
185
230
  </ToolbarProvider>
186
231
  <View
187
232
  style={[
@@ -213,12 +258,12 @@ const VideoCallScreen = () => {
213
258
  <></>
214
259
  ) : (
215
260
  <ToolbarProvider value={{position: ToolbarPosition.bottom}}>
216
- <BottombarComponent />
261
+ <BottombarComponent customItems={BottombarProps} />
217
262
  </ToolbarProvider>
218
263
  )}
219
264
  </View>
220
265
  <ToolbarProvider value={{position: ToolbarPosition.right}}>
221
- <RightbarComponent />
266
+ <RightbarComponent customItems={RightbarProps} />
222
267
  </ToolbarProvider>
223
268
  </View>
224
269
  <VideocallAfterView />
@@ -15,6 +15,8 @@ import useGetMeetingPhrase from '../utils/useGetMeetingPhrase';
15
15
  import TertiaryButton from '../atoms/TertiaryButton';
16
16
  import IconButton, {IconButtonProps} from '../atoms/IconButton';
17
17
  import {useVideoCall} from '../components/useVideoCall';
18
+ import {useToolbarMenu} from '../utils/useMenu';
19
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
18
20
 
19
21
  export interface CopyJoinInfoProps {
20
22
  showLabel?: boolean;
@@ -24,6 +26,7 @@ export interface CopyJoinInfoProps {
24
26
  }
25
27
 
26
28
  const CopyJoinInfo = (props: CopyJoinInfoProps) => {
29
+ const {isToolbarMenuItem} = useToolbarMenu();
27
30
  const {
28
31
  showLabel = $config.ICON_TEXT || false,
29
32
  showTeritaryButton = false,
@@ -57,6 +60,8 @@ const CopyJoinInfo = (props: CopyJoinInfoProps) => {
57
60
  <>
58
61
  {showTeritaryButton ? (
59
62
  <TertiaryButton text="Invite" onPress={onPress} />
63
+ ) : isToolbarMenuItem ? (
64
+ <ToolbarMenuItem {...iconButtonProps} />
60
65
  ) : (
61
66
  <IconButton {...iconButtonProps} />
62
67
  )}
@@ -26,6 +26,9 @@ import IconButton, {IconButtonProps} from '../atoms/IconButton';
26
26
  import ThemeConfig from '../theme';
27
27
  import {ImageIconProps} from '../atoms/ImageIcon';
28
28
  import useIsHandRaised from '../utils/useIsHandRaised';
29
+ import {useToolbarMenu} from '../utils/useMenu';
30
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
31
+
29
32
  /**
30
33
  * A component to mute / unmute the local audio
31
34
  */
@@ -45,6 +48,7 @@ export interface LocalAudioMuteProps {
45
48
  }
46
49
 
47
50
  function LocalAudioMute(props: LocalAudioMuteProps) {
51
+ const {isToolbarMenuItem} = useToolbarMenu();
48
52
  const {rtcProps} = useContext(PropsContext);
49
53
  const {
50
54
  data: {isHost},
@@ -156,6 +160,8 @@ function LocalAudioMute(props: LocalAudioMuteProps) {
156
160
 
157
161
  return props?.render ? (
158
162
  props.render(onPress, isAudioEnabled)
163
+ ) : isToolbarMenuItem ? (
164
+ <ToolbarMenuItem {...iconButtonProps} />
159
165
  ) : (
160
166
  <IconButton {...iconButtonProps} />
161
167
  );
@@ -6,6 +6,9 @@ import IconButton, {IconButtonProps} from '../atoms/IconButton';
6
6
  import ReactNativeForegroundService from '@supersami/rn-foreground-service';
7
7
  import {Platform} from 'react-native';
8
8
  import {DispatchContext} from '../../agora-rn-uikit';
9
+ import {useToolbarMenu} from '../utils/useMenu';
10
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
11
+
9
12
  export interface LocalEndcallProps {
10
13
  showLabel?: boolean;
11
14
  isOnActionSheet?: boolean;
@@ -21,6 +24,7 @@ const stopForegroundService = () => {
21
24
  };
22
25
 
23
26
  const LocalEndcall = (props: LocalEndcallProps) => {
27
+ const {isToolbarMenuItem} = useToolbarMenu();
24
28
  const {dispatch} = useContext(DispatchContext);
25
29
  const {showLabel = $config.ICON_TEXT, isOnActionSheet = false} = props;
26
30
  //commented for v1 release
@@ -80,7 +84,11 @@ const LocalEndcall = (props: LocalEndcallProps) => {
80
84
  setModalVisible={setEndcallVisible}
81
85
  modalVisible={endcallVisible}
82
86
  />
83
- <IconButton {...iconButtonProps} />
87
+ {isToolbarMenuItem ? (
88
+ <ToolbarMenuItem {...iconButtonProps} />
89
+ ) : (
90
+ <IconButton {...iconButtonProps} />
91
+ )}
84
92
  </>
85
93
  );
86
94
  };
@@ -4,6 +4,8 @@ import {PropsContext, ToggleState} from '../../agora-rn-uikit';
4
4
  import Styles from '../components/styles';
5
5
  import {useLocalUserInfo, useRtc} from 'customization-api';
6
6
  import IconButton, {IconButtonProps} from '../atoms/IconButton';
7
+ import {useToolbarMenu} from '../utils/useMenu';
8
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
7
9
 
8
10
  export interface LocalSwitchCameraProps {
9
11
  showLabel?: boolean;
@@ -12,6 +14,7 @@ export interface LocalSwitchCameraProps {
12
14
  }
13
15
 
14
16
  function LocalSwitchCamera(props: LocalSwitchCameraProps) {
17
+ const {isToolbarMenuItem} = useToolbarMenu();
15
18
  const {callbacks} = useContext(PropsContext);
16
19
  const {RtcEngineUnsafe} = useRtc();
17
20
  const local = useLocalUserInfo();
@@ -39,6 +42,8 @@ function LocalSwitchCamera(props: LocalSwitchCameraProps) {
39
42
 
40
43
  return props?.render ? (
41
44
  props.render(onPress, isVideoEnabled)
45
+ ) : isToolbarMenuItem ? (
46
+ <ToolbarMenuItem {...iconButtonProps} />
42
47
  ) : (
43
48
  <IconButton {...iconButtonProps} />
44
49
  );
@@ -25,6 +25,9 @@ import IconButton, {IconButtonProps} from '../atoms/IconButton';
25
25
  import ThemeConfig from '../theme';
26
26
  import {ImageIconProps} from '../atoms/ImageIcon';
27
27
  import useIsHandRaised from '../utils/useIsHandRaised';
28
+ import {useToolbarMenu} from '../utils/useMenu';
29
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
30
+
28
31
  /**
29
32
  * A component to mute / unmute the local video
30
33
  */
@@ -45,6 +48,7 @@ export interface LocalVideoMuteProps {
45
48
 
46
49
  function LocalVideoMute(props: LocalVideoMuteProps) {
47
50
  const {rtcProps} = useContext(PropsContext);
51
+ const {isToolbarMenuItem} = useToolbarMenu();
48
52
  const {
49
53
  data: {isHost},
50
54
  } = useRoomInfo();
@@ -152,6 +156,8 @@ function LocalVideoMute(props: LocalVideoMuteProps) {
152
156
  }
153
157
  return props?.render ? (
154
158
  props.render(onPress, isVideoEnabled)
159
+ ) : isToolbarMenuItem ? (
160
+ <ToolbarMenuItem {...iconButtonProps} />
155
161
  ) : (
156
162
  <IconButton {...iconButtonProps} />
157
163
  );
@@ -13,6 +13,8 @@ import React from 'react';
13
13
  import {useRecording} from './recording/useRecording';
14
14
  import IconButton, {IconButtonProps} from '../atoms/IconButton';
15
15
  import {useVideoCall} from '../components/useVideoCall';
16
+ import {useToolbarMenu} from '../utils/useMenu';
17
+ import ToolbarMenuItem from '../atoms/ToolbarMenuItem';
16
18
 
17
19
  export interface RecordingButtonProps {
18
20
  showLabel?: boolean;
@@ -21,6 +23,7 @@ export interface RecordingButtonProps {
21
23
  }
22
24
 
23
25
  const Recording = (props: RecordingButtonProps) => {
26
+ const {isToolbarMenuItem} = useToolbarMenu();
24
27
  const {startRecording, inProgress, isRecordingActive} = useRecording();
25
28
  //commented for v1 release
26
29
  //const recordingButton = useString<boolean>('recordingButton');
@@ -55,10 +58,10 @@ const Recording = (props: RecordingButtonProps) => {
55
58
 
56
59
  return props?.render ? (
57
60
  props.render(onPress, isRecordingActive)
61
+ ) : isToolbarMenuItem ? (
62
+ <ToolbarMenuItem {...iconButtonProps} />
58
63
  ) : (
59
- <>
60
- <IconButton {...iconButtonProps} />
61
- </>
64
+ <IconButton {...iconButtonProps} />
62
65
  );
63
66
  };
64
67
 
@@ -21,11 +21,15 @@ import ThemeConfig from '../../../theme';
21
21
  import {ClientRole, PropsContext} from '../../../../agora-rn-uikit';
22
22
  import {useContent} from 'customization-api';
23
23
  import {isMobileUA} from '../../../utils/common';
24
+ import {IconButtonProps} from '../../../atoms/IconButton';
25
+ import {useToolbarMenu} from '../../../utils/useMenu';
26
+ import ToolbarMenuItem from '../../../atoms/ToolbarMenuItem';
24
27
 
25
28
  interface LocalRaiseHandProps {
26
29
  showLabel?: boolean;
27
30
  }
28
31
  const LocalRaiseHand = (props: LocalRaiseHandProps) => {
32
+ const {isToolbarMenuItem} = useToolbarMenu();
29
33
  const {audienceSendsRequest, audienceRecallsRequest, raiseHandList} =
30
34
  useContext(LiveStreamContext);
31
35
  const {rtcProps} = useContext(PropsContext);
@@ -37,30 +41,33 @@ const LocalRaiseHand = (props: LocalRaiseHandProps) => {
37
41
  const handStatusText = (toggle: boolean) =>
38
42
  toggle ? 'Lower hand' : 'Raise Hand';
39
43
  const isHandRasied = raiseHandList[localUid]?.raised === RaiseHandValue.TRUE;
40
- return (
41
- <IconButton
42
- iconProps={{
43
- name: isHandRasied ? 'lower-hand' : 'raise-hand',
44
- tintColor: isHandRasied
45
- ? $config.PRIMARY_ACTION_TEXT_COLOR
46
- : $config.SECONDARY_ACTION_COLOR,
47
- iconBackgroundColor: isHandRasied
48
- ? $config.PRIMARY_ACTION_BRAND_COLOR
49
- : '',
50
- base64: isMobileUA() ? true : false,
51
- }}
52
- btnTextProps={{
53
- text: showLabel ? handStatusText(isHandRasied) : '',
54
- textColor: $config.FONT_COLOR,
55
- }}
56
- onPress={() => {
57
- if (isHandRasied) {
58
- audienceRecallsRequest();
59
- } else {
60
- audienceSendsRequest();
61
- }
62
- }}
63
- />
44
+ const iconButtonProps: IconButtonProps = {
45
+ iconProps: {
46
+ name: isHandRasied ? 'lower-hand' : 'raise-hand',
47
+ tintColor: isHandRasied
48
+ ? $config.PRIMARY_ACTION_TEXT_COLOR
49
+ : $config.SECONDARY_ACTION_COLOR,
50
+ iconBackgroundColor: isHandRasied
51
+ ? $config.PRIMARY_ACTION_BRAND_COLOR
52
+ : '',
53
+ base64: isMobileUA() ? true : false,
54
+ },
55
+ btnTextProps: {
56
+ text: showLabel ? handStatusText(isHandRasied) : '',
57
+ textColor: $config.FONT_COLOR,
58
+ },
59
+ onPress: () => {
60
+ if (isHandRasied) {
61
+ audienceRecallsRequest();
62
+ } else {
63
+ audienceSendsRequest();
64
+ }
65
+ },
66
+ };
67
+ return isToolbarMenuItem ? (
68
+ <ToolbarMenuItem {...iconButtonProps} />
69
+ ) : (
70
+ <IconButton {...iconButtonProps} />
64
71
  );
65
72
  };
66
73
 
@@ -19,6 +19,8 @@ import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
19
19
  import {PropsContext, ClientRole} from '../../../agora-rn-uikit';
20
20
  import {useLocalUserInfo, useRoomInfo} from 'customization-api';
21
21
  import useIsHandRaised from '../../utils/useIsHandRaised';
22
+ import {useToolbarMenu} from '../../utils/useMenu';
23
+ import ToolbarMenuItem from '../../atoms/ToolbarMenuItem';
22
24
  /**
23
25
  * A component to start and stop screen sharing on web clients.
24
26
  * Screen sharing is not yet implemented on mobile platforms.
@@ -30,6 +32,7 @@ export interface ScreenshareButtonProps {
30
32
  }
31
33
 
32
34
  const ScreenshareButton = (props: ScreenshareButtonProps) => {
35
+ const {isToolbarMenuItem} = useToolbarMenu();
33
36
  const {rtcProps} = useContext(PropsContext);
34
37
  const {
35
38
  data: {isHost},
@@ -84,6 +87,8 @@ const ScreenshareButton = (props: ScreenshareButtonProps) => {
84
87
 
85
88
  return props?.render ? (
86
89
  props.render(onPress, isScreenshareActive)
90
+ ) : isToolbarMenuItem ? (
91
+ <ToolbarMenuItem {...iconButtonProps} />
87
92
  ) : (
88
93
  <IconButton {...iconButtonProps} />
89
94
  );
@@ -0,0 +1,31 @@
1
+ /*
2
+ ********************************************
3
+ Copyright © 2021 Agora Lab, Inc., all rights reserved.
4
+ AppBuilder and all associated components, source code, APIs, services, and documentation
5
+ (the “Materials”) are owned by Agora Lab, Inc. and its licensors. The Materials may not be
6
+ accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
7
+ Use without a license or in violation of any license terms and conditions (including use for
8
+ any purpose competitive to Agora Lab, Inc.’s business) is strictly prohibited. For more
9
+ information visit https://appbuilder.agora.io.
10
+ *********************************************
11
+ */
12
+
13
+ import React from 'react';
14
+ import {createHook} from 'customization-implementation';
15
+
16
+ const ToolbarMenuContext = React.createContext({isToolbarMenuItem: false});
17
+
18
+ export interface ToolbarMenuProviderProps {
19
+ children: React.ReactNode;
20
+ }
21
+ const ToolbarMenuProvider = (props: ToolbarMenuProviderProps) => {
22
+ return (
23
+ <ToolbarMenuContext.Provider value={{isToolbarMenuItem: true}}>
24
+ {props.children}
25
+ </ToolbarMenuContext.Provider>
26
+ );
27
+ };
28
+
29
+ const useToolbarMenu = createHook(ToolbarMenuContext);
30
+
31
+ export {ToolbarMenuProvider, useToolbarMenu};