@cloudflare/realtimekit-react-native 0.1.1 → 0.1.2-staging.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.
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/reactnativecore/DyteHelperModule.java +1 -0
- package/android/src/main/java/com/reactnativecore/ForegroundService.java +1 -1
- package/android/src/main/java/com/reactnativecore/NotificationHelper.java +11 -12
- package/ios/RNInCallManager.m +82 -36
- package/ios/screenshare/DyteScreenshareHandler.swift +2 -4
- package/lib/BackgroundHandler.js +15 -5
- package/lib/LocalMediaHandler.d.ts +22 -14
- package/lib/LocalMediaHandler.js +192 -168
- package/lib/LocalMediaInterfaces.d.ts +1 -0
- package/lib/LocalMediaUtils.d.ts +8 -1
- package/lib/LocalMediaUtils.js +24 -12
- package/lib/ReactContext.d.ts +2 -7
- package/lib/ReactContext.js +5 -11
- package/package.json +4 -6
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
|
|
7
7
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
|
|
8
8
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
|
|
9
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
|
9
10
|
<uses-permission android:name="android.permission.CAMERA"/>
|
|
10
11
|
<uses-permission android:name="android.permission.INTERNET"/>
|
|
11
12
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
|
|
@@ -134,6 +134,7 @@ public class DyteHelperModule extends ReactContextBaseJavaModule {
|
|
|
134
134
|
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
|
|
135
135
|
if ((ForegroundService.class).getName().equals(service.service.getClassName())) {
|
|
136
136
|
promise.resolve(true);
|
|
137
|
+
return;
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
promise.resolve(false);
|
|
@@ -28,7 +28,7 @@ public class ForegroundService extends Service {
|
|
|
28
28
|
if (notification != null) {
|
|
29
29
|
try {
|
|
30
30
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
31
|
-
startForeground(notificationHelper.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
|
|
31
|
+
startForeground(notificationHelper.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
|
|
32
32
|
} else {
|
|
33
33
|
startForeground(notificationHelper.NOTIFICATION_ID, notification);
|
|
34
34
|
}
|
|
@@ -22,9 +22,9 @@ import java.util.Random;
|
|
|
22
22
|
|
|
23
23
|
class NotificationHelper {
|
|
24
24
|
public static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
|
25
|
-
private static final String CHANNEL_ID = "
|
|
26
|
-
private static final String CHANNEL_NAME = "
|
|
27
|
-
private static final String CHANNEL_DESC = "
|
|
25
|
+
private static final String CHANNEL_ID = "RealtimeKitNotificationChannel";
|
|
26
|
+
private static final String CHANNEL_NAME = "Screen Sharing";
|
|
27
|
+
private static final String CHANNEL_DESC = "Screen Sharing";
|
|
28
28
|
|
|
29
29
|
private static NotificationHelper instance = null;
|
|
30
30
|
private NotificationManager mNotificationManager;
|
|
@@ -83,18 +83,17 @@ class NotificationHelper {
|
|
|
83
83
|
|
|
84
84
|
builder
|
|
85
85
|
.setCategory(NotificationCompat.CATEGORY_CALL)
|
|
86
|
-
.setContentTitle("
|
|
87
|
-
.setContentText("
|
|
88
|
-
.setPriority(NotificationCompat.
|
|
86
|
+
.setContentTitle("Screen Share")
|
|
87
|
+
.setContentText("You are sharing your screen")
|
|
88
|
+
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
89
89
|
.setContentIntent(pendingIntent)
|
|
90
|
-
.setOngoing(
|
|
91
|
-
.
|
|
92
|
-
.
|
|
93
|
-
.setAutoCancel(false)
|
|
90
|
+
.setOngoing(false)
|
|
91
|
+
.setUsesChronometer(false)
|
|
92
|
+
.setAutoCancel(true)
|
|
94
93
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
95
94
|
.setOnlyAlertOnce(true)
|
|
96
|
-
.setSmallIcon(appIconResId)
|
|
97
|
-
|
|
95
|
+
.setSmallIcon(appIconResId)
|
|
96
|
+
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE);
|
|
98
97
|
if(largeIcon != null){
|
|
99
98
|
builder.setLargeIcon(largeIcon);
|
|
100
99
|
}
|
package/ios/RNInCallManager.m
CHANGED
|
@@ -549,6 +549,11 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
|
|
|
549
549
|
{
|
|
550
550
|
// NSLog(@"👉 Checking if Bluetooth device is connected");
|
|
551
551
|
NSMutableArray *devices = [NSMutableArray array];
|
|
552
|
+
NSError *error = nil;
|
|
553
|
+
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
|
|
554
|
+
withOptions:AVAudioSessionCategoryOptionAllowBluetooth
|
|
555
|
+
error:&error];
|
|
556
|
+
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
|
|
552
557
|
AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
|
|
553
558
|
for (AVAudioSessionPortDescription* desc in [route outputs]) {
|
|
554
559
|
// NSLog(@"🧑💻 Bluetooth Desc: %@", desc);
|
|
@@ -558,6 +563,20 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
|
|
|
558
563
|
[devices addObject:[desc portName]];
|
|
559
564
|
}
|
|
560
565
|
}
|
|
566
|
+
|
|
567
|
+
// If no Bluetooth device found in current route, check available outputs
|
|
568
|
+
if (devices.count == 0) {
|
|
569
|
+
NSArray<AVAudioSessionPortDescription *> *inputs = [route inputs];
|
|
570
|
+
|
|
571
|
+
// Check if Bluetooth is available in inputs (for headsets that function as both input and output)
|
|
572
|
+
for (AVAudioSessionPortDescription* desc in inputs) {
|
|
573
|
+
if ([[desc portType] isEqualToString:AVAudioSessionPortBluetoothHFP] ||
|
|
574
|
+
[[desc portType] isEqualToString:AVAudioSessionPortBluetoothLE]) {
|
|
575
|
+
[devices addObject:[desc portName]];
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
561
580
|
// NSLog(@"🧑💻 Bluetooth Devices %@", devices);
|
|
562
581
|
if (!devices || !devices.count){
|
|
563
582
|
resolve(@NO);
|
|
@@ -620,7 +639,11 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
|
|
|
620
639
|
[self audioSessionSetMode:audioMode
|
|
621
640
|
callerMemo:NSStringFromSelector(_cmd)];
|
|
622
641
|
|
|
623
|
-
|
|
642
|
+
@try {
|
|
643
|
+
[self sendEventWithName:@"onAudioDeviceChanged" body:@{@"devices": audioMode}];
|
|
644
|
+
} @catch (NSException *exception) {
|
|
645
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged': %@", exception.reason);
|
|
646
|
+
}
|
|
624
647
|
// NSLog(@"👨💻 RNInCallManager.updateAudioRoute() audio mode has changed to %@", audioMode);
|
|
625
648
|
return true;
|
|
626
649
|
} else {
|
|
@@ -806,7 +829,11 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
|
|
|
806
829
|
if (state != self->_proximityIsNear) {
|
|
807
830
|
// NSLog(@"RNInCallManager.UIDeviceProximityStateDidChangeNotification(): isNear: %@", state ? @"YES" : @"NO");
|
|
808
831
|
self->_proximityIsNear = state;
|
|
809
|
-
|
|
832
|
+
@try {
|
|
833
|
+
[self sendEventWithName:@"Proximity" body:@{@"isNear": state ? @YES : @NO}];
|
|
834
|
+
} @catch (NSException *exception) {
|
|
835
|
+
NSLog(@"Error sending event 'Proximity': %@", exception.reason);
|
|
836
|
+
}
|
|
810
837
|
}
|
|
811
838
|
}];
|
|
812
839
|
|
|
@@ -936,62 +963,81 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
|
|
|
936
963
|
if ([self checkAudioRoute:@[AVAudioSessionPortHeadsetMic]
|
|
937
964
|
routeType:@"input"]) {
|
|
938
965
|
_forceSpeakerOn = 0;
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
966
|
+
@try {
|
|
967
|
+
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
968
|
+
body:@{
|
|
969
|
+
@"availableAudioDeviceList": @"[speaker, earpiece, wired]",
|
|
970
|
+
@"selectedAudioDevice": AVAudioSessionPortHeadsetMic,
|
|
971
|
+
}];
|
|
972
|
+
} @catch (NSException *exception) {
|
|
973
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged' (HeadsetMic): %@", exception.reason);
|
|
974
|
+
}
|
|
944
975
|
} else if ([self checkAudioRoute:@[AVAudioSessionPortHeadphones]
|
|
945
976
|
routeType:@"output"]) {
|
|
946
977
|
_forceSpeakerOn = 0;
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
978
|
+
@try {
|
|
979
|
+
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
980
|
+
body:@{
|
|
981
|
+
@"availableAudioDeviceList": @"[speaker, earpiece, wired]",
|
|
982
|
+
@"selectedAudioDevice": AVAudioSessionPortHeadphones,
|
|
983
|
+
}];
|
|
984
|
+
} @catch (NSException *exception) {
|
|
985
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged' (Headphones): %@", exception.reason);
|
|
986
|
+
}
|
|
952
987
|
} else if ([self checkAudioRoute:@[AVAudioSessionPortBluetoothHFP]
|
|
953
988
|
routeType:@"input"]) {
|
|
954
989
|
_forceSpeakerOn = 0;
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
990
|
+
@try {
|
|
991
|
+
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
992
|
+
body:@{
|
|
993
|
+
@"availableAudioDeviceList": @"[speaker, earpiece, bluetooth]",
|
|
994
|
+
@"selectedAudioDevice": AVAudioSessionPortBluetoothHFP,
|
|
995
|
+
}];
|
|
996
|
+
} @catch (NSException *exception) {
|
|
997
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged' (BluetoothHFP): %@", exception.reason);
|
|
998
|
+
}
|
|
960
999
|
} else if ([self checkAudioRoute:@[AVAudioSessionPortBluetoothA2DP]
|
|
961
1000
|
routeType:@"input"]) {
|
|
962
1001
|
_forceSpeakerOn = 0;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1002
|
+
@try {
|
|
1003
|
+
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
1004
|
+
body:@{
|
|
1005
|
+
@"availableAudioDeviceList": @"[speaker, earpiece, bluetooth]",
|
|
1006
|
+
@"selectedAudioDevice": AVAudioSessionPortBluetoothA2DP,
|
|
1007
|
+
}];
|
|
1008
|
+
} @catch (NSException *exception) {
|
|
1009
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged' (BluetoothA2DP): %@", exception.reason);
|
|
1010
|
+
}
|
|
968
1011
|
} else if ([self checkAudioRoute:@[AVAudioSessionPortBluetoothLE]
|
|
969
1012
|
routeType:@"input"]) {
|
|
970
1013
|
_forceSpeakerOn = 0;
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1014
|
+
@try {
|
|
1015
|
+
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
1016
|
+
body:@{
|
|
1017
|
+
@"availableAudioDeviceList": @"[speaker, earpiece, bluetooth]",
|
|
1018
|
+
@"selectedAudioDevice": AVAudioSessionPortBluetoothLE,
|
|
1019
|
+
}];
|
|
1020
|
+
} @catch (NSException *exception) {
|
|
1021
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged' (BluetoothLE): %@", exception.reason);
|
|
1022
|
+
}
|
|
976
1023
|
}
|
|
977
1024
|
break;
|
|
978
1025
|
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
|
|
979
|
-
|
|
980
|
-
|
|
1026
|
+
@try {
|
|
1027
|
+
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
1028
|
+
body:@{
|
|
981
1029
|
@"availableAudioDeviceList": @"[speaker, earpiece]",
|
|
982
1030
|
@"selectedAudioDevice": @"speaker",
|
|
983
|
-
}];
|
|
1031
|
+
}];
|
|
1032
|
+
} @catch (NSException *exception) {
|
|
1033
|
+
NSLog(@"Error sending event 'onAudioDeviceChanged' (OldDeviceUnavailable): %@", exception.reason);
|
|
1034
|
+
}
|
|
984
1035
|
break;
|
|
985
1036
|
case AVAudioSessionRouteChangeReasonCategoryChange:
|
|
986
1037
|
// NSLog(@"🧑💻 RNInCallManager.AudioRouteChange.Reason: CategoryChange. category=%@ mode=%@", self->_audioSession.category, self->_audioSession.mode);
|
|
987
1038
|
break;
|
|
988
1039
|
case AVAudioSessionRouteChangeReasonOverride:
|
|
989
|
-
// NSLog(@"🧑💻 RNInCallManager.AudioRouteChange.Reason: Override");
|
|
990
|
-
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
991
|
-
body:@{
|
|
992
|
-
@"availableAudioDeviceList": @"[speaker, earpiece]",
|
|
993
|
-
@"selectedAudioDevice": @"speaker",
|
|
994
|
-
}];
|
|
1040
|
+
// NSLog(@"🧑💻 RNInCallManager.AudioRouteChange.Reason: Override");
|
|
995
1041
|
break;
|
|
996
1042
|
case AVAudioSessionRouteChangeReasonWakeFromSleep:
|
|
997
1043
|
// NSLog(@"RNInCallManager.AudioRouteChange.Reason: WakeFromSleep");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ReplayKit
|
|
2
2
|
|
|
3
|
-
open class
|
|
3
|
+
open class RTKScreenshareHandler: RPBroadcastSampleHandler {
|
|
4
4
|
|
|
5
5
|
private var clientConnection: DyteSocketConnection?
|
|
6
6
|
private var uploader: DyteScreenshareUploader?
|
|
@@ -21,7 +21,6 @@ open class DyteScreenshareHandler: RPBroadcastSampleHandler {
|
|
|
21
21
|
super.init()
|
|
22
22
|
if let connection = DyteSocketConnection(filePath: socketFilePath) {
|
|
23
23
|
clientConnection = connection
|
|
24
|
-
print("Setup Connection")
|
|
25
24
|
setupConnection()
|
|
26
25
|
uploader = DyteScreenshareUploader(connection: connection, bundleIdentifier: bundleIdentifier)
|
|
27
26
|
}
|
|
@@ -49,7 +48,6 @@ open class DyteScreenshareHandler: RPBroadcastSampleHandler {
|
|
|
49
48
|
|
|
50
49
|
public override func broadcastFinished() {
|
|
51
50
|
// User has requested to finish the broadcast.
|
|
52
|
-
print("Broadcast Stopped")
|
|
53
51
|
DyteDarwinNotificationCenter.shared.postNotification(.broadcastStopped)
|
|
54
52
|
clientConnection?.close()
|
|
55
53
|
}
|
|
@@ -68,7 +66,7 @@ open class DyteScreenshareHandler: RPBroadcastSampleHandler {
|
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
private extension
|
|
69
|
+
private extension RTKScreenshareHandler {
|
|
72
70
|
|
|
73
71
|
func setupConnection() {
|
|
74
72
|
clientConnection?.didClose = { [weak self] error in
|
package/lib/BackgroundHandler.js
CHANGED
|
@@ -13,7 +13,9 @@ class BackgroundTimer {
|
|
|
13
13
|
delete this.callbacks[id];
|
|
14
14
|
}
|
|
15
15
|
else {
|
|
16
|
-
|
|
16
|
+
Platform.OS === 'android'
|
|
17
|
+
? DyteRNBackgroundTimer.backgroundTimerSetTimeout(id, this.callbacks[id].timeout)
|
|
18
|
+
: DyteRNBackgroundTimer.setTimeout(id, this.callbacks[id].timeout);
|
|
17
19
|
}
|
|
18
20
|
callback();
|
|
19
21
|
}
|
|
@@ -21,11 +23,15 @@ class BackgroundTimer {
|
|
|
21
23
|
}
|
|
22
24
|
// Original API
|
|
23
25
|
start(delay = 0) {
|
|
24
|
-
return
|
|
26
|
+
return Platform.OS === 'android'
|
|
27
|
+
? DyteRNBackgroundTimer.backgroundTimerStart(delay)
|
|
28
|
+
: DyteRNBackgroundTimer.start(delay);
|
|
25
29
|
}
|
|
26
30
|
stop() {
|
|
27
31
|
Emitter.removeAllListeners('backgroundTimer.timeout');
|
|
28
|
-
return
|
|
32
|
+
return Platform.OS === 'android'
|
|
33
|
+
? DyteRNBackgroundTimer.backgroundTimerStop()
|
|
34
|
+
: DyteRNBackgroundTimer.stop();
|
|
29
35
|
}
|
|
30
36
|
runBackgroundTimer(callback, delay) {
|
|
31
37
|
const EventEmitter = Platform.select({
|
|
@@ -57,7 +63,9 @@ class BackgroundTimer {
|
|
|
57
63
|
interval: false,
|
|
58
64
|
timeout,
|
|
59
65
|
};
|
|
60
|
-
|
|
66
|
+
Platform.OS === 'android'
|
|
67
|
+
? DyteRNBackgroundTimer.backgroundTimerSetTimeout(timeoutId, timeout)
|
|
68
|
+
: DyteRNBackgroundTimer.setTimeout(timeoutId, timeout);
|
|
61
69
|
return timeoutId;
|
|
62
70
|
}
|
|
63
71
|
clearTimeout(timeoutId) {
|
|
@@ -74,7 +82,9 @@ class BackgroundTimer {
|
|
|
74
82
|
interval: true,
|
|
75
83
|
timeout,
|
|
76
84
|
};
|
|
77
|
-
|
|
85
|
+
Platform.OS === 'android'
|
|
86
|
+
? DyteRNBackgroundTimer.backgroundTimerSetTimeout(intervalId, timeout)
|
|
87
|
+
: DyteRNBackgroundTimer.setTimeout(intervalId, timeout);
|
|
78
88
|
return intervalId;
|
|
79
89
|
}
|
|
80
90
|
clearInterval(intervalId) {
|
|
@@ -26,6 +26,7 @@ export default class LocalMediaHandler extends EventEmitter {
|
|
|
26
26
|
audioEnabled: boolean;
|
|
27
27
|
videoEnabled: boolean;
|
|
28
28
|
screenShareEnabled: boolean;
|
|
29
|
+
private _pendingScreenShare;
|
|
29
30
|
currentDevices: {
|
|
30
31
|
audio?: MediaDeviceInfo;
|
|
31
32
|
video?: MediaDeviceInfo;
|
|
@@ -38,8 +39,6 @@ export default class LocalMediaHandler extends EventEmitter {
|
|
|
38
39
|
_handleAppStateChange: (nextAppState: any) => void;
|
|
39
40
|
private configureForeground;
|
|
40
41
|
constructor(localMediaUtils: LocalMediaUtils);
|
|
41
|
-
destructor(): void;
|
|
42
|
-
private handlePermissionErrors;
|
|
43
42
|
private conditionallyRestartAudio;
|
|
44
43
|
private conditionallyRestartVideo;
|
|
45
44
|
private shouldReacquireTrack;
|
|
@@ -63,36 +62,30 @@ export default class LocalMediaHandler extends EventEmitter {
|
|
|
63
62
|
audio: boolean;
|
|
64
63
|
video: boolean;
|
|
65
64
|
}): Promise<void>;
|
|
66
|
-
private stopAudioTrack;
|
|
67
|
-
private stopVideoTrack;
|
|
68
65
|
private stopScreenShareTracks;
|
|
69
|
-
removeAudioTrack(): void;
|
|
70
|
-
removeVideoTrack(): void;
|
|
71
66
|
removeScreenShareTracks(tracks?: {
|
|
72
67
|
audio?: boolean;
|
|
73
68
|
video?: boolean;
|
|
74
69
|
}): void;
|
|
75
|
-
removeAllTracks(): void;
|
|
76
70
|
private setAudioTrack;
|
|
77
71
|
private setVideoTrack;
|
|
78
72
|
private setScreenShareTracks;
|
|
79
73
|
private onScreenShareEnded;
|
|
80
|
-
disableAudio(): void
|
|
74
|
+
disableAudio(): Promise<void>;
|
|
81
75
|
enableAudio(): Promise<void>;
|
|
76
|
+
toggleAudio(): Promise<void>;
|
|
82
77
|
enableVideo(): Promise<void>;
|
|
83
78
|
disableVideo(): Promise<void>;
|
|
84
|
-
toggleAudio(): Promise<void>;
|
|
85
79
|
toggleVideo(): Promise<void>;
|
|
86
80
|
setAudioDevice(device: MediaDeviceInfo): Promise<void>;
|
|
87
81
|
setVideoDevice(device: MediaDeviceInfo): Promise<void>;
|
|
88
82
|
setSpeakerDevice(device?: MediaDeviceInfo): Promise<void>;
|
|
89
|
-
setDevice(route: MediaDeviceInfo): Promise<
|
|
83
|
+
setDevice(route: MediaDeviceInfo): Promise<void>;
|
|
90
84
|
private oniOSBroadcastStart;
|
|
91
85
|
private oniOSBroadcastStop;
|
|
92
86
|
toggleScreenShare(): Promise<void>;
|
|
93
87
|
enableScreenShare(): Promise<void>;
|
|
94
88
|
disableScreenShare(): Promise<void>;
|
|
95
|
-
destruct(): void;
|
|
96
89
|
getAllDevices(): MediaDeviceInfo[];
|
|
97
90
|
getCurrentDevices(): {
|
|
98
91
|
audio?: MediaDeviceInfo;
|
|
@@ -102,16 +95,31 @@ export default class LocalMediaHandler extends EventEmitter {
|
|
|
102
95
|
getDeviceById(deviceId: string, kind: 'audioinput' | 'audiooutput' | 'videoinput'): MediaDeviceInfo;
|
|
103
96
|
getAudioDevices(): MediaDeviceInfo[];
|
|
104
97
|
getVideoDevices(): MediaDeviceInfo[];
|
|
105
|
-
getSpeakerDevices():
|
|
98
|
+
getSpeakerDevices(): {
|
|
99
|
+
deviceId: string;
|
|
100
|
+
label: string;
|
|
101
|
+
kind: string;
|
|
102
|
+
groupId: string;
|
|
103
|
+
facing: string;
|
|
104
|
+
toJSON(): any;
|
|
105
|
+
}[];
|
|
106
106
|
onDeviceChange(changedDevices: {
|
|
107
107
|
added: MediaDeviceInfo[];
|
|
108
108
|
removed: MediaDeviceInfo[];
|
|
109
109
|
}, forceDeviceChange: boolean): Promise<void>;
|
|
110
|
-
cleanUpTracks(): void;
|
|
111
|
-
destructMediaHandler(): Promise<void>;
|
|
112
110
|
static init(_: any): Promise<LocalMediaHandler>;
|
|
113
111
|
emit(event: keyof typeof MediaEvents, ...args: any[]): boolean;
|
|
114
112
|
on(event: keyof typeof MediaEvents, listener: (...args: any[]) => void): this;
|
|
113
|
+
destruct(): void;
|
|
114
|
+
destructMediaHandler(): Promise<void>;
|
|
115
|
+
cleanUpTracks(): void;
|
|
116
|
+
destructor(): void;
|
|
117
|
+
removeAllTracks(): void;
|
|
118
|
+
private stopAudioTrack;
|
|
119
|
+
removeAudioTrack(): void;
|
|
120
|
+
private stopVideoTrack;
|
|
121
|
+
removeVideoTrack(): void;
|
|
122
|
+
removeAllListeners(event?: keyof typeof MediaEvents): this;
|
|
115
123
|
}
|
|
116
124
|
export interface RNLocalMediaHandler {
|
|
117
125
|
new (): LocalMediaHandler;
|
package/lib/LocalMediaHandler.js
CHANGED
|
@@ -22,12 +22,13 @@ var _LocalMediaHandler_localMediaUtils, _LocalMediaHandler_appState, _LocalMedia
|
|
|
22
22
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
23
23
|
import { EventEmitter } from 'events';
|
|
24
24
|
import LocalMediaUtils from './LocalMediaUtils';
|
|
25
|
-
import { AppState, NativeEventEmitter, NativeModules, Platform, } from 'react-native';
|
|
25
|
+
import { AppState, NativeEventEmitter, NativeModules, PermissionsAndroid, Platform, } from 'react-native';
|
|
26
26
|
import BackgroundTimer from './BackgroundHandler';
|
|
27
27
|
import InCallManger from './NativeAudioManager';
|
|
28
28
|
import { setupPermissions } from './PermissionHandler';
|
|
29
29
|
const { DyteHelper, BroadcastEventEmitter } = NativeModules;
|
|
30
30
|
const broadcastEmitter = new NativeEventEmitter(BroadcastEventEmitter);
|
|
31
|
+
// eslint-disable-next-line no-shadow
|
|
31
32
|
export var MediaEvents;
|
|
32
33
|
(function (MediaEvents) {
|
|
33
34
|
MediaEvents[MediaEvents["AUDIO_TRACK_CHANGE"] = 0] = "AUDIO_TRACK_CHANGE";
|
|
@@ -46,12 +47,26 @@ function checkIfAudioTrackIsSilent(track) {
|
|
|
46
47
|
class LocalMediaHandler extends EventEmitter {
|
|
47
48
|
configureForeground() {
|
|
48
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
if (Platform.OS !== 'android')
|
|
51
|
+
return;
|
|
49
52
|
const val = yield DyteHelper.isForegroundServiceRunning();
|
|
50
|
-
if (
|
|
51
|
-
|
|
53
|
+
if (!val) {
|
|
54
|
+
if (Platform.Version >= 33) {
|
|
55
|
+
const res = yield PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
|
56
|
+
if (res !== PermissionsAndroid.RESULTS.GRANTED) {
|
|
57
|
+
console.warn('Permission required for screenshare notification');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (Platform.Version >= 26) {
|
|
61
|
+
yield DyteHelper.createNotificationChannel();
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
yield DyteHelper.startService();
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.warn('Failed to start foreground service', e);
|
|
68
|
+
}
|
|
52
69
|
}
|
|
53
|
-
if (!val)
|
|
54
|
-
yield DyteHelper.startService();
|
|
55
70
|
});
|
|
56
71
|
}
|
|
57
72
|
constructor(localMediaUtils) {
|
|
@@ -60,8 +75,8 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
60
75
|
_LocalMediaHandler_appState.set(this, void 0);
|
|
61
76
|
_LocalMediaHandler_appStateSubscription.set(this, void 0);
|
|
62
77
|
_LocalMediaHandler_interval.set(this, void 0);
|
|
78
|
+
this._pendingScreenShare = false;
|
|
63
79
|
this._handleAppStateChange = (nextAppState) => {
|
|
64
|
-
// console.log('App state changed to : ', nextAppState);
|
|
65
80
|
if (__classPrivateFieldGet(this, _LocalMediaHandler_appState, "f").match(/inactive|background/) &&
|
|
66
81
|
nextAppState === 'active') {
|
|
67
82
|
BackgroundTimer.clearInterval(__classPrivateFieldGet(this, _LocalMediaHandler_interval, "f"));
|
|
@@ -77,7 +92,9 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
77
92
|
}
|
|
78
93
|
else {
|
|
79
94
|
if (__classPrivateFieldGet(this, _LocalMediaHandler_interval, "f") === null) {
|
|
80
|
-
this.
|
|
95
|
+
if (this.screenShareEnabled || this._pendingScreenShare) {
|
|
96
|
+
this.configureForeground();
|
|
97
|
+
}
|
|
81
98
|
}
|
|
82
99
|
__classPrivateFieldSet(this, _LocalMediaHandler_interval, BackgroundTimer.setInterval(() => { }, 1000), "f");
|
|
83
100
|
__classPrivateFieldSet(this, _LocalMediaHandler_appState, nextAppState, "f");
|
|
@@ -98,8 +115,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
98
115
|
video: undefined,
|
|
99
116
|
speaker: undefined,
|
|
100
117
|
};
|
|
101
|
-
//
|
|
102
|
-
//if (Platform.OS === 'android')
|
|
118
|
+
// LocalMediaUtils onDeviceChange with callback from native onAudioDeviceChanged events
|
|
103
119
|
__classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").onDeviceChange((changedDevices) => __awaiter(this, void 0, void 0, function* () {
|
|
104
120
|
yield this.onDeviceChange(changedDevices, false);
|
|
105
121
|
}));
|
|
@@ -113,15 +129,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
113
129
|
}
|
|
114
130
|
InCallManger.start({});
|
|
115
131
|
}
|
|
116
|
-
destructor() {
|
|
117
|
-
__classPrivateFieldGet(this, _LocalMediaHandler_appStateSubscription, "f").remove();
|
|
118
|
-
broadcastEmitter.removeAllListeners('iOS_BroadcastStarted');
|
|
119
|
-
broadcastEmitter.removeAllListeners('iOS_BroadcastStopped');
|
|
120
|
-
BackgroundTimer.stop();
|
|
121
|
-
}
|
|
122
|
-
handlePermissionErrors(kind, err) {
|
|
123
|
-
// pass
|
|
124
|
-
}
|
|
125
132
|
conditionallyRestartAudio() {
|
|
126
133
|
return __awaiter(this, void 0, void 0, function* () {
|
|
127
134
|
var _a;
|
|
@@ -241,12 +248,17 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
241
248
|
(_b = this.audioTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
242
249
|
(_c = this.rawAudioTrack) === null || _c === void 0 ? void 0 : _c.stop();
|
|
243
250
|
}
|
|
244
|
-
|
|
251
|
+
try {
|
|
252
|
+
this.rawAudioTrack = yield LocalMediaUtils.getAudioTrack();
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
console.warn('Failed to acquire audio track: ', err);
|
|
256
|
+
this.rawAudioTrack = undefined;
|
|
257
|
+
}
|
|
245
258
|
this.setAudioTrack(this.rawAudioTrack);
|
|
246
259
|
this.addMediaStreamTrackListeners(this.audioTrack);
|
|
260
|
+
this.emit('AUDIO_TRACK_CHANGE');
|
|
247
261
|
this.setDevice(this.currentDevices.audio);
|
|
248
|
-
// await InCallManger.chooseAudioRoute(audioDeviceId);
|
|
249
|
-
// console.log('Device selected: ', audioDeviceId);
|
|
250
262
|
/**
|
|
251
263
|
* NOTE(roerohan): Firefox does not show device labels until permissions are granted.
|
|
252
264
|
* So, we need to repopulate the devices once permission is granted.
|
|
@@ -254,18 +266,9 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
254
266
|
if (this.audioTrack && this.permissions.audio === 'NOT_REQUESTED') {
|
|
255
267
|
yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").repopulateAvailableDevices();
|
|
256
268
|
}
|
|
257
|
-
this.permissions.audio = 'ACCEPTED';
|
|
258
|
-
this.emit('MEDIA_PERMISSION_UPDATE', {
|
|
259
|
-
kind: 'audio',
|
|
260
|
-
message: this.permissions.audio,
|
|
261
|
-
});
|
|
262
269
|
this.emit('DEVICE_CHANGE', {
|
|
263
270
|
device: this.currentDevices.audio,
|
|
264
271
|
});
|
|
265
|
-
/*
|
|
266
|
-
TODO
|
|
267
|
-
callStats.mediaPermission('AUDIO', CallStatsPermissionEnum.ACCEPTED);
|
|
268
|
-
callStats.selectedDevice('AUDIO', this.currentDevices.audio); */
|
|
269
272
|
});
|
|
270
273
|
}
|
|
271
274
|
onVisibilityChange() {
|
|
@@ -294,10 +297,17 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
294
297
|
videoDeviceId,
|
|
295
298
|
});
|
|
296
299
|
if (!this.rawVideoTrack) {
|
|
297
|
-
|
|
300
|
+
try {
|
|
301
|
+
this.rawVideoTrack = yield LocalMediaUtils.getVideoTrack(videoConstraints);
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
console.warn('Failed to acquire video track: ', err);
|
|
305
|
+
this.rawVideoTrack = undefined;
|
|
306
|
+
}
|
|
298
307
|
}
|
|
299
308
|
this.setVideoTrack(this.rawVideoTrack);
|
|
300
309
|
this.addMediaStreamTrackListeners(this.rawVideoTrack);
|
|
310
|
+
this.emit('VIDEO_TRACK_CHANGE');
|
|
301
311
|
}
|
|
302
312
|
if (forceStopTrack) {
|
|
303
313
|
(_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
@@ -310,11 +320,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
310
320
|
if (this.videoTrack && this.permissions.video === 'NOT_REQUESTED') {
|
|
311
321
|
yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").repopulateAvailableDevices();
|
|
312
322
|
}
|
|
313
|
-
this.permissions.video = 'ACCEPTED';
|
|
314
|
-
this.emit('MEDIA_PERMISSION_UPDATE', {
|
|
315
|
-
kind: 'video',
|
|
316
|
-
message: this.permissions.video,
|
|
317
|
-
});
|
|
318
323
|
this.emit('DEVICE_CHANGE', {
|
|
319
324
|
device: this.currentDevices.video,
|
|
320
325
|
});
|
|
@@ -327,23 +332,17 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
327
332
|
if (!speakerDevices.length) {
|
|
328
333
|
return;
|
|
329
334
|
}
|
|
330
|
-
const
|
|
335
|
+
const lastDeviceIndex = speakerDevices.length - 1;
|
|
336
|
+
const speakerDeviceId = deviceId !== null && deviceId !== void 0 ? deviceId : speakerDevices[lastDeviceIndex].deviceId;
|
|
331
337
|
if (((_a = this.currentDevices.speaker) === null || _a === void 0 ? void 0 : _a.deviceId) !== speakerDeviceId) {
|
|
332
|
-
|
|
338
|
+
// Audio Input devices are same as output devices in mobile
|
|
339
|
+
this.currentDevices.audio = __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").getDeviceById(speakerDeviceId, 'audioinput');
|
|
340
|
+
this.currentDevices.speaker = this.currentDevices.audio;
|
|
333
341
|
}
|
|
342
|
+
yield this.setDevice(this.currentDevices.audio);
|
|
334
343
|
this.emit('DEVICE_CHANGE', {
|
|
335
344
|
device: this.currentDevices.speaker,
|
|
336
345
|
});
|
|
337
|
-
/*
|
|
338
|
-
TODO
|
|
339
|
-
const speakerDeviceId = deviceId ?? speakerDevices[0].deviceId;
|
|
340
|
-
if (this.currentDevices.speaker?.deviceId !== speakerDeviceId) {
|
|
341
|
-
this.currentDevices.speaker = this.#localMediaUtils.getDeviceById(
|
|
342
|
-
speakerDeviceId,
|
|
343
|
-
'audiooutput'
|
|
344
|
-
);
|
|
345
|
-
callStats.selectedDevice('SPEAKER', this.currentDevices.speaker);
|
|
346
|
-
} */
|
|
347
346
|
});
|
|
348
347
|
}
|
|
349
348
|
getOperationalWebcamDeviceId() {
|
|
@@ -374,10 +373,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
374
373
|
getOperationalMicDeviceId() {
|
|
375
374
|
return __awaiter(this, void 0, void 0, function* () {
|
|
376
375
|
let audioDevices = __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").getAudioDevices();
|
|
377
|
-
// console.log(
|
|
378
|
-
// 'getOperationalMicDeviceId: ',
|
|
379
|
-
// JSON.stringify(audioDevices, null, 2)
|
|
380
|
-
// );
|
|
381
376
|
if (!audioDevices.length) {
|
|
382
377
|
return { isOperational: false, deviceId: null };
|
|
383
378
|
}
|
|
@@ -387,10 +382,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
387
382
|
We are giving preference to external device
|
|
388
383
|
*/
|
|
389
384
|
audioDevices = [...audioDevices].reverse();
|
|
390
|
-
// console.log(
|
|
391
|
-
// 'getOperationalMicDeviceId Reverse: ',
|
|
392
|
-
// JSON.stringify(audioDevices, null, 2)
|
|
393
|
-
// );
|
|
394
385
|
let operationalDeviceId = null;
|
|
395
386
|
for (let deviceIndex = 0; deviceIndex < audioDevices.length; deviceIndex += 1) {
|
|
396
387
|
try {
|
|
@@ -403,7 +394,9 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
403
394
|
break;
|
|
404
395
|
}
|
|
405
396
|
}
|
|
406
|
-
catch (err) {
|
|
397
|
+
catch (err) {
|
|
398
|
+
console.warn('Failed to acquire audio track: ', err);
|
|
399
|
+
}
|
|
407
400
|
}
|
|
408
401
|
return operationalDeviceId
|
|
409
402
|
? { isOperational: true, deviceId: operationalDeviceId }
|
|
@@ -412,7 +405,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
412
405
|
}
|
|
413
406
|
setupStreams(_a) {
|
|
414
407
|
return __awaiter(this, arguments, void 0, function* ({ audio, video, }) {
|
|
415
|
-
var _b, _c
|
|
408
|
+
var _b, _c;
|
|
416
409
|
try {
|
|
417
410
|
const permResult = yield setupPermissions(audio, video);
|
|
418
411
|
this.permissions.video = permResult.camera;
|
|
@@ -422,6 +415,14 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
422
415
|
this.permissions.video = (_b = val.camera) !== null && _b !== void 0 ? _b : false;
|
|
423
416
|
this.permissions.audio = (_c = val.microphone) !== null && _c !== void 0 ? _c : false;
|
|
424
417
|
}
|
|
418
|
+
this.emit('MEDIA_PERMISSION_UPDATE', {
|
|
419
|
+
kind: 'audio',
|
|
420
|
+
message: this.permissions.audio,
|
|
421
|
+
});
|
|
422
|
+
this.emit('MEDIA_PERMISSION_UPDATE', {
|
|
423
|
+
kind: 'video',
|
|
424
|
+
message: this.permissions.video,
|
|
425
|
+
});
|
|
425
426
|
const constraints = {};
|
|
426
427
|
if (!this.currentDevices) {
|
|
427
428
|
this.currentDevices = {
|
|
@@ -450,37 +451,20 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
450
451
|
constraints.video = videoConstraints.video;
|
|
451
452
|
}
|
|
452
453
|
}
|
|
453
|
-
const { audioTrack, videoTrack } = yield LocalMediaUtils.getAudioAndVideoTrack(constraints);
|
|
454
|
-
if (audio && audioTrack) {
|
|
455
|
-
this.rawAudioTrack = audioTrack;
|
|
456
|
-
this.permissions.audio = 'ACCEPTED';
|
|
457
|
-
}
|
|
458
|
-
this.emit('MEDIA_PERMISSION_UPDATE', {
|
|
459
|
-
kind: 'audio',
|
|
460
|
-
message: this.permissions.audio,
|
|
461
|
-
});
|
|
462
|
-
if (video && videoTrack) {
|
|
463
|
-
this.rawVideoTrack = videoTrack;
|
|
464
|
-
this.permissions.video = 'ACCEPTED';
|
|
465
|
-
}
|
|
466
|
-
this.emit('MEDIA_PERMISSION_UPDATE', {
|
|
467
|
-
kind: 'video',
|
|
468
|
-
message: this.permissions.video,
|
|
469
|
-
});
|
|
470
|
-
if (((_d = Object.keys(constraints)) === null || _d === void 0 ? void 0 : _d.length) === 0) {
|
|
471
|
-
this.audioEnabled = false;
|
|
472
|
-
this.videoEnabled = false;
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
454
|
if (audio)
|
|
476
455
|
yield this.setupAudioStream();
|
|
477
456
|
if (video)
|
|
478
457
|
yield this.setupVideoStream();
|
|
479
|
-
if (audioTrack)
|
|
458
|
+
if (this.audioTrack)
|
|
480
459
|
this.audioEnabled = true;
|
|
481
|
-
|
|
460
|
+
else
|
|
461
|
+
this.audioEnabled = false;
|
|
462
|
+
if (this.videoTrack)
|
|
482
463
|
this.videoEnabled = true;
|
|
464
|
+
else
|
|
465
|
+
this.videoEnabled = false;
|
|
483
466
|
this.screenShareEnabled = false;
|
|
467
|
+
// Setting default audio output to speaker
|
|
484
468
|
yield this.setupSpeaker();
|
|
485
469
|
// Setup Foreground Service after handling permissions
|
|
486
470
|
if (Platform.OS === 'android') {
|
|
@@ -488,19 +472,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
488
472
|
}
|
|
489
473
|
});
|
|
490
474
|
}
|
|
491
|
-
stopAudioTrack() {
|
|
492
|
-
var _a, _b;
|
|
493
|
-
(_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
494
|
-
(_b = this.audioTrack) === null || _b === void 0 ? void 0 : _b.release();
|
|
495
|
-
this.audioEnabled = false;
|
|
496
|
-
}
|
|
497
|
-
stopVideoTrack() {
|
|
498
|
-
var _a, _b, _c, _d;
|
|
499
|
-
(_a = this.rawVideoTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
500
|
-
(_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
501
|
-
(_c = this.rawVideoTrack) === null || _c === void 0 ? void 0 : _c.release();
|
|
502
|
-
(_d = this.videoTrack) === null || _d === void 0 ? void 0 : _d.release();
|
|
503
|
-
}
|
|
504
475
|
stopScreenShareTracks(tracks = {}) {
|
|
505
476
|
var _a, _b, _c, _d;
|
|
506
477
|
const { audio = true, video = true } = tracks;
|
|
@@ -514,16 +485,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
514
485
|
this.screenShareEnabled = false;
|
|
515
486
|
}
|
|
516
487
|
}
|
|
517
|
-
removeAudioTrack() {
|
|
518
|
-
this.stopAudioTrack();
|
|
519
|
-
this.audioTrack = undefined;
|
|
520
|
-
this.rawAudioTrack = undefined;
|
|
521
|
-
}
|
|
522
|
-
removeVideoTrack() {
|
|
523
|
-
this.stopVideoTrack();
|
|
524
|
-
this.videoTrack = undefined;
|
|
525
|
-
this.rawVideoTrack = undefined;
|
|
526
|
-
}
|
|
527
488
|
removeScreenShareTracks(tracks) {
|
|
528
489
|
var _a;
|
|
529
490
|
(_a = this.screenShareTracks.video) === null || _a === void 0 ? void 0 : _a.removeEventListener('ended', this.onScreenShareEnded);
|
|
@@ -533,11 +494,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
533
494
|
video: undefined,
|
|
534
495
|
};
|
|
535
496
|
}
|
|
536
|
-
removeAllTracks() {
|
|
537
|
-
this.removeAudioTrack();
|
|
538
|
-
this.removeVideoTrack();
|
|
539
|
-
this.removeScreenShareTracks();
|
|
540
|
-
}
|
|
541
497
|
setAudioTrack(audioTrack) {
|
|
542
498
|
if (audioTrack === this.audioTrack) {
|
|
543
499
|
return;
|
|
@@ -570,12 +526,16 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
570
526
|
this.emit('SCREENSHARE_ENDED');
|
|
571
527
|
}
|
|
572
528
|
disableAudio() {
|
|
573
|
-
this
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
}
|
|
529
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
530
|
+
yield this.toggleAudio();
|
|
531
|
+
});
|
|
577
532
|
}
|
|
578
533
|
enableAudio() {
|
|
534
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
535
|
+
yield this.toggleAudio();
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
toggleAudio() {
|
|
579
539
|
return __awaiter(this, void 0, void 0, function* () {
|
|
580
540
|
var _a, _b;
|
|
581
541
|
if (this.permissions.audio !== 'ACCEPTED') {
|
|
@@ -591,10 +551,18 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
591
551
|
kind: 'audio',
|
|
592
552
|
message: this.permissions.audio,
|
|
593
553
|
});
|
|
594
|
-
if (this.permissions.audio === 'DENIED'
|
|
554
|
+
if (this.permissions.audio === 'DENIED' ||
|
|
555
|
+
this.permissions.audio === 'NOT_REQUESTED') {
|
|
595
556
|
this.audioEnabled = false;
|
|
596
557
|
return;
|
|
597
558
|
}
|
|
559
|
+
if (this.audioEnabled) {
|
|
560
|
+
this.audioEnabled = false;
|
|
561
|
+
if (this.audioTrack) {
|
|
562
|
+
this.audioTrack.enabled = this.audioEnabled;
|
|
563
|
+
}
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
598
566
|
try {
|
|
599
567
|
/**
|
|
600
568
|
* NOTE (@madhugb): We need to setup new stream,
|
|
@@ -631,20 +599,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
631
599
|
yield this.toggleVideo();
|
|
632
600
|
});
|
|
633
601
|
}
|
|
634
|
-
toggleAudio() {
|
|
635
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
636
|
-
var _a;
|
|
637
|
-
if (this.permissions.audio === 'DENIED') {
|
|
638
|
-
this.audioEnabled = false;
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
if (!this.audioTrack) {
|
|
642
|
-
yield this.setupAudioStream((_a = this.currentDevices.audio) === null || _a === void 0 ? void 0 : _a.deviceId);
|
|
643
|
-
}
|
|
644
|
-
this.audioEnabled = !this.audioEnabled;
|
|
645
|
-
this.audioTrack.enabled = this.audioEnabled;
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
602
|
toggleVideo() {
|
|
649
603
|
return __awaiter(this, void 0, void 0, function* () {
|
|
650
604
|
var _a, _b;
|
|
@@ -661,7 +615,8 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
661
615
|
kind: 'video',
|
|
662
616
|
message: this.permissions.video,
|
|
663
617
|
});
|
|
664
|
-
if (this.permissions.video === 'DENIED'
|
|
618
|
+
if (this.permissions.video === 'DENIED' ||
|
|
619
|
+
this.permissions.video === 'NOT_REQUESTED') {
|
|
665
620
|
this.videoEnabled = false;
|
|
666
621
|
return;
|
|
667
622
|
}
|
|
@@ -680,10 +635,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
680
635
|
}
|
|
681
636
|
setAudioDevice(device) {
|
|
682
637
|
return __awaiter(this, void 0, void 0, function* () {
|
|
683
|
-
yield
|
|
684
|
-
this.setupAudioStream(device.deviceId);
|
|
685
|
-
this.emit('AUDIO_TRACK_CHANGE');
|
|
686
|
-
this.emit('DEVICE_CHANGE', { device });
|
|
638
|
+
yield this.setupAudioStream(device.deviceId);
|
|
687
639
|
});
|
|
688
640
|
}
|
|
689
641
|
setVideoDevice(device) {
|
|
@@ -692,8 +644,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
692
644
|
this.removeVideoTrack();
|
|
693
645
|
}
|
|
694
646
|
yield this.setupVideoStream(device.deviceId);
|
|
695
|
-
this.emit('VIDEO_TRACK_CHANGE');
|
|
696
|
-
this.emit('DEVICE_CHANGE', { device });
|
|
697
647
|
});
|
|
698
648
|
}
|
|
699
649
|
setSpeakerDevice(device) {
|
|
@@ -703,7 +653,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
703
653
|
}
|
|
704
654
|
setDevice(route) {
|
|
705
655
|
return __awaiter(this, void 0, void 0, function* () {
|
|
706
|
-
|
|
656
|
+
yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").chooseAudioRoute(route.deviceId);
|
|
707
657
|
});
|
|
708
658
|
}
|
|
709
659
|
oniOSBroadcastStart() {
|
|
@@ -726,6 +676,12 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
726
676
|
return __awaiter(this, void 0, void 0, function* () {
|
|
727
677
|
if (this.screenShareEnabled && Platform.OS !== 'ios') {
|
|
728
678
|
this.removeScreenShareTracks();
|
|
679
|
+
try {
|
|
680
|
+
yield DyteHelper.stopService();
|
|
681
|
+
}
|
|
682
|
+
catch (e) {
|
|
683
|
+
console.warn('Failed to stop foreground service', e);
|
|
684
|
+
}
|
|
729
685
|
return;
|
|
730
686
|
}
|
|
731
687
|
if (Platform.OS === 'ios' && this.screenShareEnabled) {
|
|
@@ -733,13 +689,21 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
733
689
|
return;
|
|
734
690
|
}
|
|
735
691
|
if (Platform.OS === 'android') {
|
|
736
|
-
|
|
737
|
-
This is because we need to get user permission starting foreground service in Android >=14
|
|
738
|
-
1. createScreenCaptureIntent() -> startForeground()
|
|
739
|
-
*/
|
|
740
|
-
this.setScreenShareTracks(yield LocalMediaUtils.getScreenShareTracks());
|
|
692
|
+
this._pendingScreenShare = true;
|
|
741
693
|
yield this.configureForeground();
|
|
742
|
-
|
|
694
|
+
try {
|
|
695
|
+
this.setScreenShareTracks(yield LocalMediaUtils.getScreenShareTracks());
|
|
696
|
+
this.screenShareEnabled = true;
|
|
697
|
+
}
|
|
698
|
+
catch (e) {
|
|
699
|
+
console.warn('Failed to start screenshare', e);
|
|
700
|
+
this.screenShareEnabled = false;
|
|
701
|
+
yield DyteHelper.stopService();
|
|
702
|
+
this._pendingScreenShare = false;
|
|
703
|
+
}
|
|
704
|
+
finally {
|
|
705
|
+
this._pendingScreenShare = false;
|
|
706
|
+
}
|
|
743
707
|
}
|
|
744
708
|
if (Platform.OS === 'ios') {
|
|
745
709
|
NativeModules.DyteScreensharePickerView.showScreenSharePickerView();
|
|
@@ -756,11 +720,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
756
720
|
yield this.toggleScreenShare();
|
|
757
721
|
});
|
|
758
722
|
}
|
|
759
|
-
destruct() {
|
|
760
|
-
this.removeAllTracks();
|
|
761
|
-
this.removeAllListeners();
|
|
762
|
-
InCallManger.stop(undefined);
|
|
763
|
-
}
|
|
764
723
|
getAllDevices() {
|
|
765
724
|
return __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").availableDevices;
|
|
766
725
|
}
|
|
@@ -794,12 +753,16 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
794
753
|
*/
|
|
795
754
|
if (addedDevice) {
|
|
796
755
|
if (addedDevice.kind === 'audioinput') {
|
|
797
|
-
|
|
798
|
-
|
|
756
|
+
if (this.permissions.audio === 'DENIED' ||
|
|
757
|
+
this.permissions.audio === 'NOT_REQUESTED') {
|
|
758
|
+
yield this.setupSpeaker(addedDevice.deviceId);
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
yield this.setupAudioStream(addedDevice.deviceId);
|
|
762
|
+
}
|
|
799
763
|
}
|
|
800
764
|
else if (addedDevice.kind === 'videoinput') {
|
|
801
765
|
yield this.setupVideoStream(addedDevice.deviceId);
|
|
802
|
-
this.emit('DEVICE_CHANGE', this.currentDevices.video);
|
|
803
766
|
}
|
|
804
767
|
else if (addedDevice.kind === 'audiooutput') {
|
|
805
768
|
yield this.setupSpeaker(addedDevice.deviceId);
|
|
@@ -808,7 +771,13 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
808
771
|
}
|
|
809
772
|
if (removedDevice) {
|
|
810
773
|
if (removedDevice.kind === 'audioinput') {
|
|
811
|
-
|
|
774
|
+
if (this.permissions.audio === 'DENIED' ||
|
|
775
|
+
this.permissions.audio === 'NOT_REQUESTED') {
|
|
776
|
+
yield this.setupSpeaker();
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
yield this.setupAudioStream();
|
|
780
|
+
}
|
|
812
781
|
}
|
|
813
782
|
else if (removedDevice.kind === 'videoinput') {
|
|
814
783
|
yield this.setupVideoStream();
|
|
@@ -818,26 +787,13 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
818
787
|
}
|
|
819
788
|
this.emit('AUDIO_TRACK_CHANGE');
|
|
820
789
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
cleanUpTracks() {
|
|
825
|
-
var _a, _b, _c, _d;
|
|
826
|
-
(_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
827
|
-
(_b = this.rawAudioTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
828
|
-
(_c = this.videoTrack) === null || _c === void 0 ? void 0 : _c.stop();
|
|
829
|
-
(_d = this.rawVideoTrack) === null || _d === void 0 ? void 0 : _d.stop();
|
|
830
|
-
this.destructor();
|
|
831
|
-
}
|
|
832
|
-
destructMediaHandler() {
|
|
833
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
834
|
-
__classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").destruct();
|
|
835
|
-
return this.destruct();
|
|
790
|
+
if (changedDevices.added.length || changedDevices.removed.length) {
|
|
791
|
+
this.emit('DEVICE_LIST_UPDATED', changedDevices);
|
|
792
|
+
}
|
|
836
793
|
});
|
|
837
794
|
}
|
|
838
795
|
static init(_) {
|
|
839
796
|
return __awaiter(this, void 0, void 0, function* () {
|
|
840
|
-
yield setupPermissions(true, true);
|
|
841
797
|
const localMediaUtils = yield LocalMediaUtils.init();
|
|
842
798
|
return new LocalMediaHandler(localMediaUtils);
|
|
843
799
|
});
|
|
@@ -848,6 +804,74 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
848
804
|
on(event, listener) {
|
|
849
805
|
return super.on(event, listener);
|
|
850
806
|
}
|
|
807
|
+
destruct() {
|
|
808
|
+
this.destructMediaHandler();
|
|
809
|
+
}
|
|
810
|
+
destructMediaHandler() {
|
|
811
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
812
|
+
this.removeAllTracks();
|
|
813
|
+
this.removeAllListeners();
|
|
814
|
+
this.cleanUpTracks();
|
|
815
|
+
__classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").destruct();
|
|
816
|
+
try {
|
|
817
|
+
if (Platform.OS === 'android')
|
|
818
|
+
yield DyteHelper.stopService();
|
|
819
|
+
}
|
|
820
|
+
catch (_err) { }
|
|
821
|
+
InCallManger.stop(undefined);
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
cleanUpTracks() {
|
|
825
|
+
var _a, _b, _c, _d;
|
|
826
|
+
(_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
827
|
+
(_b = this.rawAudioTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
828
|
+
(_c = this.videoTrack) === null || _c === void 0 ? void 0 : _c.stop();
|
|
829
|
+
(_d = this.rawVideoTrack) === null || _d === void 0 ? void 0 : _d.stop();
|
|
830
|
+
this.destructor();
|
|
831
|
+
}
|
|
832
|
+
destructor() {
|
|
833
|
+
if (Platform.OS === 'android')
|
|
834
|
+
__classPrivateFieldGet(this, _LocalMediaHandler_appStateSubscription, "f").remove();
|
|
835
|
+
// TODO: Remove native broadcast listeners for group_call & not for webinar
|
|
836
|
+
BackgroundTimer.stop();
|
|
837
|
+
}
|
|
838
|
+
removeAllTracks() {
|
|
839
|
+
this.removeAudioTrack();
|
|
840
|
+
this.removeVideoTrack();
|
|
841
|
+
this.removeScreenShareTracks();
|
|
842
|
+
}
|
|
843
|
+
stopAudioTrack() {
|
|
844
|
+
var _a, _b;
|
|
845
|
+
(_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
846
|
+
(_b = this.audioTrack) === null || _b === void 0 ? void 0 : _b.release();
|
|
847
|
+
this.audioEnabled = false;
|
|
848
|
+
}
|
|
849
|
+
removeAudioTrack() {
|
|
850
|
+
this.stopAudioTrack();
|
|
851
|
+
this.audioTrack = undefined;
|
|
852
|
+
this.rawAudioTrack = undefined;
|
|
853
|
+
}
|
|
854
|
+
stopVideoTrack() {
|
|
855
|
+
var _a, _b, _c, _d;
|
|
856
|
+
(_a = this.rawVideoTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
857
|
+
(_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
858
|
+
(_c = this.rawVideoTrack) === null || _c === void 0 ? void 0 : _c.release();
|
|
859
|
+
(_d = this.videoTrack) === null || _d === void 0 ? void 0 : _d.release();
|
|
860
|
+
}
|
|
861
|
+
removeVideoTrack() {
|
|
862
|
+
this.stopVideoTrack();
|
|
863
|
+
this.videoTrack = undefined;
|
|
864
|
+
this.rawVideoTrack = undefined;
|
|
865
|
+
}
|
|
866
|
+
removeAllListeners(event) {
|
|
867
|
+
if (event === 'SCREENSHARE_TRACK_CHANGE' ||
|
|
868
|
+
event === 'DEVICE_LIST_UPDATED' ||
|
|
869
|
+
event === 'DEVICE_CHANGE' ||
|
|
870
|
+
!event) {
|
|
871
|
+
return null;
|
|
872
|
+
}
|
|
873
|
+
return super.removeAllListeners(event);
|
|
874
|
+
}
|
|
851
875
|
}
|
|
852
876
|
_LocalMediaHandler_localMediaUtils = new WeakMap(), _LocalMediaHandler_appState = new WeakMap(), _LocalMediaHandler_appStateSubscription = new WeakMap(), _LocalMediaHandler_interval = new WeakMap();
|
|
853
877
|
export default LocalMediaHandler;
|
|
@@ -68,6 +68,7 @@ export interface RealtimeKitMediaTrackConstraints extends MediaTrackConstraints
|
|
|
68
68
|
}
|
|
69
69
|
export interface RealtimeKitMediaStreamConstraints extends MediaStreamConstraints {
|
|
70
70
|
audio?: boolean | RealtimeKitMediaTrackConstraints;
|
|
71
|
+
timeout?: number;
|
|
71
72
|
}
|
|
72
73
|
export interface VideoConstraints {
|
|
73
74
|
[key: string]: RealtimeKitMediaTrackConstraints;
|
package/lib/LocalMediaUtils.d.ts
CHANGED
|
@@ -89,5 +89,12 @@ export default class LocalMediaUtils {
|
|
|
89
89
|
/**
|
|
90
90
|
* Returns all audio output devices (speaker devices).
|
|
91
91
|
*/
|
|
92
|
-
getSpeakerDevices():
|
|
92
|
+
getSpeakerDevices(): {
|
|
93
|
+
deviceId: string;
|
|
94
|
+
label: string;
|
|
95
|
+
kind: string;
|
|
96
|
+
groupId: string;
|
|
97
|
+
facing: string;
|
|
98
|
+
toJSON(): any;
|
|
99
|
+
}[];
|
|
93
100
|
}
|
package/lib/LocalMediaUtils.js
CHANGED
|
@@ -120,7 +120,6 @@ class LocalMediaUtils {
|
|
|
120
120
|
return Object.assign(Object.assign({}, audioDeviceProps), { deviceId: audioDevice, label: audioDevice, kind: 'audioinput' });
|
|
121
121
|
})
|
|
122
122
|
.filter((audioDevice) => audioDevice.connected);
|
|
123
|
-
// console.log('Resp: ', JSON.stringify(resp, null, 2));
|
|
124
123
|
return resp;
|
|
125
124
|
});
|
|
126
125
|
}
|
|
@@ -143,7 +142,7 @@ class LocalMediaUtils {
|
|
|
143
142
|
return yield mediaDevices.getUserMedia(constraints);
|
|
144
143
|
}
|
|
145
144
|
// NOTE(roerohan): The await is required to catch errors (if any).
|
|
146
|
-
return
|
|
145
|
+
return Promise.race([
|
|
147
146
|
mediaDevices.getUserMedia(constraints),
|
|
148
147
|
new Promise((_resolve, reject) => {
|
|
149
148
|
setTimeout(() => reject(new LocalMediaError('Get user media timed out', 'ERR_GUM_TIMEOUT')), timeout);
|
|
@@ -159,13 +158,14 @@ class LocalMediaUtils {
|
|
|
159
158
|
return __awaiter(this, void 0, void 0, function* () {
|
|
160
159
|
const mediaStream = (yield LocalMediaUtils.getUserMediaWithTimeout({
|
|
161
160
|
audio: true,
|
|
161
|
+
timeout: 5000,
|
|
162
162
|
}));
|
|
163
163
|
return mediaStream.getAudioTracks()[0];
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
static getVideoTrack(constraints) {
|
|
167
167
|
return __awaiter(this, void 0, void 0, function* () {
|
|
168
|
-
const mediaStream = (yield LocalMediaUtils.getUserMediaWithTimeout(constraints));
|
|
168
|
+
const mediaStream = (yield LocalMediaUtils.getUserMediaWithTimeout(Object.assign(Object.assign({}, constraints), { timeout: 5000 })));
|
|
169
169
|
return mediaStream.getVideoTracks()[0];
|
|
170
170
|
});
|
|
171
171
|
}
|
|
@@ -177,7 +177,6 @@ class LocalMediaUtils {
|
|
|
177
177
|
* is made: https://github.com/microsoft/TypeScript/issues/33232
|
|
178
178
|
*/
|
|
179
179
|
const stream = (yield mediaDevices.getDisplayMedia());
|
|
180
|
-
// console.log('Screenshare stream: ', stream.getVideoTracks());
|
|
181
180
|
return {
|
|
182
181
|
video: stream.getVideoTracks()[0],
|
|
183
182
|
audio: stream.getAudioTracks()[0],
|
|
@@ -186,11 +185,16 @@ class LocalMediaUtils {
|
|
|
186
185
|
}
|
|
187
186
|
static getAudioAndVideoTrack(constraints) {
|
|
188
187
|
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
188
|
+
try {
|
|
189
|
+
const mediaStream = (yield LocalMediaUtils.getUserMediaWithTimeout(Object.assign(Object.assign({}, constraints), { timeout: 5000 })));
|
|
190
|
+
return {
|
|
191
|
+
audioTrack: mediaStream.getAudioTracks()[0],
|
|
192
|
+
videoTrack: mediaStream.getVideoTracks()[0],
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
throw err;
|
|
197
|
+
}
|
|
194
198
|
});
|
|
195
199
|
}
|
|
196
200
|
onDeviceChange(callback) {
|
|
@@ -212,7 +216,9 @@ class LocalMediaUtils {
|
|
|
212
216
|
removed: previouslyAvailableDevices.filter((device) => !currentlyAvailableDeviceIds.includes(device.deviceId)),
|
|
213
217
|
};
|
|
214
218
|
this.repopulateAvailableDevices().then(() => {
|
|
215
|
-
|
|
219
|
+
if (changedDevices.added.length || changedDevices.removed.length) {
|
|
220
|
+
callback(changedDevices, false);
|
|
221
|
+
}
|
|
216
222
|
});
|
|
217
223
|
}
|
|
218
224
|
else {
|
|
@@ -224,7 +230,9 @@ class LocalMediaUtils {
|
|
|
224
230
|
removed: previouslyAvailableDevices.filter((device) => !currentlyAvailableDeviceIds.includes(device.deviceId)),
|
|
225
231
|
};
|
|
226
232
|
this.repopulateAvailableDevices().then(() => {
|
|
227
|
-
|
|
233
|
+
if (changedDevices.added.length || changedDevices.removed.length) {
|
|
234
|
+
callback(changedDevices, false);
|
|
235
|
+
}
|
|
228
236
|
});
|
|
229
237
|
}
|
|
230
238
|
});
|
|
@@ -269,7 +277,11 @@ class LocalMediaUtils {
|
|
|
269
277
|
* Returns all audio output devices (speaker devices).
|
|
270
278
|
*/
|
|
271
279
|
getSpeakerDevices() {
|
|
272
|
-
|
|
280
|
+
const speakerDevices = __classPrivateFieldGet(this, _LocalMediaUtils_availableDevices, "f");
|
|
281
|
+
// In Mobile, speaker devices are the same as audio input devices
|
|
282
|
+
return speakerDevices
|
|
283
|
+
.filter((device) => device.kind === 'audioinput')
|
|
284
|
+
.map((device) => (Object.assign(Object.assign({}, device), { deviceId: device.deviceId, label: device.label, kind: 'audiooutput' })));
|
|
273
285
|
}
|
|
274
286
|
}
|
|
275
287
|
_LocalMediaUtils_availableDevices = new WeakMap(), _LocalMediaUtils_nativeEventEmitter = new WeakMap();
|
package/lib/ReactContext.d.ts
CHANGED
|
@@ -22,16 +22,11 @@ export declare const RealtimeKitContext: React.Context<{
|
|
|
22
22
|
* @param renderBeforeLoad The provider will not render children by default
|
|
23
23
|
* until it gets a client object, renderBeforeLoad can be used to override that
|
|
24
24
|
*/
|
|
25
|
-
export declare function RealtimeKitProvider({ value, children,
|
|
25
|
+
export declare function RealtimeKitProvider({ value, children, fallback, }: {
|
|
26
26
|
value: RealtimeKitClient | undefined;
|
|
27
27
|
children: ReactChild | ReactChild[];
|
|
28
|
-
|
|
28
|
+
fallback?: ReactChild | ReactChild[];
|
|
29
29
|
}): JSX.Element;
|
|
30
|
-
export declare namespace RealtimeKitProvider {
|
|
31
|
-
var defaultProps: {
|
|
32
|
-
renderBeforeLoad: boolean;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
30
|
/**
|
|
36
31
|
* Hook which returns the reference to the DyteClient object
|
|
37
32
|
* @returns meeting instance from `useDyteClient()`
|
package/lib/ReactContext.js
CHANGED
|
@@ -59,31 +59,25 @@ export const RealtimeKitContext = createContext({
|
|
|
59
59
|
* @param renderBeforeLoad The provider will not render children by default
|
|
60
60
|
* until it gets a client object, renderBeforeLoad can be used to override that
|
|
61
61
|
*/
|
|
62
|
-
export function RealtimeKitProvider({ value, children,
|
|
63
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
64
|
-
renderBeforeLoad, }) {
|
|
62
|
+
export function RealtimeKitProvider({ value, children, fallback = null, }) {
|
|
65
63
|
const [updates, setUpdates] = useState();
|
|
66
64
|
const updatesRef = useRef();
|
|
67
65
|
useEffect(() => {
|
|
68
66
|
if (value) {
|
|
69
|
-
|
|
67
|
+
const newUpdate = new RealtimeKitUpdates(value);
|
|
68
|
+
setUpdates(newUpdate);
|
|
69
|
+
updatesRef.current = newUpdate;
|
|
70
70
|
}
|
|
71
71
|
return () => {
|
|
72
72
|
var _a;
|
|
73
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
74
73
|
(_a = updatesRef.current) === null || _a === void 0 ? void 0 : _a.clean();
|
|
75
74
|
};
|
|
76
75
|
}, [value]);
|
|
77
|
-
if (!value)
|
|
78
|
-
return null;
|
|
79
76
|
return (React.createElement(RealtimeKitContext.Provider, { value: {
|
|
80
77
|
meeting: value,
|
|
81
78
|
updates,
|
|
82
|
-
} }, children));
|
|
79
|
+
} }, value ? children : fallback));
|
|
83
80
|
}
|
|
84
|
-
RealtimeKitProvider.defaultProps = {
|
|
85
|
-
renderBeforeLoad: false,
|
|
86
|
-
};
|
|
87
81
|
/**
|
|
88
82
|
* Hook which returns the reference to the DyteClient object
|
|
89
83
|
* @returns meeting instance from `useDyteClient()`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/realtimekit-react-native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2-staging.10",
|
|
4
4
|
"description": "Cloudflare RealtimeKit SDK for react native",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"author": "Cloudflare",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"private": false,
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@cloudflare/realtimekit": "1.0.
|
|
28
|
+
"@cloudflare/realtimekit": "1.0.2",
|
|
29
29
|
"events": "^3.3.0",
|
|
30
30
|
"fast-base64-decode": "1.0.0",
|
|
31
31
|
"node-libs-react-native": "^1.2.1",
|
|
@@ -38,15 +38,13 @@
|
|
|
38
38
|
"android"
|
|
39
39
|
],
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@cloudflare/react-native-webrtc": "114.0.
|
|
41
|
+
"@cloudflare/react-native-webrtc": "~114.0.18",
|
|
42
42
|
"@expo/config-plugins": "*",
|
|
43
43
|
"react": "*",
|
|
44
44
|
"react-native": "*"
|
|
45
45
|
},
|
|
46
46
|
"publishConfig": {
|
|
47
|
-
"
|
|
48
|
-
"access": "public",
|
|
49
|
-
"tag": "latest"
|
|
47
|
+
"tag": "staging"
|
|
50
48
|
},
|
|
51
49
|
"scripts": {
|
|
52
50
|
"postpublish": "mv package.json.bak package.json"
|