@cloudflare/realtimekit-react-native 0.1.2-staging.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 +20 -10
- package/ios/screenshare/DyteScreenshareHandler.swift +2 -4
- package/lib/BackgroundHandler.js +15 -5
- package/lib/LocalMediaHandler.d.ts +12 -11
- package/lib/LocalMediaHandler.js +115 -82
- package/lib/LocalMediaUtils.js +0 -2
- package/package.json +3 -3
|
@@ -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);
|
|
@@ -1018,16 +1037,7 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
|
|
|
1018
1037
|
// NSLog(@"🧑💻 RNInCallManager.AudioRouteChange.Reason: CategoryChange. category=%@ mode=%@", self->_audioSession.category, self->_audioSession.mode);
|
|
1019
1038
|
break;
|
|
1020
1039
|
case AVAudioSessionRouteChangeReasonOverride:
|
|
1021
|
-
@
|
|
1022
|
-
// NSLog(@"🧑💻 RNInCallManager.AudioRouteChange.Reason: Override");
|
|
1023
|
-
[self sendEventWithName:@"onAudioDeviceChanged"
|
|
1024
|
-
body:@{
|
|
1025
|
-
@"availableAudioDeviceList": @"[speaker, earpiece]",
|
|
1026
|
-
@"selectedAudioDevice": @"speaker",
|
|
1027
|
-
}];
|
|
1028
|
-
} @catch (NSException *exception) {
|
|
1029
|
-
NSLog(@"Error sending event 'onAudioDeviceChanged' (Override): %@", exception.reason);
|
|
1030
|
-
}
|
|
1040
|
+
// NSLog(@"🧑💻 RNInCallManager.AudioRouteChange.Reason: Override");
|
|
1031
1041
|
break;
|
|
1032
1042
|
case AVAudioSessionRouteChangeReasonWakeFromSleep:
|
|
1033
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,16 +62,11 @@ 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;
|
|
@@ -86,13 +80,12 @@ export default class LocalMediaHandler extends EventEmitter {
|
|
|
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;
|
|
@@ -114,11 +107,19 @@ export default class LocalMediaHandler extends EventEmitter {
|
|
|
114
107
|
added: MediaDeviceInfo[];
|
|
115
108
|
removed: MediaDeviceInfo[];
|
|
116
109
|
}, forceDeviceChange: boolean): Promise<void>;
|
|
117
|
-
cleanUpTracks(): void;
|
|
118
|
-
destructMediaHandler(): Promise<void>;
|
|
119
110
|
static init(_: any): Promise<LocalMediaHandler>;
|
|
120
111
|
emit(event: keyof typeof MediaEvents, ...args: any[]): boolean;
|
|
121
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;
|
|
122
123
|
}
|
|
123
124
|
export interface RNLocalMediaHandler {
|
|
124
125
|
new (): LocalMediaHandler;
|
package/lib/LocalMediaHandler.js
CHANGED
|
@@ -22,7 +22,7 @@ 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';
|
|
@@ -47,12 +47,26 @@ function checkIfAudioTrackIsSilent(track) {
|
|
|
47
47
|
class LocalMediaHandler extends EventEmitter {
|
|
48
48
|
configureForeground() {
|
|
49
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
if (Platform.OS !== 'android')
|
|
51
|
+
return;
|
|
50
52
|
const val = yield DyteHelper.isForegroundServiceRunning();
|
|
51
|
-
if (
|
|
52
|
-
|
|
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
|
+
}
|
|
53
69
|
}
|
|
54
|
-
if (!val)
|
|
55
|
-
yield DyteHelper.startService();
|
|
56
70
|
});
|
|
57
71
|
}
|
|
58
72
|
constructor(localMediaUtils) {
|
|
@@ -61,8 +75,8 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
61
75
|
_LocalMediaHandler_appState.set(this, void 0);
|
|
62
76
|
_LocalMediaHandler_appStateSubscription.set(this, void 0);
|
|
63
77
|
_LocalMediaHandler_interval.set(this, void 0);
|
|
78
|
+
this._pendingScreenShare = false;
|
|
64
79
|
this._handleAppStateChange = (nextAppState) => {
|
|
65
|
-
// console.log('App state changed to : ', nextAppState);
|
|
66
80
|
if (__classPrivateFieldGet(this, _LocalMediaHandler_appState, "f").match(/inactive|background/) &&
|
|
67
81
|
nextAppState === 'active') {
|
|
68
82
|
BackgroundTimer.clearInterval(__classPrivateFieldGet(this, _LocalMediaHandler_interval, "f"));
|
|
@@ -78,7 +92,9 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
78
92
|
}
|
|
79
93
|
else {
|
|
80
94
|
if (__classPrivateFieldGet(this, _LocalMediaHandler_interval, "f") === null) {
|
|
81
|
-
this.
|
|
95
|
+
if (this.screenShareEnabled || this._pendingScreenShare) {
|
|
96
|
+
this.configureForeground();
|
|
97
|
+
}
|
|
82
98
|
}
|
|
83
99
|
__classPrivateFieldSet(this, _LocalMediaHandler_interval, BackgroundTimer.setInterval(() => { }, 1000), "f");
|
|
84
100
|
__classPrivateFieldSet(this, _LocalMediaHandler_appState, nextAppState, "f");
|
|
@@ -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;
|
|
@@ -250,9 +257,8 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
250
257
|
}
|
|
251
258
|
this.setAudioTrack(this.rawAudioTrack);
|
|
252
259
|
this.addMediaStreamTrackListeners(this.audioTrack);
|
|
260
|
+
this.emit('AUDIO_TRACK_CHANGE');
|
|
253
261
|
this.setDevice(this.currentDevices.audio);
|
|
254
|
-
// await InCallManger.chooseAudioRoute(audioDeviceId);
|
|
255
|
-
// console.log('Device selected: ', audioDeviceId);
|
|
256
262
|
/**
|
|
257
263
|
* NOTE(roerohan): Firefox does not show device labels until permissions are granted.
|
|
258
264
|
* So, we need to repopulate the devices once permission is granted.
|
|
@@ -263,10 +269,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
263
269
|
this.emit('DEVICE_CHANGE', {
|
|
264
270
|
device: this.currentDevices.audio,
|
|
265
271
|
});
|
|
266
|
-
/*
|
|
267
|
-
TODO
|
|
268
|
-
callStats.mediaPermission('AUDIO', CallStatsPermissionEnum.ACCEPTED);
|
|
269
|
-
callStats.selectedDevice('AUDIO', this.currentDevices.audio); */
|
|
270
272
|
});
|
|
271
273
|
}
|
|
272
274
|
onVisibilityChange() {
|
|
@@ -305,6 +307,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
305
307
|
}
|
|
306
308
|
this.setVideoTrack(this.rawVideoTrack);
|
|
307
309
|
this.addMediaStreamTrackListeners(this.rawVideoTrack);
|
|
310
|
+
this.emit('VIDEO_TRACK_CHANGE');
|
|
308
311
|
}
|
|
309
312
|
if (forceStopTrack) {
|
|
310
313
|
(_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
@@ -469,19 +472,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
469
472
|
}
|
|
470
473
|
});
|
|
471
474
|
}
|
|
472
|
-
stopAudioTrack() {
|
|
473
|
-
var _a, _b;
|
|
474
|
-
(_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
475
|
-
(_b = this.audioTrack) === null || _b === void 0 ? void 0 : _b.release();
|
|
476
|
-
this.audioEnabled = false;
|
|
477
|
-
}
|
|
478
|
-
stopVideoTrack() {
|
|
479
|
-
var _a, _b, _c, _d;
|
|
480
|
-
(_a = this.rawVideoTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
481
|
-
(_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
482
|
-
(_c = this.rawVideoTrack) === null || _c === void 0 ? void 0 : _c.release();
|
|
483
|
-
(_d = this.videoTrack) === null || _d === void 0 ? void 0 : _d.release();
|
|
484
|
-
}
|
|
485
475
|
stopScreenShareTracks(tracks = {}) {
|
|
486
476
|
var _a, _b, _c, _d;
|
|
487
477
|
const { audio = true, video = true } = tracks;
|
|
@@ -495,16 +485,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
495
485
|
this.screenShareEnabled = false;
|
|
496
486
|
}
|
|
497
487
|
}
|
|
498
|
-
removeAudioTrack() {
|
|
499
|
-
this.stopAudioTrack();
|
|
500
|
-
this.audioTrack = undefined;
|
|
501
|
-
this.rawAudioTrack = undefined;
|
|
502
|
-
}
|
|
503
|
-
removeVideoTrack() {
|
|
504
|
-
this.stopVideoTrack();
|
|
505
|
-
this.videoTrack = undefined;
|
|
506
|
-
this.rawVideoTrack = undefined;
|
|
507
|
-
}
|
|
508
488
|
removeScreenShareTracks(tracks) {
|
|
509
489
|
var _a;
|
|
510
490
|
(_a = this.screenShareTracks.video) === null || _a === void 0 ? void 0 : _a.removeEventListener('ended', this.onScreenShareEnded);
|
|
@@ -514,11 +494,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
514
494
|
video: undefined,
|
|
515
495
|
};
|
|
516
496
|
}
|
|
517
|
-
removeAllTracks() {
|
|
518
|
-
this.removeAudioTrack();
|
|
519
|
-
this.removeVideoTrack();
|
|
520
|
-
this.removeScreenShareTracks();
|
|
521
|
-
}
|
|
522
497
|
setAudioTrack(audioTrack) {
|
|
523
498
|
if (audioTrack === this.audioTrack) {
|
|
524
499
|
return;
|
|
@@ -660,10 +635,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
660
635
|
}
|
|
661
636
|
setAudioDevice(device) {
|
|
662
637
|
return __awaiter(this, void 0, void 0, function* () {
|
|
663
|
-
yield
|
|
664
|
-
this.setupAudioStream(device.deviceId);
|
|
665
|
-
this.emit('AUDIO_TRACK_CHANGE');
|
|
666
|
-
this.emit('DEVICE_CHANGE', { device });
|
|
638
|
+
yield this.setupAudioStream(device.deviceId);
|
|
667
639
|
});
|
|
668
640
|
}
|
|
669
641
|
setVideoDevice(device) {
|
|
@@ -672,8 +644,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
672
644
|
this.removeVideoTrack();
|
|
673
645
|
}
|
|
674
646
|
yield this.setupVideoStream(device.deviceId);
|
|
675
|
-
this.emit('VIDEO_TRACK_CHANGE');
|
|
676
|
-
this.emit('DEVICE_CHANGE', { device });
|
|
677
647
|
});
|
|
678
648
|
}
|
|
679
649
|
setSpeakerDevice(device) {
|
|
@@ -683,7 +653,7 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
683
653
|
}
|
|
684
654
|
setDevice(route) {
|
|
685
655
|
return __awaiter(this, void 0, void 0, function* () {
|
|
686
|
-
|
|
656
|
+
yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").chooseAudioRoute(route.deviceId);
|
|
687
657
|
});
|
|
688
658
|
}
|
|
689
659
|
oniOSBroadcastStart() {
|
|
@@ -706,6 +676,12 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
706
676
|
return __awaiter(this, void 0, void 0, function* () {
|
|
707
677
|
if (this.screenShareEnabled && Platform.OS !== 'ios') {
|
|
708
678
|
this.removeScreenShareTracks();
|
|
679
|
+
try {
|
|
680
|
+
yield DyteHelper.stopService();
|
|
681
|
+
}
|
|
682
|
+
catch (e) {
|
|
683
|
+
console.warn('Failed to stop foreground service', e);
|
|
684
|
+
}
|
|
709
685
|
return;
|
|
710
686
|
}
|
|
711
687
|
if (Platform.OS === 'ios' && this.screenShareEnabled) {
|
|
@@ -713,13 +689,21 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
713
689
|
return;
|
|
714
690
|
}
|
|
715
691
|
if (Platform.OS === 'android') {
|
|
716
|
-
|
|
717
|
-
This is because we need to get user permission starting foreground service in Android >=14
|
|
718
|
-
1. createScreenCaptureIntent() -> startForeground()
|
|
719
|
-
*/
|
|
720
|
-
this.setScreenShareTracks(yield LocalMediaUtils.getScreenShareTracks());
|
|
692
|
+
this._pendingScreenShare = true;
|
|
721
693
|
yield this.configureForeground();
|
|
722
|
-
|
|
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
|
+
}
|
|
723
707
|
}
|
|
724
708
|
if (Platform.OS === 'ios') {
|
|
725
709
|
NativeModules.DyteScreensharePickerView.showScreenSharePickerView();
|
|
@@ -736,11 +720,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
736
720
|
yield this.toggleScreenShare();
|
|
737
721
|
});
|
|
738
722
|
}
|
|
739
|
-
destruct() {
|
|
740
|
-
this.removeAllTracks();
|
|
741
|
-
this.removeAllListeners();
|
|
742
|
-
InCallManger.stop(undefined);
|
|
743
|
-
}
|
|
744
723
|
getAllDevices() {
|
|
745
724
|
return __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").availableDevices;
|
|
746
725
|
}
|
|
@@ -813,20 +792,6 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
813
792
|
}
|
|
814
793
|
});
|
|
815
794
|
}
|
|
816
|
-
cleanUpTracks() {
|
|
817
|
-
var _a, _b, _c, _d;
|
|
818
|
-
(_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
|
|
819
|
-
(_b = this.rawAudioTrack) === null || _b === void 0 ? void 0 : _b.stop();
|
|
820
|
-
(_c = this.videoTrack) === null || _c === void 0 ? void 0 : _c.stop();
|
|
821
|
-
(_d = this.rawVideoTrack) === null || _d === void 0 ? void 0 : _d.stop();
|
|
822
|
-
this.destructor();
|
|
823
|
-
}
|
|
824
|
-
destructMediaHandler() {
|
|
825
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
826
|
-
__classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").destruct();
|
|
827
|
-
return this.destruct();
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
795
|
static init(_) {
|
|
831
796
|
return __awaiter(this, void 0, void 0, function* () {
|
|
832
797
|
const localMediaUtils = yield LocalMediaUtils.init();
|
|
@@ -839,6 +804,74 @@ class LocalMediaHandler extends EventEmitter {
|
|
|
839
804
|
on(event, listener) {
|
|
840
805
|
return super.on(event, listener);
|
|
841
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
|
+
}
|
|
842
875
|
}
|
|
843
876
|
_LocalMediaHandler_localMediaUtils = new WeakMap(), _LocalMediaHandler_appState = new WeakMap(), _LocalMediaHandler_appStateSubscription = new WeakMap(), _LocalMediaHandler_interval = new WeakMap();
|
|
844
877
|
export default LocalMediaHandler;
|
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
|
}
|
|
@@ -178,7 +177,6 @@ class LocalMediaUtils {
|
|
|
178
177
|
* is made: https://github.com/microsoft/TypeScript/issues/33232
|
|
179
178
|
*/
|
|
180
179
|
const stream = (yield mediaDevices.getDisplayMedia());
|
|
181
|
-
// console.log('Screenshare stream: ', stream.getVideoTracks());
|
|
182
180
|
return {
|
|
183
181
|
video: stream.getVideoTracks()[0],
|
|
184
182
|
audio: stream.getAudioTracks()[0],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudflare/realtimekit-react-native",
|
|
3
|
-
"version": "0.1.2-staging.
|
|
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,7 +38,7 @@
|
|
|
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": "*"
|