agora-appbuilder-core 4.0.0-beta.0 → 4.0.0-beta.10

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.
Files changed (50) hide show
  1. package/package.json +2 -2
  2. package/template/agora-rn-uikit/src/Rtc/Create.tsx +25 -22
  3. package/template/android/app/src/main/AndroidManifest.xml +20 -26
  4. package/template/android/app/src/main/assets/fonts/icomoon.ttf +0 -0
  5. package/template/bridge/rtc/webNg/RtcEngine.ts +22 -2
  6. package/template/global.d.ts +2 -2
  7. package/template/index.rsdk.tsx +1 -0
  8. package/template/index.wsdk.tsx +1 -1
  9. package/template/ios/HelloWorld/Info.plist +1 -1
  10. package/template/ios/HelloWorld.xcodeproj/project.pbxproj +17 -0
  11. package/template/react-native-toast-message/src/components/checkbox.js +9 -3
  12. package/template/src/AppWrapper.tsx +1 -3
  13. package/template/src/assets/font-styles.css +3 -1
  14. package/template/src/atoms/Dropdown.tsx +1 -1
  15. package/template/src/atoms/PrimaryButton.tsx +1 -1
  16. package/template/src/atoms/Toggle.tsx +1 -1
  17. package/template/src/components/Controls.tsx +1 -0
  18. package/template/src/components/DeviceConfigure.tsx +52 -11
  19. package/template/src/components/DeviceContext.tsx +6 -6
  20. package/template/src/components/NetworkQualityContext.tsx +3 -3
  21. package/template/src/components/PinnedVideo.tsx +9 -1
  22. package/template/src/components/Precall.native.tsx +1 -1
  23. package/template/src/components/Precall.tsx +1 -1
  24. package/template/src/components/SettingsView.tsx +1 -1
  25. package/template/src/components/participants/Participant.tsx +2 -2
  26. package/template/src/components/precall/LocalMute.tsx +8 -3
  27. package/template/src/components/precall/PreCallSettings.tsx +1 -1
  28. package/template/src/pages/Authenticate.tsx +1 -1
  29. package/template/src/pages/Create.tsx +1 -1
  30. package/template/src/pages/video-call/ActionSheet.native.tsx +1 -1
  31. package/template/src/pages/video-call/ActionSheet.tsx +1 -1
  32. package/template/src/pages/video-call/ActionSheetContent.tsx +6 -6
  33. package/template/src/pages/video-call/ActionSheetHandle.tsx +1 -1
  34. package/template/src/pages/video-call/VideoCallMobileView.tsx +41 -39
  35. package/template/src/pages/video-call/VideoRenderer.tsx +104 -98
  36. package/template/src/subComponents/ChatInput.ios.tsx +1 -1
  37. package/template/src/subComponents/ChatInput.tsx +1 -1
  38. package/template/src/subComponents/Illustration.tsx +2 -2
  39. package/template/src/subComponents/LayoutIconDropdown.tsx +2 -1
  40. package/template/src/subComponents/LocalAudioMute.tsx +3 -3
  41. package/template/src/subComponents/LocalSwitchCamera.tsx +2 -5
  42. package/template/src/subComponents/LocalVideoMute.tsx +3 -3
  43. package/template/src/subComponents/RemoteAudioMute.tsx +1 -1
  44. package/template/src/subComponents/RemoteVideoMute.tsx +1 -1
  45. package/template/src/subComponents/SelectDevice.tsx +10 -10
  46. package/template/src/subComponents/ToastConfig.tsx +13 -1
  47. package/template/src/subComponents/chat/ChatParticipants.tsx +1 -1
  48. package/template/src/subComponents/screenshare/ScreenshareButton.tsx +1 -1
  49. package/template/src/utils/useMuteToggleLocal.ts +46 -1
  50. package/template/web/index.html +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "4.0.0-beta.0",
3
+ "version": "4.0.0-beta.10",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -10,7 +10,7 @@
10
10
  "scripts": {
11
11
  "vercel-build": "npm run dev-setup && cd template && npm run web:build && cd .. && npm run copy-vercel",
12
12
  "uikit": "rm -rf template/agora-rn-uikit && git clone https://github.com/AgoraIO-Community/ReactNative-UIKit.git template/agora-rn-uikit && cd template/agora-rn-uikit && git checkout feature/redesign/ui-kit",
13
- "deps": "cd template && npm i && npx react-native link",
13
+ "deps": "cd template && npm i",
14
14
  "dev-setup": "npm run uikit && npm run deps && node devSetup.js",
15
15
  "web-build": "cd template && npm run web:build && cd .. && npm run copy-vercel",
16
16
  "copy-vercel": "cp -r Builds/web template/dist && cp vercel.json template/dist",
@@ -331,31 +331,34 @@ const Create = ({
331
331
  });
332
332
 
333
333
  engine.current.addListener('AudioVolumeIndication', (...args) => {
334
- const [remoteUserVolumes, localUserVolume] = args;
335
- const localUserObj = {
336
- uid: rtcProps.uid,
337
- volume: localUserVolume,
338
- };
339
- const volumes = [...remoteUserVolumes, localUserObj];
340
- /* finding obj with highest volume level from local & remote users*/
341
- const highestvolumeObj = volumes.reduce(function (prev, current) {
342
- return prev.volume > current.volume ? prev : current;
343
- });
344
-
345
- const activeSpeakerUid = highestvolumeObj
346
- ? highestvolumeObj.uid
347
- : undefined;
348
- // console.log('highest volume obj', highestvolumeObj);
349
-
350
- highestvolumeObj.volume > 0 &&
351
- dispatch({
352
- type: 'ActiveSpeakerDetected',
353
- value: [activeSpeakerUid],
354
- });
334
+ // console.log('-- AudioVolumeCallback', args);
335
+ const [speakers, totalVolume] = args;
336
+ if (speakers[0]?.uid === 0) {
337
+ //callback for local user
338
+ const isLocalUserSpeaking = speakers[0].vad; //1-speaking , 0-not speaking
339
+ const localUserVolumeLevel = speakers[0].volume;
340
+ // vad value is not consistent while speaking so using volume level
341
+ if (localUserVolumeLevel > 0) {
342
+ dispatch({
343
+ type: 'ActiveSpeakerDetected',
344
+ value: [rtcProps.uid],
345
+ });
346
+ } else {
347
+ dispatch({
348
+ type: 'ActiveSpeakerDetected',
349
+ value: [undefined],
350
+ });
351
+ }
352
+ } else {
353
+ // remote users callback, this will be handeled in ActiveSpeaker callback(367)
354
+ // const highestvolumeObj = speakers.reduce(function (prev, current) {
355
+ // return prev.volume > current.volume ? prev : current;
356
+ // }, null);
357
+ }
355
358
  });
356
359
 
357
360
  engine.current.addListener('ActiveSpeaker', (...args) => {
358
- // used as a callback from the web bridge
361
+ // used as a callback from the web bridge as well remote users
359
362
  dispatch({
360
363
  type: 'ActiveSpeakerDetected',
361
364
  value: args,
@@ -1,40 +1,34 @@
1
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
1
+ <manifest
2
+ xmlns:android="http://schemas.android.com/apk/res/android"
2
3
  package="com.helloworld">
3
-
4
- <uses-permission android:name="android.permission.INTERNET" />
5
- <!-- for bg audio , foreground service -->
6
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
7
- <uses-permission android:name="android.permission.WAKE_LOCK" />
8
-
9
- <application
4
+ <uses-permission android:name="android.permission.INTERNET" />
5
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
6
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
7
+ <application
10
8
  android:name=".MainApplication"
11
9
  android:label="@string/app_name"
12
10
  android:icon="@mipmap/ic_launcher"
13
11
  android:roundIcon="@mipmap/ic_launcher_round"
14
12
  android:allowBackup="false"
15
13
  android:theme="@style/AppTheme">
16
-
17
- <!-- for bg audio , foreground service -->
18
- <meta-data android:name="com.supersami.foregroundservice.notification_channel_name" android:value="AppBuilder"/>
19
- <meta-data android:name="com.supersami.foregroundservice.notification_channel_description" android:value="AppBuilder is running"/>
20
- <meta-data android:name="com.supersami.foregroundservice.notification_color" android:resource="@color/blue"/>
21
- <service android:name="com.supersami.foregroundservice.ForegroundService"></service>
22
- <service android:name="com.supersami.foregroundservice.ForegroundServiceTask"></service>
23
-
24
- <activity
14
+ <activity
25
15
  android:name=".MainActivity"
26
16
  android:label="@string/app_name"
27
17
  android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
28
18
  android:launchMode="singleTask"
29
19
  android:windowSoftInputMode="adjustResize"
30
20
  android:screenOrientation="portrait"
31
- android:exported="true">
32
- <intent-filter>
33
- <action android:name="android.intent.action.MAIN" />
34
- <category android:name="android.intent.category.LAUNCHER" />
35
- </intent-filter>
36
- </activity>
37
- <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
38
- </application>
39
-
21
+ android:exported="true">
22
+ <intent-filter>
23
+ <action android:name="android.intent.action.MAIN" />
24
+ <category android:name="android.intent.category.LAUNCHER" />
25
+ </intent-filter>
26
+ </activity>
27
+ <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
28
+ <meta-data android:name="com.supersami.foregroundservice.notification_channel_name" android:value="AppBuilder"/>
29
+ <meta-data android:name="com.supersami.foregroundservice.notification_channel_description" android:value="AppBuilder is running"/>
30
+ <meta-data android:name="com.supersami.foregroundservice.notification_color" android:resource="@color/blue"/>
31
+ <service android:name="com.supersami.foregroundservice.ForegroundService" />
32
+ <service android:name="com.supersami.foregroundservice.ForegroundServiceTask" />
33
+ </application>
40
34
  </manifest>
@@ -192,8 +192,8 @@ export default class RtcEngine {
192
192
  private inScreenshare: Boolean = false;
193
193
  private videoProfile: VideoProfile = '480p_9';
194
194
  private isPublished = false;
195
- private isAudioEnabled = true;
196
- private isVideoEnabled = true;
195
+ private isAudioEnabled = false;
196
+ private isVideoEnabled = false;
197
197
  private isAudioPublished = false;
198
198
  private isVideoPublished = false;
199
199
  private isJoined = false;
@@ -229,6 +229,10 @@ export default class RtcEngine {
229
229
  try {
230
230
  let localAudio = await AgoraRTC.createMicrophoneAudioTrack(audioConfig);
231
231
  this.localStream.audio = localAudio;
232
+ this.audioDeviceId = localAudio
233
+ ?.getMediaStreamTrack()
234
+ .getSettings().deviceId;
235
+ this.isAudioEnabled = true;
232
236
  } catch (e) {
233
237
  let audioError = e;
234
238
  e.status = {audioError};
@@ -262,6 +266,14 @@ export default class RtcEngine {
262
266
  );
263
267
  this.localStream.audio = localAudio;
264
268
  this.localStream.video = localVideo;
269
+ this.audioDeviceId = localAudio
270
+ ?.getMediaStreamTrack()
271
+ .getSettings().deviceId;
272
+ this.videoDeviceId = localVideo
273
+ ?.getMediaStreamTrack()
274
+ .getSettings().deviceId;
275
+ this.isVideoEnabled = true;
276
+ this.isAudioEnabled = true;
265
277
  } catch (e) {
266
278
  let audioError = false;
267
279
  let videoError = false;
@@ -269,12 +281,20 @@ export default class RtcEngine {
269
281
  let localAudio = await AgoraRTC.createMicrophoneAudioTrack(audioConfig);
270
282
 
271
283
  this.localStream.audio = localAudio;
284
+ this.audioDeviceId = localAudio
285
+ ?.getMediaStreamTrack()
286
+ .getSettings().deviceId;
287
+ this.isAudioEnabled = true;
272
288
  } catch (error) {
273
289
  audioError = error;
274
290
  }
275
291
  try {
276
292
  let localVideo = await AgoraRTC.createCameraVideoTrack(videoConfig);
277
293
  this.localStream.video = localVideo;
294
+ this.videoDeviceId = localVideo
295
+ ?.getMediaStreamTrack()
296
+ .getSettings().deviceId;
297
+ this.isVideoEnabled = true;
278
298
  } catch (error) {
279
299
  videoError = error;
280
300
  }
@@ -76,7 +76,7 @@ interface ConfigInterface {
76
76
  PRIMARY_ACTION_TEXT_COLOR: string;
77
77
  SECONDARY_ACTION_COLOR: string;
78
78
  FONT_COLOR: string;
79
- BACKGROUND_IMAGE: string;
79
+ BG: string;
80
80
  BACKGROUND_COLOR: string;
81
81
  VIDEO_AUDIO_TILE_COLOR: string;
82
82
  VIDEO_AUDIO_TILE_OVERLAY_COLOR: string;
@@ -85,7 +85,7 @@ interface ConfigInterface {
85
85
  SEMANTIC_ERROR: string;
86
86
  SEMANTIC_SUCCESS: string;
87
87
  SEMANTIC_WARNING: string;
88
- SEMANTIC_NETRUAL: string;
88
+ SEMANTIC_NEUTRAL: string;
89
89
  INPUT_FIELD_BACKGROUND_COLOR: string;
90
90
  INPUT_FIELD_BORDER_COLOR: string;
91
91
  CARD_LAYER_1_COLOR: string;
@@ -18,6 +18,7 @@ import SDKAppWrapper, {
18
18
  } from './src/SDKAppWrapper';
19
19
  import React from 'react';
20
20
  import * as RN from 'react-native-web';
21
+ import './src/assets/font-styles.css';
21
22
 
22
23
  export * from 'customization-api';
23
24
  export * from 'customization-implementation';
@@ -6,7 +6,7 @@ import SDKAppWrapper, {
6
6
  import SDKEvents from './src/utils/SdkEvents';
7
7
  import React from 'react';
8
8
  import * as RN from 'react-native-web';
9
-
9
+ import './src/assets/font-styles.css';
10
10
  export * from 'customization-api';
11
11
  export * from 'customization-implementation';
12
12
 
@@ -53,7 +53,7 @@
53
53
  <key>NSCameraUsageDescription</key>
54
54
  <string>Camera access</string>
55
55
  <key>NSLocationWhenInUseUsageDescription</key>
56
- <string></string>
56
+ <string/>
57
57
  <key>NSMicrophoneUsageDescription</key>
58
58
  <string>Mic access</string>
59
59
  <key>UIAppFonts</key>
@@ -18,6 +18,8 @@
18
18
  65580BB1266EDC8000B310B6 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65580BB0266EDC8000B310B6 /* File.swift */; };
19
19
  65580BB3266EDD6300B310B6 /* HelloWorld.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 65580BB2266EDCA400B310B6 /* HelloWorld.entitlements */; };
20
20
  81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
21
+ 49B7B61E43464F098E87335F /* icomoon.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FF34150ABA37458FB48221FB /* icomoon.ttf */; };
22
+ 76624C45E19C435BACC727C7 /* SourceSansPro-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E72FF36D2A984B10BA9C6F91 /* SourceSansPro-Regular.ttf */; };
21
23
  /* End PBXBuildFile section */
22
24
 
23
25
  /* Begin PBXContainerItemProxy section */
@@ -56,6 +58,8 @@
56
58
  81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = HelloWorld/LaunchScreen.storyboard; sourceTree = "<group>"; };
57
59
  ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
58
60
  ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
61
+ FF34150ABA37458FB48221FB /* icomoon.ttf */ = {isa = PBXFileReference; name = "icomoon.ttf"; path = "../src/assets/fonts/icomoon.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
62
+ E72FF36D2A984B10BA9C6F91 /* SourceSansPro-Regular.ttf */ = {isa = PBXFileReference; name = "SourceSansPro-Regular.ttf"; path = "../src/assets/fonts/SourceSansPro-Regular.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
59
63
  /* End PBXFileReference section */
60
64
 
61
65
  /* Begin PBXFrameworksBuildPhase section */
@@ -148,6 +152,7 @@
148
152
  00E356EF1AD99517003FC87E /* HelloWorldTests */,
149
153
  83CBBA001A601CBA00E9B192 /* Products */,
150
154
  2D16E6871FA4F8E400B85C8A /* Frameworks */,
155
+ A87D6475B3A64BB58397D417 /* Resources */,
151
156
  );
152
157
  indentWidth = 2;
153
158
  sourceTree = "<group>";
@@ -165,6 +170,16 @@
165
170
  name = Products;
166
171
  sourceTree = "<group>";
167
172
  };
173
+ A87D6475B3A64BB58397D417 /* Resources */ = {
174
+ isa = "PBXGroup";
175
+ children = (
176
+ FF34150ABA37458FB48221FB /* icomoon.ttf */,
177
+ E72FF36D2A984B10BA9C6F91 /* SourceSansPro-Regular.ttf */,
178
+ );
179
+ name = Resources;
180
+ sourceTree = "<group>";
181
+ path = "";
182
+ };
168
183
  /* End PBXGroup section */
169
184
 
170
185
  /* Begin PBXNativeTarget section */
@@ -304,6 +319,8 @@
304
319
  65580BB3266EDD6300B310B6 /* HelloWorld.entitlements in Resources */,
305
320
  81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
306
321
  13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
322
+ 49B7B61E43464F098E87335F /* icomoon.ttf in Resources */,
323
+ 76624C45E19C435BACC727C7 /* SourceSansPro-Regular.ttf in Resources */,
307
324
  );
308
325
  runOnlyForDeploymentPostprocessing = 0;
309
326
  };
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import { View, TouchableOpacity, Text, Pressable } from 'react-native';
3
3
  import PropTypes from 'prop-types';
4
4
  import { stylePropType } from '../utils/prop-types';
@@ -17,6 +17,7 @@ function BaseToast({
17
17
  contentContainerStyle,
18
18
  text1Style,
19
19
  text2Style,
20
+ subTextStyle,
20
21
  activeOpacity,
21
22
  text1NumberOfLines,
22
23
  text2NumberOfLines,
@@ -90,7 +91,7 @@ function BaseToast({
90
91
  marginRight: 8
91
92
  }}
92
93
  />
93
- <Text style={{ color: 'white' }}>{checkbox.text}</Text>
94
+ <Text style={subTextStyle}>{checkbox.text}</Text>
94
95
  </Pressable>
95
96
  )}
96
97
  {primaryBtn || secondaryBtn ? (
@@ -114,6 +115,7 @@ function BaseToast({
114
115
  {...primaryBtn}
115
116
  onPress={(e) => {
116
117
  primaryBtn.onPress(checked, e);
118
+ setChecked(false);
117
119
  }}
118
120
  />
119
121
  )}
@@ -126,6 +128,10 @@ function BaseToast({
126
128
  paddingVertical: 0
127
129
  }}
128
130
  {...secondaryBtn}
131
+ onPress={(e) => {
132
+ secondaryBtn.onPress(checked, e);
133
+ setChecked(false);
134
+ }}
129
135
  />
130
136
  )}
131
137
  </View>
@@ -143,7 +149,7 @@ BaseToast.propTypes = {
143
149
  leadingIcon: PropTypes.node,
144
150
  trailingIcon: PropTypes.node,
145
151
  text1: PropTypes.string,
146
- text2: PropTypes.string || PropTypes.element,
152
+ text2: PropTypes.string || PropTypes.element || PropTypes.any,
147
153
  onPress: PropTypes.func,
148
154
  style: stylePropType,
149
155
  contentContainerStyle: stylePropType,
@@ -75,9 +75,7 @@ const AppWrapper = (props: AppWrapperProps) => {
75
75
 
76
76
  return (
77
77
  <AppRoot>
78
- <ImageBackgroundComp
79
- bg={$config.BACKGROUND_IMAGE}
80
- color={$config.BACKGROUND_COLOR}>
78
+ <ImageBackgroundComp bg={$config.BG} color={$config.BACKGROUND_COLOR}>
81
79
  <SafeAreaView
82
80
  // @ts-ignore textAlign not supported by TS definitions but is applied to web regardless
83
81
  style={[{flex: 1}, Platform.select({web: {textAlign: 'left'}})]}>
@@ -1,6 +1,8 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap");
2
+
1
3
  @font-face {
2
4
  font-family: 'icomoon';
3
- src: url('fonts/icomoon.ttf?6qgqxy') format('truetype');
5
+ src: url('https://dbudicf5k4as1.cloudfront.net/10/icomoon.ttf') format('truetype');
4
6
  font-weight: normal;
5
7
  font-style: normal;
6
8
  font-display: block;
@@ -169,7 +169,7 @@ const Dropdown: FC<Props> = ({
169
169
  iconType="plain"
170
170
  name={icon}
171
171
  iconSize={20}
172
- tintColor={$config.SEMANTIC_NETRUAL}
172
+ tintColor={$config.SEMANTIC_NEUTRAL}
173
173
  />
174
174
  </View>
175
175
  ) : (
@@ -38,7 +38,7 @@ export default function PrimaryButton(props: PrimaryButtonProps) {
38
38
  style={[
39
39
  styles.container,
40
40
  props?.disabled
41
- ? {backgroundColor: $config.SEMANTIC_NETRUAL}
41
+ ? {backgroundColor: $config.SEMANTIC_NEUTRAL}
42
42
  : {backgroundColor: $config.PRIMARY_ACTION_BRAND_COLOR},
43
43
  containerStyle ? containerStyle : {},
44
44
  ]}
@@ -20,7 +20,7 @@ const Toggle = (props: SwitchProps) => {
20
20
  onValueChange={toggleSwitch}
21
21
  disabled={false}
22
22
  backgroundActive={$config.PRIMARY_ACTION_BRAND_COLOR}
23
- backgroundInactive={$config.SEMANTIC_NETRUAL}
23
+ backgroundInactive={$config.SEMANTIC_NEUTRAL}
24
24
  circleActiveColor={$config.CARD_LAYER_1_COLOR}
25
25
  circleInActiveColor={$config.CARD_LAYER_1_COLOR}
26
26
  // renderInsideCircle={() => <CustomComponent />} // custom component to render inside the Switch circle (Text, Image, etc.)
@@ -423,6 +423,7 @@ const style = StyleSheet.create({
423
423
  alignItems: 'center',
424
424
  },
425
425
  centerContent: {
426
+ zIndex: 2,
426
427
  flex: 1,
427
428
  flexDirection: 'row',
428
429
  justifyContent: 'center',
@@ -224,13 +224,22 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
224
224
  }
225
225
  };
226
226
 
227
+ useEffect(() => {
228
+ const interval = setInterval(() => {
229
+ navigator.mediaDevices.enumerateDevices();
230
+ }, 2000);
231
+ return () => {
232
+ clearInterval(interval);
233
+ };
234
+ }, []);
235
+
227
236
  useEffect(() => {
228
237
  // Labels are empty in firefox when permission is granted first time
229
238
  // refresh device list if labels are empty
230
239
 
231
240
  const logTag = 'useEffect[rtc,store]';
232
241
 
233
- if (activeDeviceId && deviceList.length !== 0) {
242
+ if (activeDeviceId && deviceList.length > 0) {
234
243
  // If stream exists and selected devices are empty, check for devices again
235
244
  if (!selectedCam || selectedCam.trim().length == 0) {
236
245
  log(logTag, 'cam: Device list populated but No selected cam');
@@ -307,6 +316,7 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
307
316
  const commonOnChangedEvent = async (changedDeviceData: DeviceInfo) => {
308
317
  // Extracted devicelist because we want to perform fallback with
309
318
  // the most current version.
319
+ const previousDeviceList = deviceList;
310
320
  const updatedDeviceList = await refreshDeviceList();
311
321
  const changedDevice = changedDeviceData.device;
312
322
 
@@ -330,7 +340,40 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
330
340
 
331
341
  log(logTag, changedDeviceData);
332
342
 
333
- if (changedDeviceData.state === 'ACTIVE') {
343
+ if (currentDevice === 'default') {
344
+ // const previousDefaultDevice = previousDeviceList.find(
345
+ // (device) => device.deviceId === 'default',
346
+ // );
347
+ // const currentDefaultDevice = updatedDeviceList.find(
348
+ // (device) => device.deviceId === 'default',
349
+ // );
350
+ // log(logTag, 'current Default device', {
351
+ // changedDeviceData,
352
+ // previousDeviceList,
353
+ // updatedDeviceList,
354
+ // previousDefaultDevice,
355
+ // currentDefaultDevice,
356
+ // });
357
+ // if (previousDefaultDevice.groupId !== currentDefaultDevice.groupId) {
358
+ // log(logTag, 'Default device changed', {
359
+ // changedDeviceData,
360
+ // previousDeviceList,
361
+ // updatedDeviceList,
362
+ // previousDefaultDevice,
363
+ // currentDefaultDevice,
364
+ // });
365
+ // setCurrentDevice('default');
366
+ // }
367
+ setCurrentDevice('default');
368
+ }
369
+
370
+ const didChangeDeviceExistBefore = previousDeviceList.find(
371
+ (device) => device.deviceId === changedDevice.deviceId,
372
+ )
373
+ ? true
374
+ : false;
375
+
376
+ if (changedDeviceData.state === 'ACTIVE' && !didChangeDeviceExistBefore) {
334
377
  const rememberedDevice =
335
378
  rememberedDevicesList[changedDevice.kind][changedDevice.deviceId];
336
379
 
@@ -348,24 +391,22 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
348
391
  return;
349
392
  }
350
393
  }
351
- if (selectedMic === 'default') {
352
- setCurrentDevice('default');
353
- }
354
394
  };
355
395
 
356
396
  // Port this to useEffectEvent(https://beta.reactjs.org/reference/react/useEffectEvent) when
357
397
  // released
358
398
  useEffect(() => {
399
+ log('previous devicelist updated', deviceList);
359
400
  AgoraRTC.onMicrophoneChanged = commonOnChangedEvent;
360
- }, [selectedMic]);
401
+ }, [selectedMic, deviceList]);
361
402
 
362
403
  useEffect(() => {
363
404
  AgoraRTC.onPlaybackDeviceChanged = commonOnChangedEvent;
364
- }, [selectedSpeaker]);
405
+ }, [selectedSpeaker, deviceList]);
365
406
 
366
407
  useEffect(() => {
367
408
  AgoraRTC.onCameraChanged = commonOnChangedEvent;
368
- }, [selectedCam]);
409
+ }, [selectedCam, deviceList]);
369
410
 
370
411
  const setSelectedMic = (deviceId: deviceId) => {
371
412
  log('mic: setting to', deviceId);
@@ -375,7 +416,7 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
375
416
  () => {
376
417
  syncSelectedDeviceUi('audioinput');
377
418
  updateActiveDeviceId('audioinput', deviceId);
378
- res();
419
+ res(null);
379
420
  },
380
421
  (e: any) => {
381
422
  console.error('DeviceConfigure: Error setting mic', e);
@@ -393,7 +434,7 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
393
434
  () => {
394
435
  syncSelectedDeviceUi('videoinput');
395
436
  updateActiveDeviceId('videoinput', deviceId);
396
- res();
437
+ res(null);
397
438
  },
398
439
  (e: any) => {
399
440
  console.error('Device Configure: Error setting webcam', e);
@@ -411,7 +452,7 @@ const DeviceConfigure: React.FC<Props> = (props: any) => {
411
452
  () => {
412
453
  setUiSelectedSpeaker(deviceId);
413
454
  updateActiveDeviceId('audiooutput', deviceId);
414
- res();
455
+ res(null);
415
456
  },
416
457
  (e: any) => {
417
458
  console.error('Device Configure: Error setting speaker', e);
@@ -13,11 +13,11 @@ import {createContext} from 'react';
13
13
 
14
14
  interface DeviceContext {
15
15
  selectedCam: string;
16
- setSelectedCam: (cam: string) => void;
16
+ setSelectedCam: (cam: string) => Promise<any>;
17
17
  selectedMic: string;
18
- setSelectedMic: (mic: string) => void;
18
+ setSelectedMic: (mic: string) => Promise<any>;
19
19
  selectedSpeaker: string;
20
- setSelectedSpeaker: (speaker: string) => void;
20
+ setSelectedSpeaker: (speaker: string) => Promise<any>;
21
21
  deviceList: MediaDeviceInfo[];
22
22
  setDeviceList: (devices: MediaDeviceInfo[]) => void;
23
23
  }
@@ -27,9 +27,9 @@ const DeviceContext = createContext<DeviceContext>({
27
27
  selectedMic: '',
28
28
  selectedSpeaker: '',
29
29
  deviceList: [],
30
- setSelectedCam: () => {},
31
- setSelectedMic: () => {},
32
- setSelectedSpeaker: () => {},
30
+ setSelectedCam: async () => {},
31
+ setSelectedMic: async () => {},
32
+ setSelectedSpeaker: async () => {},
33
33
  setDeviceList: () => {},
34
34
  });
35
35
  export default DeviceContext;
@@ -37,7 +37,7 @@ export const networkIconsObject: {
37
37
  } = {
38
38
  0: {
39
39
  icon: 'connection-unsupported',
40
- tint: $config.SEMANTIC_NETRUAL,
40
+ tint: $config.SEMANTIC_NEUTRAL,
41
41
  text: 'unknown',
42
42
  },
43
43
  1: {
@@ -72,12 +72,12 @@ export const networkIconsObject: {
72
72
  },
73
73
  7: {
74
74
  icon: 'connection-unpublished',
75
- tint: $config.SEMANTIC_NETRUAL,
75
+ tint: $config.SEMANTIC_NEUTRAL,
76
76
  text: 'unpublished',
77
77
  },
78
78
  8: {
79
79
  icon: 'connection-loading',
80
- tint: $config.SEMANTIC_NETRUAL,
80
+ tint: $config.SEMANTIC_NEUTRAL,
81
81
  text: 'loading',
82
82
  },
83
83
  };
@@ -127,10 +127,18 @@ const PinnedVideo: layoutComponent = ({renderData}) => {
127
127
  }
128
128
  return (
129
129
  <Pressable
130
+ //old
130
131
  //if user pinned somebody then side panel items should not be clickable - swap video should be called
131
132
  //instead we will show replace pin button on hovering the video tile
133
+ //old
132
134
  disabled={
133
- activeSpeaker || pinnedUid || screenShareOn ? true : false
135
+ //old fix
136
+ //activeSpeaker || pinnedUid || screenShareOn ? true : false
137
+ //old fix
138
+
139
+ //latest fix : pinned video sidepanel layout should not be clickable
140
+ //if user hover on it we will show pin for me/replace pin(if someone already pinned) button
141
+ true
134
142
  }
135
143
  style={
136
144
  isSidePinnedlayout
@@ -379,7 +379,7 @@ const style = StyleSheet.create({
379
379
  fontWeight: '400',
380
380
  fontSize: ThemeConfig.FontSize.small,
381
381
  lineHeight: 18,
382
- color: $config.SEMANTIC_NETRUAL,
382
+ color: $config.SEMANTIC_NEUTRAL,
383
383
  textAlign: 'left',
384
384
  },
385
385
  btnContainerStyle: {maxWidth: 337, alignSelf: 'center', marginTop: 50},
@@ -382,7 +382,7 @@ const style = StyleSheet.create({
382
382
  fontWeight: '400',
383
383
  fontSize: ThemeConfig.FontSize.small,
384
384
  lineHeight: 18,
385
- color: $config.SEMANTIC_NETRUAL,
385
+ color: $config.SEMANTIC_NEUTRAL,
386
386
  textAlign: 'left',
387
387
  },
388
388
  btnContainerStyle: {maxWidth: 337, alignSelf: 'center', marginTop: 50},
@@ -116,7 +116,7 @@ const EditName: React.FC = (props?: EditNameProps) => {
116
116
  name="person"
117
117
  iconSize={20}
118
118
  iconType="plain"
119
- tintColor={$config.SEMANTIC_NETRUAL}
119
+ tintColor={$config.SEMANTIC_NEUTRAL}
120
120
  />
121
121
  <TextInput
122
122
  maxLength={maxInputLimit}