agora-appbuilder-core 4.1.0-beta-2 → 4.1.0-beta-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 +1 -1
- package/template/customization-api/atoms.ts +1 -0
- package/template/customization-api/sub-components.ts +2 -0
- package/template/src/ai-agent/components/AgentControls/AgentContext.tsx +16 -1
- package/template/src/ai-agent/components/AgentControls/const.ts +38 -5
- package/template/src/ai-agent/components/AgentControls/index.tsx +40 -23
- package/template/src/ai-agent/components/AudioVisualizer.tsx +32 -20
- package/template/src/ai-agent/components/Bottombar.tsx +113 -48
- package/template/src/ai-agent/components/{CustomSidePanel.tsx → CustomChatPanel.tsx} +3 -3
- package/template/src/ai-agent/components/CustomCreate.tsx +7 -185
- package/template/src/ai-agent/components/CustomSettingsPanel.tsx +155 -0
- package/template/src/ai-agent/components/SelectAiAgent.tsx +71 -0
- package/template/src/ai-agent/components/SelectAiAgentVoice.tsx +68 -0
- package/template/src/ai-agent/components/agent-chat-panel/agent-chat-ui.tsx +3 -3
- package/template/src/ai-agent/components/mobile/MobileLayoutComponent.tsx +1 -1
- package/template/src/ai-agent/components/mobile/Topbar.tsx +10 -26
- package/template/src/ai-agent/index.tsx +48 -199
- package/template/src/atoms/Dropdown.tsx +1 -1
- package/template/src/components/SettingsView.tsx +7 -3
- package/template/src/components/room-info/useRoomInfo.tsx +10 -0
- package/template/src/pages/video-call/VideoCallScreen.tsx +18 -3
- package/template/src/subComponents/FallbackLogo.tsx +1 -3
- package/template/src/subComponents/SelectDevice.tsx +7 -7
- package/template/src/subComponents/SidePanelHeader.tsx +2 -2
- package/template/src/utils/useJoinRoom.ts +6 -0
- package/template/src/ai-agent/components/CustomCreateNative.tsx +0 -265
package/package.json
CHANGED
|
@@ -7,3 +7,4 @@ export {default as PrimaryButton} from '../src/atoms/PrimaryButton';
|
|
|
7
7
|
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
|
+
export {default as Dropdown} from '../src/atoms/Dropdown';
|
|
@@ -91,3 +91,5 @@ export {default as Loading} from '../src/subComponents/Loading';
|
|
|
91
91
|
export {default as UserAvatar} from '../src/atoms/UserAvatar';
|
|
92
92
|
export {default as Card} from '../src/atoms/Card';
|
|
93
93
|
export {default as ThemeConfig} from '../src/theme';
|
|
94
|
+
export {default as SelectDevice} from '../src/subComponents/SelectDevice';
|
|
95
|
+
export {EditName} from '../src/components/SettingsView';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, {createContext, useState} from 'react';
|
|
2
2
|
import {AIAgentState, AgentState} from './const';
|
|
3
3
|
import {UidType} from 'customization-api';
|
|
4
|
-
|
|
4
|
+
import {AI_AGENT_VOICE} from './const';
|
|
5
5
|
export interface ChatItem {
|
|
6
6
|
id: string;
|
|
7
7
|
uid: UidType;
|
|
@@ -22,6 +22,10 @@ export interface AgentContextInterface {
|
|
|
22
22
|
setAgentUID: (uid: UidType | null) => void;
|
|
23
23
|
chatItems: ChatItem[];
|
|
24
24
|
addChatItem: (newItem: ChatItem) => void;
|
|
25
|
+
agentId: string;
|
|
26
|
+
setAgentId: (id: string) => void;
|
|
27
|
+
agentVoice?: keyof typeof AI_AGENT_VOICE | '';
|
|
28
|
+
setAgentVoice: (voice: keyof typeof AI_AGENT_VOICE) => void;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
export const AgentContext = createContext<AgentContextInterface>({
|
|
@@ -35,6 +39,10 @@ export const AgentContext = createContext<AgentContextInterface>({
|
|
|
35
39
|
setAgentUID: () => {},
|
|
36
40
|
chatItems: [],
|
|
37
41
|
addChatItem: () => {}, // Default no-op
|
|
42
|
+
agentVoice: '',
|
|
43
|
+
setAgentVoice: () => {},
|
|
44
|
+
agentId: '',
|
|
45
|
+
setAgentId: () => {},
|
|
38
46
|
});
|
|
39
47
|
|
|
40
48
|
/**
|
|
@@ -74,6 +82,9 @@ export const AgentProvider: React.FC<{children: React.ReactNode}> = ({
|
|
|
74
82
|
const [agentUID, setAgentUID] = useState<UidType | null>(null);
|
|
75
83
|
const [isSubscribedForStreams, setIsSubscribedForStreams] = useState(false);
|
|
76
84
|
const [chatItems, setChatItems] = useState<ChatItem[]>([]);
|
|
85
|
+
const [agentId, setAgentId] = useState('');
|
|
86
|
+
const [agentVoice, setAgentVoice] =
|
|
87
|
+
useState<AgentContextInterface['agentVoice']>('');
|
|
77
88
|
|
|
78
89
|
/**
|
|
79
90
|
* Adds a new chat item to the chat state while ensuring:
|
|
@@ -155,6 +166,10 @@ export const AgentProvider: React.FC<{children: React.ReactNode}> = ({
|
|
|
155
166
|
setAgentUID,
|
|
156
167
|
chatItems,
|
|
157
168
|
addChatItem, // Expose the function in the context
|
|
169
|
+
agentId,
|
|
170
|
+
setAgentId,
|
|
171
|
+
agentVoice,
|
|
172
|
+
setAgentVoice,
|
|
158
173
|
};
|
|
159
174
|
|
|
160
175
|
return (
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {isMobileUA} from '../../../utils/common';
|
|
2
2
|
|
|
3
3
|
export const AI_AGENT_STATE = {
|
|
4
|
-
NOT_CONNECTED: '
|
|
5
|
-
REQUEST_SENT: isMobileUA() ? '
|
|
6
|
-
AWAITING_JOIN: isMobileUA() ? '
|
|
4
|
+
NOT_CONNECTED: 'Join Call',
|
|
5
|
+
REQUEST_SENT: isMobileUA() ? 'Join Call' : 'Requesting agent join..', // loading - reg
|
|
6
|
+
AWAITING_JOIN: isMobileUA() ? 'Join Call' : 'Agent will join shortly..', // loading
|
|
7
7
|
AGENT_CONNECTED: 'End Call',
|
|
8
|
-
AGENT_REQUEST_FAILED: '
|
|
8
|
+
AGENT_REQUEST_FAILED: 'Join Call',
|
|
9
9
|
AGENT_DISCONNECT_REQUEST: isMobileUA()
|
|
10
10
|
? 'End Call'
|
|
11
11
|
: 'Disconnecting agent...', // loading - req
|
|
12
12
|
AGENT_DISCONNECT_FAILED: 'End Call',
|
|
13
|
-
AWAITING_LEAVE: '
|
|
13
|
+
AWAITING_LEAVE: 'Join Call', // loading
|
|
14
14
|
} as const;
|
|
15
15
|
|
|
16
16
|
export type AIAgentState = keyof typeof AI_AGENT_STATE;
|
|
@@ -56,3 +56,36 @@ export const AGORA_SSO_LOGIN_PATH = '/api/v0/oauth/authorize';
|
|
|
56
56
|
export const AGORA_SSO_LOGOUT_PATH = '/api/v0/logout';
|
|
57
57
|
|
|
58
58
|
export const AGORA_SSO_CLIENT_ID = 'openai_agora';
|
|
59
|
+
|
|
60
|
+
export const AI_AGENT_VOICE = {
|
|
61
|
+
'en-US-AvaMultilingualNeural': 'en-US-AvaMultilingualNeural',
|
|
62
|
+
'en-US-AndrewMultilingualNeural': 'en-US-AndrewMultilingualNeural',
|
|
63
|
+
'en-US-EmmaMultilingualNeural': 'en-US-EmmaMultilingualNeural',
|
|
64
|
+
'en-US-BrianMultilingualNeural': 'en-US-BrianMultilingualNeural',
|
|
65
|
+
'en-US-AvaNeural': 'en-US-AvaNeural',
|
|
66
|
+
'en-US-AndrewNeural': 'en-US-AndrewNeural',
|
|
67
|
+
'en-US-EmmaNeural': 'en-US-EmmaNeural',
|
|
68
|
+
'en-US-BrianNeural': 'en-US-BrianNeural',
|
|
69
|
+
'en-US-JennyNeural': 'en-US-JennyNeural',
|
|
70
|
+
'en-US-GuyNeural': 'en-US-GuyNeural',
|
|
71
|
+
'en-US-AriaNeural': 'en-US-AriaNeural',
|
|
72
|
+
'en-US-DavisNeural': 'en-US-DavisNeural',
|
|
73
|
+
'en-US-JaneNeural': 'en-US-JaneNeural',
|
|
74
|
+
'en-US-JasonNeural': 'en-US-JasonNeural',
|
|
75
|
+
'en-US-SaraNeural': 'en-US-SaraNeural',
|
|
76
|
+
'en-US-TonyNeural': 'en-US-TonyNeural',
|
|
77
|
+
'en-US-NancyNeural': 'en-US-NancyNeural',
|
|
78
|
+
'en-US-AmberNeural': 'en-US-AmberNeural',
|
|
79
|
+
'en-US-AnaNeural': 'en-US-AnaNeural',
|
|
80
|
+
'en-US-AshleyNeural': 'en-US-AshleyNeural',
|
|
81
|
+
'en-US-BrandonNeural': 'en-US-BrandonNeural',
|
|
82
|
+
'en-US-ChristopherNeural': 'en-US-ChristopherNeural',
|
|
83
|
+
'en-US-CoraNeural': 'en-US-CoraNeural',
|
|
84
|
+
'en-US-ElizabethNeural': 'en-US-ElizabethNeural',
|
|
85
|
+
'en-US-EricNeural': 'en-US-EricNeural',
|
|
86
|
+
'en-US-JacobNeural': 'en-US-JacobNeural',
|
|
87
|
+
'en-US-JennyMultilingualNeural4': 'en-US-JennyMultilingualNeural4',
|
|
88
|
+
'en-US-MichelleNeural': 'en-US-MichelleNeural',
|
|
89
|
+
'en-US-MonicaNeural': 'en-US-MonicaNeural',
|
|
90
|
+
'en-US-RogerNeural': 'en-US-RogerNeural',
|
|
91
|
+
};
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
useContent,
|
|
9
9
|
useEndCall,
|
|
10
10
|
useLocalUid,
|
|
11
|
-
useHistory,
|
|
12
11
|
useStorageContext,
|
|
13
12
|
Toast,
|
|
14
13
|
} from 'customization-api';
|
|
@@ -20,6 +19,7 @@ const connectToAIAgent = async (
|
|
|
20
19
|
channel_name: string,
|
|
21
20
|
localUid: UidType,
|
|
22
21
|
agentAuthToken: string,
|
|
22
|
+
data?: {agent_id: string; agent_voice: string},
|
|
23
23
|
): Promise<{}> => {
|
|
24
24
|
// const apiUrl = '/api/proxy';
|
|
25
25
|
const apiUrl = $config.BACKEND_ENDPOINT + '/v1/convoai';
|
|
@@ -27,6 +27,14 @@ const connectToAIAgent = async (
|
|
|
27
27
|
channel_name: channel_name,
|
|
28
28
|
uid: localUid, // user uid // localUid or 0
|
|
29
29
|
};
|
|
30
|
+
|
|
31
|
+
if (data && data.agent_id) {
|
|
32
|
+
requestBody['ai_agent_id'] = data.agent_id;
|
|
33
|
+
}
|
|
34
|
+
if (data && data.agent_voice) {
|
|
35
|
+
requestBody['voice'] = data.agent_voice;
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
console.log({requestBody});
|
|
31
39
|
const headers: HeadersInit = {
|
|
32
40
|
'Content-Type': 'application/json',
|
|
@@ -70,12 +78,13 @@ export const AgentControl: React.FC<{channel_name: string}> = ({
|
|
|
70
78
|
setAgentAuthToken,
|
|
71
79
|
agentUID,
|
|
72
80
|
setAgentUID,
|
|
81
|
+
agentVoice,
|
|
82
|
+
agentId,
|
|
73
83
|
} = useContext(AgentContext);
|
|
74
84
|
// console.log("X-Client-ID state", clientId)
|
|
75
85
|
// const { users } = useContext(UserContext)
|
|
76
86
|
const {activeUids: users} = useContent();
|
|
77
87
|
const endcall = useEndCall();
|
|
78
|
-
const history = useHistory();
|
|
79
88
|
const {store} = useStorageContext();
|
|
80
89
|
const localUid = useLocalUid();
|
|
81
90
|
|
|
@@ -103,6 +112,10 @@ export const AgentControl: React.FC<{channel_name: string}> = ({
|
|
|
103
112
|
channel_name,
|
|
104
113
|
localUid,
|
|
105
114
|
store.token,
|
|
115
|
+
{
|
|
116
|
+
agent_id: agentId,
|
|
117
|
+
agent_voice: agentVoice,
|
|
118
|
+
},
|
|
106
119
|
);
|
|
107
120
|
// console.log("response X-Client-ID", newClientId, typeof newClientId)
|
|
108
121
|
// @ts-ignore
|
|
@@ -170,7 +183,10 @@ export const AgentControl: React.FC<{channel_name: string}> = ({
|
|
|
170
183
|
}
|
|
171
184
|
try {
|
|
172
185
|
setAgentConnectionState(AgentState.AGENT_DISCONNECT_REQUEST);
|
|
173
|
-
await connectToAIAgent('stop', channel_name, localUid, store.token
|
|
186
|
+
await connectToAIAgent('stop', channel_name, localUid, store.token, {
|
|
187
|
+
agent_id: agentId,
|
|
188
|
+
agent_voice: agentVoice,
|
|
189
|
+
});
|
|
174
190
|
setAgentConnectionState(AgentState.AWAITING_LEAVE);
|
|
175
191
|
|
|
176
192
|
Toast.show({
|
|
@@ -209,6 +225,7 @@ export const AgentControl: React.FC<{channel_name: string}> = ({
|
|
|
209
225
|
console.log('agent contrl', {users});
|
|
210
226
|
// welcome agent
|
|
211
227
|
const aiAgentUID = users.filter(item => item === agentUID);
|
|
228
|
+
|
|
212
229
|
if (
|
|
213
230
|
aiAgentUID.length &&
|
|
214
231
|
agentConnectionState === AgentState.AWAITING_JOIN
|
|
@@ -249,12 +266,11 @@ export const AgentControl: React.FC<{channel_name: string}> = ({
|
|
|
249
266
|
agentConnectionState === AgentState.AGENT_CONNECTED ||
|
|
250
267
|
agentConnectionState === AgentState.AGENT_DISCONNECT_FAILED;
|
|
251
268
|
|
|
252
|
-
const backgroundColorStyle =
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const fontcolorStyle =
|
|
256
|
-
|
|
257
|
-
: {color: isEndAgent ? '#FF414D' : '#00C2FF'};
|
|
269
|
+
const backgroundColorStyle = {
|
|
270
|
+
backgroundColor: isEndAgent ? $config.SEMANTIC_ERROR : '#0097D4',
|
|
271
|
+
};
|
|
272
|
+
const fontcolorStyle = {color: $config.FONT_COLOR};
|
|
273
|
+
|
|
258
274
|
return (
|
|
259
275
|
<TouchableOpacity
|
|
260
276
|
style={{
|
|
@@ -265,29 +281,30 @@ export const AgentControl: React.FC<{channel_name: string}> = ({
|
|
|
265
281
|
alignItems: 'center',
|
|
266
282
|
gap: 8,
|
|
267
283
|
borderRadius: 40,
|
|
268
|
-
borderWidth: isMobileUA() ? 0 : 1,
|
|
269
|
-
borderColor: isEndAgent ? '#FF414D' : '#00C2FF',
|
|
270
284
|
flexDirection: 'row',
|
|
271
285
|
...backgroundColorStyle,
|
|
272
286
|
}}
|
|
273
287
|
onPress={handleConnectionToggle}
|
|
274
288
|
disabled={isLoading}>
|
|
275
289
|
{isLoading ? (
|
|
276
|
-
<ActivityIndicator
|
|
277
|
-
size="small"
|
|
278
|
-
color={isMobileUA() ? '#FFFFFF' : '#00C2FF'}
|
|
279
|
-
/>
|
|
290
|
+
<ActivityIndicator size="small" color={$config.FONT_COLOR} />
|
|
280
291
|
) : isStartAgent ? (
|
|
281
|
-
<CallIcon fill={
|
|
292
|
+
<CallIcon fill={$config.FONT_COLOR} />
|
|
282
293
|
) : (
|
|
283
|
-
<EndCall fill={
|
|
294
|
+
<EndCall fill={$config.FONT_COLOR} />
|
|
295
|
+
)}
|
|
296
|
+
{!(agentConnectionState === 'AGENT_CONNECTED') ? (
|
|
297
|
+
<Text
|
|
298
|
+
style={{
|
|
299
|
+
fontFamily: ThemeConfig.FontFamily.sansPro,
|
|
300
|
+
fontSize: 18,
|
|
301
|
+
lineHeight: 18,
|
|
302
|
+
fontWeight: '600',
|
|
303
|
+
...fontcolorStyle,
|
|
304
|
+
}}>{`${AI_AGENT_STATE[agentConnectionState]}`}</Text>
|
|
305
|
+
) : (
|
|
306
|
+
<></>
|
|
284
307
|
)}
|
|
285
|
-
|
|
286
|
-
<Text
|
|
287
|
-
style={{
|
|
288
|
-
fontFamily: ThemeConfig.FontFamily.sansPro,
|
|
289
|
-
...fontcolorStyle,
|
|
290
|
-
}}>{`${AI_AGENT_STATE[agentConnectionState]}`}</Text>
|
|
291
308
|
</TouchableOpacity>
|
|
292
309
|
);
|
|
293
310
|
};
|
|
@@ -1,34 +1,46 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {Text, View} from 'react-native';
|
|
2
|
+
import {Text, View, StyleSheet} from 'react-native';
|
|
3
3
|
import {LiveAudioVisualizer} from './react-audio-visualize';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import ThemeConfig from '../../theme';
|
|
5
|
+
import hexadecimalTransparency from '../../utils/hexadecimalTransparency';
|
|
6
|
+
import {Spacer} from 'customization-api';
|
|
6
7
|
|
|
7
8
|
export const DisconnectedView = ({isConnected}) => {
|
|
8
9
|
return (
|
|
9
|
-
<View
|
|
10
|
-
style={
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
display: 'flex',
|
|
14
|
-
alignItems: 'center',
|
|
15
|
-
justifyContent: 'center',
|
|
16
|
-
}}>
|
|
17
|
-
{/* big circle that covers the parent view */}
|
|
18
|
-
{isMobileUA() ? <DisconnectedIconMobile /> : <DisconnectedIconDesktop />}
|
|
19
|
-
<Text
|
|
20
|
-
style={{
|
|
21
|
-
color: '#B3B3B3',
|
|
22
|
-
fontSize: 20,
|
|
23
|
-
fontWeight: '400',
|
|
24
|
-
marginTop: 20,
|
|
25
|
-
}}>
|
|
10
|
+
<View style={DisconnectedViewStyles.container}>
|
|
11
|
+
<View style={DisconnectedViewStyles.circleView} />
|
|
12
|
+
<Spacer size={16} />
|
|
13
|
+
<Text style={DisconnectedViewStyles.textStyle}>
|
|
26
14
|
{isConnected ? '' : 'Not Joined'}
|
|
27
15
|
</Text>
|
|
28
16
|
</View>
|
|
29
17
|
);
|
|
30
18
|
};
|
|
31
19
|
|
|
20
|
+
const DisconnectedViewStyles = StyleSheet.create({
|
|
21
|
+
container: {
|
|
22
|
+
flex: 1,
|
|
23
|
+
backgroundColor: $config.VIDEO_AUDIO_TILE_COLOR,
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
},
|
|
28
|
+
circleView: {
|
|
29
|
+
width: 210,
|
|
30
|
+
height: 210,
|
|
31
|
+
borderRadius: 210 / 2,
|
|
32
|
+
borderWidth: 15,
|
|
33
|
+
borderColor: $config.SEMANTIC_NEUTRAL,
|
|
34
|
+
},
|
|
35
|
+
textStyle: {
|
|
36
|
+
color: $config.FONT_COLOR + hexadecimalTransparency['40%'],
|
|
37
|
+
fontSize: 16,
|
|
38
|
+
lineHeight: 18,
|
|
39
|
+
fontWeight: '400',
|
|
40
|
+
fontFamily: ThemeConfig.FontFamily.sansPro,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
32
44
|
function createSilentAudioTrack(): MediaStreamTrack {
|
|
33
45
|
const audioContext = new (window.AudioContext ||
|
|
34
46
|
(window as any).webkitAudioContext)();
|
|
@@ -3,49 +3,113 @@ import {
|
|
|
3
3
|
ToolbarComponents,
|
|
4
4
|
useSidePanel,
|
|
5
5
|
useRoomInfo,
|
|
6
|
+
IconButton,
|
|
7
|
+
SidePanelType,
|
|
8
|
+
useActionSheet,
|
|
9
|
+
IconButtonProps,
|
|
10
|
+
ToolbarItem,
|
|
6
11
|
} from 'customization-api';
|
|
7
|
-
import ThemeConfig from '../../theme';
|
|
8
12
|
import {isMobileUA} from '../../utils/common';
|
|
9
|
-
import React, {useEffect
|
|
10
|
-
import {Text, View} from 'react-native';
|
|
13
|
+
import React, {useEffect} from 'react';
|
|
11
14
|
import {AgentControl} from './AgentControls';
|
|
12
|
-
import {LogoIcon} from './icons';
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
const CustomSettingButton = () => {
|
|
17
|
+
const {sidePanel, setSidePanel} = useSidePanel();
|
|
18
|
+
|
|
19
|
+
const isPanelActive = sidePanel === 'custom-settings-panel';
|
|
20
|
+
const onPress = () => {
|
|
21
|
+
isPanelActive
|
|
22
|
+
? setSidePanel(SidePanelType.None)
|
|
23
|
+
: setSidePanel('custom-settings-panel');
|
|
24
|
+
};
|
|
25
|
+
const {isOnActionSheet} = useActionSheet();
|
|
26
|
+
let iconButtonProps: IconButtonProps = {
|
|
27
|
+
onPress: onPress,
|
|
28
|
+
|
|
29
|
+
iconProps: {
|
|
30
|
+
name: 'settings',
|
|
31
|
+
tintColor: isPanelActive
|
|
32
|
+
? $config.PRIMARY_ACTION_TEXT_COLOR
|
|
33
|
+
: $config.SECONDARY_ACTION_COLOR,
|
|
34
|
+
iconBackgroundColor: isPanelActive
|
|
35
|
+
? $config.PRIMARY_ACTION_BRAND_COLOR
|
|
36
|
+
: '',
|
|
37
|
+
},
|
|
38
|
+
btnTextProps: {
|
|
39
|
+
text: '',
|
|
40
|
+
textColor: $config.FONT_COLOR,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
iconButtonProps.isOnActionSheet = isOnActionSheet;
|
|
44
|
+
if (isOnActionSheet) {
|
|
45
|
+
iconButtonProps.btnTextProps.textStyle = {
|
|
46
|
+
color: $config.FONT_COLOR,
|
|
47
|
+
marginTop: 8,
|
|
48
|
+
fontSize: 12,
|
|
49
|
+
fontWeight: '400',
|
|
50
|
+
fontFamily: 'Source Sans Pro',
|
|
51
|
+
textAlign: 'center',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return (
|
|
55
|
+
<ToolbarItem>
|
|
56
|
+
{' '}
|
|
57
|
+
<IconButton {...iconButtonProps} />{' '}
|
|
58
|
+
</ToolbarItem>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const CustomTranscriptButton = () => {
|
|
63
|
+
const {sidePanel, setSidePanel} = useSidePanel();
|
|
64
|
+
|
|
65
|
+
const isPanelActive = sidePanel === 'agent-transcript-panel';
|
|
66
|
+
const onPress = () => {
|
|
67
|
+
isPanelActive
|
|
68
|
+
? setSidePanel(SidePanelType.None)
|
|
69
|
+
: setSidePanel('agent-transcript-panel');
|
|
70
|
+
};
|
|
71
|
+
const {isOnActionSheet} = useActionSheet();
|
|
72
|
+
let iconButtonProps: IconButtonProps = {
|
|
73
|
+
onPress: onPress,
|
|
74
|
+
|
|
75
|
+
iconProps: {
|
|
76
|
+
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIpSURBVHgB7dv/TcJAFAfwL8b/ZYRzA5lA3AAmECcAJkAnQCaQDYQJqBPIBnQD2KC+S4+kIem9El+l1O8nuZTQpxzf/r4WgIiIiIiIiKhhOlULsyzryqQv7QHXbdvpdFawJOEMpO2z9thJG1T57uoaFP7RJ9ppqK1NVQLaycShnQ7S7iWkQ1nBTeyvw9rj0F5+v/oYK4gGhOvfIVfRi83UAvr3GJCCASkYkIIBKRiQggEpGJCCASkYkIIBKRiQ4ha2UmlvYTqWFhuUWkhLkA85WHHSZjAcgbAO6EnGVtLwOpHhkj3yIYVTS6mboAbymYlMdjBiuYmlhXCO1iW1X6hJ6EMKI5YBOVl67uS9ssGo6CDVb4Q+OBix3sQ20sFpeP2M8o6OpM7ve9aw5TfnOQxZB+RQfYB/Elqj8TCvYEAKBqRgQAoGpLA+inkJDE/UkB+6/f05F6nxpwyrUNOHIeuApnIm+w5jWf5kyQblNzJ7x7N4qR3J5ANGLDexQx3heOHe+aJk9rp4iSOvl2jopUbduiXv351RezbLgLqyes9Qg3B9NS6Z3Zf5k0Kt74NZQNb7oNfQWcsxHs8p8+eFhWMWjlfHUawL406e8bnmeB6kYEAKBqRgQAoGpNAC2qL9vmMzo48Bh2sgfwvlEoftv+DvxNzHCqJrULgGekF7TbUCdR8UnkQfwnYI49L8glefsvcq/5jFCw+WX/2PWaQlsafriYiIiIiIiBrtB7K/UdV6QM6CAAAAAElFTkSuQmCC',
|
|
77
|
+
tintColor: isPanelActive
|
|
78
|
+
? $config.PRIMARY_ACTION_TEXT_COLOR
|
|
79
|
+
: $config.SECONDARY_ACTION_COLOR,
|
|
80
|
+
iconBackgroundColor: isPanelActive
|
|
81
|
+
? $config.PRIMARY_ACTION_BRAND_COLOR
|
|
82
|
+
: '',
|
|
83
|
+
},
|
|
84
|
+
btnTextProps: {
|
|
85
|
+
text: '',
|
|
86
|
+
textColor: $config.FONT_COLOR,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
iconButtonProps.isOnActionSheet = isOnActionSheet;
|
|
90
|
+
if (isOnActionSheet) {
|
|
91
|
+
iconButtonProps.btnTextProps.textStyle = {
|
|
92
|
+
color: $config.FONT_COLOR,
|
|
93
|
+
marginTop: 8,
|
|
94
|
+
fontSize: 12,
|
|
95
|
+
fontWeight: '400',
|
|
96
|
+
fontFamily: 'Source Sans Pro',
|
|
97
|
+
textAlign: 'center',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
15
100
|
return (
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
alignItems: 'center',
|
|
20
|
-
justifyContent: 'center',
|
|
21
|
-
gap: 8,
|
|
22
|
-
marginRight: 20,
|
|
23
|
-
}}>
|
|
24
|
-
<LogoIcon />
|
|
25
|
-
<Text
|
|
26
|
-
style={{
|
|
27
|
-
color: '#C3C3C3',
|
|
28
|
-
textAlign: 'center',
|
|
29
|
-
fontSize: 18,
|
|
30
|
-
fontStyle: 'normal',
|
|
31
|
-
fontWeight: '600',
|
|
32
|
-
lineHeight: 18,
|
|
33
|
-
fontFamily: ThemeConfig.FontFamily.sansPro,
|
|
34
|
-
}}>
|
|
35
|
-
AI Builder Demo
|
|
36
|
-
</Text>
|
|
37
|
-
</View>
|
|
101
|
+
<ToolbarItem>
|
|
102
|
+
<IconButton {...iconButtonProps} />
|
|
103
|
+
</ToolbarItem>
|
|
38
104
|
);
|
|
39
105
|
};
|
|
40
106
|
|
|
41
107
|
const Bottombar = () => {
|
|
42
|
-
const {MeetingTitleToolbarItem
|
|
43
|
-
ToolbarComponents;
|
|
108
|
+
const {MeetingTitleToolbarItem} = ToolbarComponents;
|
|
44
109
|
const {setSidePanel} = useSidePanel();
|
|
45
110
|
const {data} = useRoomInfo();
|
|
46
|
-
const [clientId, setClientId] = useState<string | null>(null);
|
|
47
111
|
useEffect(() => {
|
|
48
|
-
!isMobileUA() && setSidePanel('
|
|
112
|
+
!isMobileUA() && setSidePanel('custom-settings-panel');
|
|
49
113
|
}, []);
|
|
50
114
|
return (
|
|
51
115
|
<ToolbarPreset
|
|
@@ -54,35 +118,36 @@ const Bottombar = () => {
|
|
|
54
118
|
layout: {hide: true},
|
|
55
119
|
invite: {hide: true},
|
|
56
120
|
more: {hide: true},
|
|
57
|
-
logo: {
|
|
58
|
-
align: 'start',
|
|
59
|
-
order: 0,
|
|
60
|
-
component: () => <LogoComponent />,
|
|
61
|
-
},
|
|
62
121
|
'meeting-title': {
|
|
63
122
|
align: 'start',
|
|
64
123
|
component: MeetingTitleToolbarItem,
|
|
65
124
|
order: 1,
|
|
66
|
-
hide:
|
|
125
|
+
hide: false,
|
|
67
126
|
},
|
|
68
127
|
'participant-count': {
|
|
69
|
-
align: 'start',
|
|
70
|
-
component: ParticipantCountToolbarItem,
|
|
71
|
-
order: 2,
|
|
72
128
|
hide: true,
|
|
73
129
|
},
|
|
74
|
-
|
|
130
|
+
'local-video': {hide: true},
|
|
131
|
+
'local-audio': {align: 'center', order: 1},
|
|
132
|
+
screenshare: {hide: true},
|
|
133
|
+
recording: {hide: true},
|
|
75
134
|
'connect-agent': {
|
|
76
|
-
align: '
|
|
135
|
+
align: 'center',
|
|
77
136
|
label: 'Agent',
|
|
78
137
|
component: () => <AgentControl channel_name={data.channel} />,
|
|
79
|
-
order:
|
|
138
|
+
order: 2,
|
|
139
|
+
},
|
|
140
|
+
'end-call': {align: 'center', order: 3, hide: true},
|
|
141
|
+
'custom-transcript': {
|
|
142
|
+
align: 'end',
|
|
143
|
+
order: 0,
|
|
144
|
+
component: CustomTranscriptButton,
|
|
145
|
+
},
|
|
146
|
+
'custom-settings': {
|
|
147
|
+
align: 'end',
|
|
148
|
+
order: 2,
|
|
149
|
+
component: CustomSettingButton,
|
|
80
150
|
},
|
|
81
|
-
'local-video': {hide: true},
|
|
82
|
-
screenshare: {hide: true},
|
|
83
|
-
recording: {hide: true},
|
|
84
|
-
'local-audio': {align: 'end', order: 1},
|
|
85
|
-
'end-call': {align: 'end', order: 2, hide: true},
|
|
86
151
|
}}
|
|
87
152
|
/>
|
|
88
153
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {StyleSheet} from 'react-native';
|
|
1
|
+
import {StyleSheet, View} from 'react-native';
|
|
2
2
|
import React, {useContext} from 'react';
|
|
3
3
|
import {useRtc} from 'customization-api';
|
|
4
4
|
import {AgentContext} from './AgentControls/AgentContext';
|
|
@@ -118,9 +118,9 @@ const CustomSidePanel = () => {
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
return (
|
|
121
|
-
<
|
|
121
|
+
<View style={styles.container}>
|
|
122
122
|
<ChatScreen />
|
|
123
|
-
</
|
|
123
|
+
</View>
|
|
124
124
|
);
|
|
125
125
|
};
|
|
126
126
|
|