@cloudflare/realtimekit-react-native 1.2.0-staging.3 → 1.2.0-staging.5
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/RealtimeKitCore.podspec +1 -1
- package/ios/scripts/screenshare_sources.rb +74 -0
- package/lib/commonjs/AudioSampleHandler.js +1 -7
- package/lib/commonjs/AudioSampleHandler.js.map +1 -1
- package/lib/commonjs/BackgroundHandler.js +0 -7
- package/lib/commonjs/BackgroundHandler.js.map +1 -1
- package/lib/commonjs/DeviceInfo.js +0 -4
- package/lib/commonjs/DeviceInfo.js.map +1 -1
- package/lib/commonjs/LocalMediaError.js +0 -4
- package/lib/commonjs/LocalMediaError.js.map +1 -1
- package/lib/commonjs/LocalMediaHandler.js +135 -186
- package/lib/commonjs/LocalMediaHandler.js.map +1 -1
- package/lib/commonjs/LocalMediaInterfaces.js.map +1 -1
- package/lib/commonjs/LocalMediaUtils.js +19 -27
- package/lib/commonjs/LocalMediaUtils.js.map +1 -1
- package/lib/commonjs/NativeAudioManager.js +3 -3
- package/lib/commonjs/NativeAudioManager.js.map +1 -1
- package/lib/commonjs/PermissionHandler.js.map +1 -1
- package/lib/commonjs/ReactContext.js +39 -43
- package/lib/commonjs/ReactContext.js.map +1 -1
- package/lib/commonjs/ReactHooks.js +7 -9
- package/lib/commonjs/ReactHooks.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/utils/crypto.js.map +1 -1
- package/lib/commonjs/utils/version.js +1 -1
- package/lib/commonjs/utils/version.js.map +1 -1
- package/lib/module/AudioSampleHandler.js +3 -7
- package/lib/module/AudioSampleHandler.js.map +1 -1
- package/lib/module/BackgroundHandler.js +2 -7
- package/lib/module/BackgroundHandler.js.map +1 -1
- package/lib/module/DeviceInfo.js +2 -4
- package/lib/module/DeviceInfo.js.map +1 -1
- package/lib/module/LocalMediaError.js +2 -4
- package/lib/module/LocalMediaError.js.map +1 -1
- package/lib/module/LocalMediaHandler.js +135 -186
- package/lib/module/LocalMediaHandler.js.map +1 -1
- package/lib/module/LocalMediaInterfaces.js +1 -1
- package/lib/module/LocalMediaInterfaces.js.map +1 -1
- package/lib/module/LocalMediaUtils.js +21 -27
- package/lib/module/LocalMediaUtils.js.map +1 -1
- package/lib/module/NativeAudioManager.js +5 -3
- package/lib/module/NativeAudioManager.js.map +1 -1
- package/lib/module/PermissionHandler.js +2 -0
- package/lib/module/PermissionHandler.js.map +1 -1
- package/lib/module/ReactContext.js +39 -43
- package/lib/module/ReactContext.js.map +1 -1
- package/lib/module/ReactHooks.js +9 -9
- package/lib/module/ReactHooks.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/crypto.js +2 -0
- package/lib/module/utils/crypto.js.map +1 -1
- package/lib/module/utils/version.js +3 -1
- package/lib/module/utils/version.js.map +1 -1
- package/lib/typescript/AudioSampleHandler.d.ts +1 -0
- package/lib/typescript/AudioSampleHandler.d.ts.map +1 -0
- package/lib/typescript/BackgroundHandler.d.ts +1 -0
- package/lib/typescript/BackgroundHandler.d.ts.map +1 -0
- package/lib/typescript/DeviceInfo.d.ts +1 -0
- package/lib/typescript/DeviceInfo.d.ts.map +1 -0
- package/lib/typescript/LocalMediaError.d.ts +1 -0
- package/lib/typescript/LocalMediaError.d.ts.map +1 -0
- package/lib/typescript/LocalMediaHandler.d.ts +1 -0
- package/lib/typescript/LocalMediaHandler.d.ts.map +1 -0
- package/lib/typescript/LocalMediaInterfaces.d.ts +1 -0
- package/lib/typescript/LocalMediaInterfaces.d.ts.map +1 -0
- package/lib/typescript/LocalMediaUtils.d.ts +1 -0
- package/lib/typescript/LocalMediaUtils.d.ts.map +1 -0
- package/lib/typescript/NativeAudioManager.d.ts +1 -0
- package/lib/typescript/NativeAudioManager.d.ts.map +1 -0
- package/lib/typescript/PermissionHandler.d.ts +1 -0
- package/lib/typescript/PermissionHandler.d.ts.map +1 -0
- package/lib/typescript/ReactContext.d.ts +1 -0
- package/lib/typescript/ReactContext.d.ts.map +1 -0
- package/lib/typescript/ReactHooks.d.ts +1 -0
- package/lib/typescript/ReactHooks.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/utils/crypto.d.ts +1 -0
- package/lib/typescript/utils/crypto.d.ts.map +1 -0
- package/lib/typescript/utils/version.d.ts +2 -1
- package/lib/typescript/utils/version.d.ts.map +1 -0
- package/package.json +3 -3
|
@@ -11,14 +11,8 @@ var _BackgroundHandler = _interopRequireDefault(require("./BackgroundHandler"));
|
|
|
11
11
|
var _NativeAudioManager = _interopRequireDefault(require("./NativeAudioManager"));
|
|
12
12
|
var _PermissionHandler = require("./PermissionHandler");
|
|
13
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
17
|
-
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
|
|
18
|
-
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
|
|
19
|
-
function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
|
|
20
|
-
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
|
|
21
|
-
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); } /* eslint-disable @typescript-eslint/no-unused-vars */
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
15
|
+
|
|
22
16
|
const {
|
|
23
17
|
RTKHelper,
|
|
24
18
|
BroadcastEventEmitter
|
|
@@ -37,8 +31,6 @@ let _meetingServiceConfig = {
|
|
|
37
31
|
channelId: 'rtk_meeting',
|
|
38
32
|
channelName: 'Ongoing Meeting'
|
|
39
33
|
};
|
|
40
|
-
|
|
41
|
-
// eslint-disable-next-line no-shadow
|
|
42
34
|
let MediaEvents = exports.MediaEvents = /*#__PURE__*/function (MediaEvents) {
|
|
43
35
|
MediaEvents[MediaEvents["AUDIO_TRACK_CHANGE"] = 0] = "AUDIO_TRACK_CHANGE";
|
|
44
36
|
MediaEvents[MediaEvents["VIDEO_TRACK_CHANGE"] = 1] = "VIDEO_TRACK_CHANGE";
|
|
@@ -54,76 +46,50 @@ function checkIfAudioTrackIsSilent(track) {
|
|
|
54
46
|
//TODO
|
|
55
47
|
return !!track;
|
|
56
48
|
}
|
|
57
|
-
var _localMediaUtils = /*#__PURE__*/new WeakMap();
|
|
58
|
-
var _appState = /*#__PURE__*/new WeakMap();
|
|
59
|
-
var _appStateSubscription = /*#__PURE__*/new WeakMap();
|
|
60
|
-
var _interval = /*#__PURE__*/new WeakMap();
|
|
61
|
-
var _screenShareState = /*#__PURE__*/new WeakMap();
|
|
62
|
-
var _deviceRemovalTimeout = /*#__PURE__*/new WeakMap();
|
|
63
|
-
var _broadcastEmitter = /*#__PURE__*/new WeakMap();
|
|
64
|
-
var _broadcastStartedSubscription = /*#__PURE__*/new WeakMap();
|
|
65
|
-
var _broadcastStoppedSubscription = /*#__PURE__*/new WeakMap();
|
|
66
49
|
class LocalMediaHandler extends _events.EventEmitter {
|
|
50
|
+
#localMediaUtils;
|
|
51
|
+
#appState;
|
|
52
|
+
#appStateSubscription;
|
|
53
|
+
#interval;
|
|
54
|
+
#screenShareState;
|
|
55
|
+
_pendingScreenShare = false;
|
|
56
|
+
#deviceRemovalTimeout = null;
|
|
57
|
+
#broadcastEmitter;
|
|
58
|
+
#broadcastStartedSubscription;
|
|
59
|
+
#broadcastStoppedSubscription;
|
|
60
|
+
_handleAppStateChange = nextAppState => {
|
|
61
|
+
const prevAppState = this.#appState;
|
|
62
|
+
this.#appState = nextAppState;
|
|
63
|
+
if (prevAppState.match(/inactive|background/) && nextAppState === 'active') {
|
|
64
|
+
// App returned to foreground — stop the background keep-alive timer
|
|
65
|
+
// and kick the video track to recover the camera feed.
|
|
66
|
+
if (this.#interval !== null) {
|
|
67
|
+
_BackgroundHandler.default.clearInterval(this.#interval);
|
|
68
|
+
this.#interval = null;
|
|
69
|
+
}
|
|
70
|
+
if (this.videoTrack) {
|
|
71
|
+
this.videoTrack.enabled = false;
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
if (this.videoTrack) {
|
|
74
|
+
this.videoTrack.enabled = true;
|
|
75
|
+
}
|
|
76
|
+
}, 100);
|
|
77
|
+
}
|
|
78
|
+
} else if (nextAppState.match(/inactive|background/)) {
|
|
79
|
+
// App moved to background — start a recurring no-op timer to keep the
|
|
80
|
+
// JS thread alive so WebRTC/native events continue to be processed.
|
|
81
|
+
// Clear any existing interval first to avoid accumulation.
|
|
82
|
+
if (this.#interval !== null) {
|
|
83
|
+
_BackgroundHandler.default.clearInterval(this.#interval);
|
|
84
|
+
}
|
|
85
|
+
this.#interval = _BackgroundHandler.default.setInterval(() => {}, 1000);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
67
88
|
constructor(localMediaUtils) {
|
|
68
89
|
super();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
_classPrivateFieldInitSpec(this, _interval, void 0);
|
|
73
|
-
_classPrivateFieldInitSpec(this, _screenShareState, void 0);
|
|
74
|
-
_defineProperty(this, "audioTrack", void 0);
|
|
75
|
-
_defineProperty(this, "rawAudioTrack", void 0);
|
|
76
|
-
_defineProperty(this, "videoTrack", void 0);
|
|
77
|
-
_defineProperty(this, "rawVideoTrack", void 0);
|
|
78
|
-
_defineProperty(this, "screenShareTracks", void 0);
|
|
79
|
-
_defineProperty(this, "audioEnabled", void 0);
|
|
80
|
-
_defineProperty(this, "videoEnabled", void 0);
|
|
81
|
-
_defineProperty(this, "screenShareEnabled", void 0);
|
|
82
|
-
_defineProperty(this, "_pendingScreenShare", false);
|
|
83
|
-
_defineProperty(this, "currentDevices", void 0);
|
|
84
|
-
_defineProperty(this, "permissions", void 0);
|
|
85
|
-
_classPrivateFieldInitSpec(this, _deviceRemovalTimeout, null);
|
|
86
|
-
_classPrivateFieldInitSpec(this, _broadcastEmitter, void 0);
|
|
87
|
-
_classPrivateFieldInitSpec(this, _broadcastStartedSubscription, void 0);
|
|
88
|
-
_classPrivateFieldInitSpec(this, _broadcastStoppedSubscription, void 0);
|
|
89
|
-
_defineProperty(this, "_handleAppStateChange", nextAppState => {
|
|
90
|
-
const prevAppState = _classPrivateFieldGet(_appState, this);
|
|
91
|
-
_classPrivateFieldSet(_appState, this, nextAppState);
|
|
92
|
-
if (prevAppState.match(/inactive|background/) && nextAppState === 'active') {
|
|
93
|
-
// App returned to foreground — stop the background keep-alive timer
|
|
94
|
-
// and kick the video track to recover the camera feed.
|
|
95
|
-
if (_classPrivateFieldGet(_interval, this) !== null) {
|
|
96
|
-
_BackgroundHandler.default.clearInterval(_classPrivateFieldGet(_interval, this));
|
|
97
|
-
_classPrivateFieldSet(_interval, this, null);
|
|
98
|
-
}
|
|
99
|
-
if (this.videoTrack) {
|
|
100
|
-
this.videoTrack.enabled = false;
|
|
101
|
-
setTimeout(() => {
|
|
102
|
-
if (this.videoTrack) {
|
|
103
|
-
this.videoTrack.enabled = true;
|
|
104
|
-
}
|
|
105
|
-
}, 100);
|
|
106
|
-
}
|
|
107
|
-
} else if (nextAppState.match(/inactive|background/)) {
|
|
108
|
-
// App moved to background — start a recurring no-op timer to keep the
|
|
109
|
-
// JS thread alive so WebRTC/native events continue to be processed.
|
|
110
|
-
// Clear any existing interval first to avoid accumulation.
|
|
111
|
-
if (_classPrivateFieldGet(_interval, this) !== null) {
|
|
112
|
-
_BackgroundHandler.default.clearInterval(_classPrivateFieldGet(_interval, this));
|
|
113
|
-
}
|
|
114
|
-
_classPrivateFieldSet(_interval, this, _BackgroundHandler.default.setInterval(() => {}, 1000));
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
// Arrow function so `this` is stable — the same reference is used in both
|
|
118
|
-
// addEventListener (setScreenShareTracks) and removeEventListener
|
|
119
|
-
// (removeScreenShareTracks). A regular method + .bind(this) creates a new
|
|
120
|
-
// function object on every call, making removeEventListener a no-op.
|
|
121
|
-
_defineProperty(this, "onScreenShareEnded", () => {
|
|
122
|
-
this.emit('SCREENSHARE_ENDED');
|
|
123
|
-
});
|
|
124
|
-
_classPrivateFieldSet(_localMediaUtils, this, localMediaUtils);
|
|
125
|
-
_classPrivateFieldSet(_broadcastEmitter, this, broadcastEmitter);
|
|
126
|
-
_classPrivateFieldSet(_appState, this, '');
|
|
90
|
+
this.#localMediaUtils = localMediaUtils;
|
|
91
|
+
this.#broadcastEmitter = broadcastEmitter;
|
|
92
|
+
this.#appState = '';
|
|
127
93
|
this.audioEnabled = true;
|
|
128
94
|
this.videoEnabled = true;
|
|
129
95
|
this.screenShareEnabled = false;
|
|
@@ -141,16 +107,16 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
141
107
|
speaker: undefined
|
|
142
108
|
};
|
|
143
109
|
// LocalMediaUtils onDeviceChange with callback from native onAudioDeviceChanged events
|
|
144
|
-
|
|
110
|
+
this.#localMediaUtils.onDeviceChange(async changedDevices => {
|
|
145
111
|
await this.onDeviceChange(changedDevices, false);
|
|
146
112
|
});
|
|
147
113
|
if (_reactNative.Platform.OS === 'ios') {
|
|
148
|
-
|
|
114
|
+
this.#broadcastStartedSubscription = this.#broadcastEmitter.addListener('iOS_BroadcastStarted', () => {
|
|
149
115
|
this.oniOSBroadcastStart();
|
|
150
|
-
})
|
|
151
|
-
|
|
116
|
+
});
|
|
117
|
+
this.#broadcastStoppedSubscription = this.#broadcastEmitter.addListener('iOS_BroadcastStopped', () => {
|
|
152
118
|
this.oniOSBroadcastStop();
|
|
153
|
-
})
|
|
119
|
+
});
|
|
154
120
|
}
|
|
155
121
|
_NativeAudioManager.default.start({
|
|
156
122
|
media: 'video'
|
|
@@ -160,27 +126,20 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
160
126
|
if (!this.currentDevices.audio || !this.audioEnabled) {
|
|
161
127
|
return;
|
|
162
128
|
}
|
|
163
|
-
await Promise.race([new Promise(resolve => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
resolve(e);
|
|
167
|
-
});
|
|
168
|
-
}), new Promise(resolve => setTimeout(resolve, 50))]);
|
|
129
|
+
await Promise.race([new Promise(resolve => this.audioTrack?.addEventListener('unmute', e => {
|
|
130
|
+
resolve(e);
|
|
131
|
+
})), new Promise(resolve => setTimeout(resolve, 50))]);
|
|
169
132
|
const reacquireTrack = await this.shouldReacquireTrack('audio');
|
|
170
133
|
if (reacquireTrack) {
|
|
171
|
-
var _this$currentDevices$;
|
|
172
134
|
this.removeMediaStreamTrackListeners(this.audioTrack);
|
|
173
|
-
await this.setupAudioStream(
|
|
135
|
+
await this.setupAudioStream(this.currentDevices.audio?.deviceId);
|
|
174
136
|
this.addMediaStreamTrackListeners(this.audioTrack);
|
|
175
137
|
this.emit('AUDIO_TRACK_CHANGE');
|
|
176
138
|
}
|
|
177
139
|
}
|
|
178
140
|
async conditionallyRestartVideo() {
|
|
179
141
|
if (!this.currentDevices.video || !this.videoEnabled) return;
|
|
180
|
-
await Promise.race([new Promise(resolve =>
|
|
181
|
-
var _this$videoTrack;
|
|
182
|
-
return (_this$videoTrack = this.videoTrack) === null || _this$videoTrack === void 0 ? void 0 : _this$videoTrack.addEventListener('unmute', resolve);
|
|
183
|
-
}), new Promise(resolve => setTimeout(resolve, 50))]);
|
|
142
|
+
await Promise.race([new Promise(resolve => this.videoTrack?.addEventListener('unmute', resolve)), new Promise(resolve => setTimeout(resolve, 50))]);
|
|
184
143
|
const reacquireTrack = await this.shouldReacquireTrack('video');
|
|
185
144
|
if (reacquireTrack) {
|
|
186
145
|
this.removeMediaStreamTrackListeners(this.videoTrack);
|
|
@@ -236,8 +195,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
236
195
|
return mediaStreamTrack;
|
|
237
196
|
}
|
|
238
197
|
async setupAudioStream(deviceId, forceStopTrack = false) {
|
|
239
|
-
|
|
240
|
-
const audioDevices = await _classPrivateFieldGet(_localMediaUtils, this).getAudioDevices();
|
|
198
|
+
const audioDevices = await this.#localMediaUtils.getAudioDevices();
|
|
241
199
|
if (!audioDevices.length) {
|
|
242
200
|
return;
|
|
243
201
|
}
|
|
@@ -245,13 +203,12 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
245
203
|
if (!audioDeviceId) {
|
|
246
204
|
audioDeviceId = (await this.getOperationalMicDeviceId()).deviceId;
|
|
247
205
|
}
|
|
248
|
-
if (
|
|
249
|
-
this.currentDevices.audio =
|
|
206
|
+
if (this.currentDevices.audio?.deviceId !== audioDeviceId) {
|
|
207
|
+
this.currentDevices.audio = this.#localMediaUtils.getDeviceById(audioDeviceId, 'audioinput');
|
|
250
208
|
}
|
|
251
209
|
if (forceStopTrack) {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
(_this$rawAudioTrack = this.rawAudioTrack) === null || _this$rawAudioTrack === void 0 || _this$rawAudioTrack.stop();
|
|
210
|
+
this.audioTrack?.stop();
|
|
211
|
+
this.rawAudioTrack?.stop();
|
|
255
212
|
}
|
|
256
213
|
try {
|
|
257
214
|
this.rawAudioTrack = await _LocalMediaUtils.default.getAudioTrack();
|
|
@@ -269,7 +226,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
269
226
|
* So, we need to repopulate the devices once permission is granted.
|
|
270
227
|
*/
|
|
271
228
|
if (this.audioTrack && this.permissions.audio === 'NOT_REQUESTED') {
|
|
272
|
-
await
|
|
229
|
+
await this.#localMediaUtils.repopulateAvailableDevices();
|
|
273
230
|
}
|
|
274
231
|
|
|
275
232
|
// Force update audio devices on iOS after audio session is active
|
|
@@ -283,8 +240,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
283
240
|
// pass
|
|
284
241
|
}
|
|
285
242
|
async setupVideoStream(deviceId, forceStopTrack = false) {
|
|
286
|
-
|
|
287
|
-
const videoDevices = await _classPrivateFieldGet(_localMediaUtils, this).getVideoDevices();
|
|
243
|
+
const videoDevices = await this.#localMediaUtils.getVideoDevices();
|
|
288
244
|
if (!videoDevices.length) {
|
|
289
245
|
return;
|
|
290
246
|
}
|
|
@@ -292,8 +248,8 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
292
248
|
if (!videoDeviceId) {
|
|
293
249
|
videoDeviceId = (await this.getOperationalWebcamDeviceId()).deviceId;
|
|
294
250
|
}
|
|
295
|
-
if (
|
|
296
|
-
this.currentDevices.video =
|
|
251
|
+
if (this.currentDevices.video?.deviceId !== videoDeviceId) {
|
|
252
|
+
this.currentDevices.video = this.#localMediaUtils.getDeviceById(videoDeviceId, 'videoinput');
|
|
297
253
|
}
|
|
298
254
|
|
|
299
255
|
/**
|
|
@@ -317,24 +273,22 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
317
273
|
this.emit('VIDEO_TRACK_CHANGE');
|
|
318
274
|
}
|
|
319
275
|
if (forceStopTrack) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
(_this$rawVideoTrack = this.rawVideoTrack) === null || _this$rawVideoTrack === void 0 || _this$rawVideoTrack.stop();
|
|
276
|
+
this.videoTrack?.stop();
|
|
277
|
+
this.rawVideoTrack?.stop();
|
|
323
278
|
}
|
|
324
279
|
/**
|
|
325
280
|
* NOTE(roerohan): Firefox does not show device labels until permissions are granted.
|
|
326
281
|
* So, we need to repopulate the devices once permission is granted.
|
|
327
282
|
*/
|
|
328
283
|
if (this.videoTrack && this.permissions.video === 'NOT_REQUESTED') {
|
|
329
|
-
await
|
|
284
|
+
await this.#localMediaUtils.repopulateAvailableDevices();
|
|
330
285
|
}
|
|
331
286
|
this.emit('DEVICE_CHANGE', {
|
|
332
287
|
device: this.currentDevices.video
|
|
333
288
|
});
|
|
334
289
|
}
|
|
335
290
|
async setupSpeaker(deviceId) {
|
|
336
|
-
|
|
337
|
-
const speakerDevices = await _classPrivateFieldGet(_localMediaUtils, this).getSpeakerDevices();
|
|
291
|
+
const speakerDevices = await this.#localMediaUtils.getSpeakerDevices();
|
|
338
292
|
if (!speakerDevices.length) {
|
|
339
293
|
return;
|
|
340
294
|
}
|
|
@@ -344,10 +298,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
344
298
|
speakerDeviceId = deviceId;
|
|
345
299
|
} else {
|
|
346
300
|
// Prefer current device if it's still available
|
|
347
|
-
const currentDeviceStillAvailable = speakerDevices.find(d =>
|
|
348
|
-
var _this$currentDevices$4;
|
|
349
|
-
return d.deviceId === ((_this$currentDevices$4 = this.currentDevices.speaker) === null || _this$currentDevices$4 === void 0 ? void 0 : _this$currentDevices$4.deviceId);
|
|
350
|
-
});
|
|
301
|
+
const currentDeviceStillAvailable = speakerDevices.find(d => d.deviceId === this.currentDevices.speaker?.deviceId);
|
|
351
302
|
if (currentDeviceStillAvailable) {
|
|
352
303
|
// Keep current device if it's still connected
|
|
353
304
|
speakerDeviceId = this.currentDevices.speaker.deviceId;
|
|
@@ -356,12 +307,12 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
356
307
|
const bluetoothDevice = speakerDevices.find(d => d.deviceId === 'bluetooth');
|
|
357
308
|
const wiredDevice = speakerDevices.find(d => d.deviceId === 'wired');
|
|
358
309
|
const speakerDevice = speakerDevices.find(d => d.deviceId === 'speaker');
|
|
359
|
-
speakerDeviceId =
|
|
310
|
+
speakerDeviceId = bluetoothDevice?.deviceId ?? wiredDevice?.deviceId ?? speakerDevice?.deviceId ?? speakerDevices[0].deviceId;
|
|
360
311
|
}
|
|
361
312
|
}
|
|
362
|
-
if (
|
|
313
|
+
if (this.currentDevices.speaker?.deviceId !== speakerDeviceId) {
|
|
363
314
|
// Audio Input devices are same as output devices in mobile
|
|
364
|
-
this.currentDevices.audio =
|
|
315
|
+
this.currentDevices.audio = this.#localMediaUtils.getDeviceById(speakerDeviceId, 'audioinput');
|
|
365
316
|
this.currentDevices.speaker = this.currentDevices.audio;
|
|
366
317
|
}
|
|
367
318
|
await this.setDevice(this.currentDevices.audio);
|
|
@@ -370,7 +321,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
370
321
|
});
|
|
371
322
|
}
|
|
372
323
|
async getOperationalWebcamDeviceId() {
|
|
373
|
-
let videoDevices = await
|
|
324
|
+
let videoDevices = await this.#localMediaUtils.getVideoDevices();
|
|
374
325
|
if (!videoDevices.length) {
|
|
375
326
|
return {
|
|
376
327
|
isOperational: false,
|
|
@@ -401,7 +352,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
401
352
|
};
|
|
402
353
|
}
|
|
403
354
|
async getOperationalMicDeviceId() {
|
|
404
|
-
let audioDevices = await
|
|
355
|
+
let audioDevices = await this.#localMediaUtils.getAudioDevices();
|
|
405
356
|
if (!audioDevices.length) {
|
|
406
357
|
return {
|
|
407
358
|
isOperational: false,
|
|
@@ -467,18 +418,18 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
467
418
|
};
|
|
468
419
|
}
|
|
469
420
|
if (audio) {
|
|
470
|
-
const audioDevices = await
|
|
421
|
+
const audioDevices = await this.#localMediaUtils.getAudioDevices();
|
|
471
422
|
if (audioDevices.length !== 0) {
|
|
472
423
|
const audioDeviceId = (await this.getOperationalMicDeviceId()).deviceId;
|
|
473
|
-
this.currentDevices.audio =
|
|
424
|
+
this.currentDevices.audio = this.#localMediaUtils.getDeviceById(audioDeviceId, 'audioinput');
|
|
474
425
|
constraints.audio = true;
|
|
475
426
|
}
|
|
476
427
|
}
|
|
477
428
|
if (video) {
|
|
478
|
-
const videoDevices = await
|
|
429
|
+
const videoDevices = await this.#localMediaUtils.getVideoDevices();
|
|
479
430
|
if (videoDevices.length !== 0) {
|
|
480
431
|
const videoDeviceId = (await this.getOperationalWebcamDeviceId()).deviceId;
|
|
481
|
-
this.currentDevices.video =
|
|
432
|
+
this.currentDevices.video = this.#localMediaUtils.getDeviceById(videoDeviceId, 'videoinput');
|
|
482
433
|
const videoConstraints = _LocalMediaUtils.default.getVideoConstraints({
|
|
483
434
|
videoDeviceId
|
|
484
435
|
});
|
|
@@ -496,7 +447,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
496
447
|
|
|
497
448
|
// Setup Foreground Service after handling permissions
|
|
498
449
|
if (_reactNative.Platform.OS === 'android') {
|
|
499
|
-
|
|
450
|
+
this.#appStateSubscription = _reactNative.AppState.addEventListener('change', this._handleAppStateChange);
|
|
500
451
|
}
|
|
501
452
|
|
|
502
453
|
// Start the meeting foreground service so Android keeps the app alive
|
|
@@ -510,22 +461,19 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
510
461
|
video = true
|
|
511
462
|
} = tracks;
|
|
512
463
|
if (audio) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
(_this$screenShareTrac2 = this.screenShareTracks) === null || _this$screenShareTrac2 === void 0 || (_this$screenShareTrac2 = _this$screenShareTrac2.audio) === null || _this$screenShareTrac2 === void 0 || _this$screenShareTrac2.release();
|
|
464
|
+
this.screenShareTracks?.audio?.stop();
|
|
465
|
+
this.screenShareTracks?.audio?.release();
|
|
516
466
|
}
|
|
517
467
|
if (video) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
(_this$screenShareTrac4 = this.screenShareTracks) === null || _this$screenShareTrac4 === void 0 || (_this$screenShareTrac4 = _this$screenShareTrac4.video) === null || _this$screenShareTrac4 === void 0 || _this$screenShareTrac4.release();
|
|
468
|
+
this.screenShareTracks?.video?.stop();
|
|
469
|
+
this.screenShareTracks?.video?.release();
|
|
521
470
|
}
|
|
522
471
|
if (audio && video) {
|
|
523
472
|
this.screenShareEnabled = false;
|
|
524
473
|
}
|
|
525
474
|
}
|
|
526
475
|
removeScreenShareTracks(tracks) {
|
|
527
|
-
|
|
528
|
-
(_this$screenShareTrac5 = this.screenShareTracks.video) === null || _this$screenShareTrac5 === void 0 || _this$screenShareTrac5.removeEventListener('ended', this.onScreenShareEnded);
|
|
476
|
+
this.screenShareTracks.video?.removeEventListener('ended', this.onScreenShareEnded);
|
|
529
477
|
this.stopScreenShareTracks(tracks);
|
|
530
478
|
this.screenShareTracks = {
|
|
531
479
|
audio: undefined,
|
|
@@ -537,9 +485,8 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
537
485
|
return;
|
|
538
486
|
}
|
|
539
487
|
if (audioTrack === undefined) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
(_this$rawAudioTrack3 = this.rawAudioTrack) === null || _this$rawAudioTrack3 === void 0 || _this$rawAudioTrack3.release();
|
|
488
|
+
this.rawAudioTrack?.stop();
|
|
489
|
+
this.rawAudioTrack?.release();
|
|
543
490
|
this.rawAudioTrack = undefined;
|
|
544
491
|
}
|
|
545
492
|
this.audioTrack = audioTrack;
|
|
@@ -549,15 +496,13 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
549
496
|
return;
|
|
550
497
|
}
|
|
551
498
|
if (videoTrack === undefined) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
(_this$rawVideoTrack3 = this.rawVideoTrack) === null || _this$rawVideoTrack3 === void 0 || _this$rawVideoTrack3.release();
|
|
499
|
+
this.rawVideoTrack?.stop();
|
|
500
|
+
this.rawVideoTrack?.release();
|
|
555
501
|
this.rawVideoTrack = undefined;
|
|
556
502
|
}
|
|
557
503
|
this.videoTrack = videoTrack;
|
|
558
504
|
}
|
|
559
505
|
setScreenShareTracks(tracks) {
|
|
560
|
-
var _this$screenShareTrac6;
|
|
561
506
|
const {
|
|
562
507
|
audio,
|
|
563
508
|
video
|
|
@@ -569,8 +514,16 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
569
514
|
});
|
|
570
515
|
}
|
|
571
516
|
this.screenShareTracks = tracks;
|
|
572
|
-
|
|
517
|
+
this.screenShareTracks.video?.addEventListener('ended', this.onScreenShareEnded);
|
|
573
518
|
}
|
|
519
|
+
|
|
520
|
+
// Arrow function so `this` is stable — the same reference is used in both
|
|
521
|
+
// addEventListener (setScreenShareTracks) and removeEventListener
|
|
522
|
+
// (removeScreenShareTracks). A regular method + .bind(this) creates a new
|
|
523
|
+
// function object on every call, making removeEventListener a no-op.
|
|
524
|
+
onScreenShareEnded = () => {
|
|
525
|
+
this.emit('SCREENSHARE_ENDED');
|
|
526
|
+
};
|
|
574
527
|
async disableAudio() {
|
|
575
528
|
await this.toggleAudio();
|
|
576
529
|
}
|
|
@@ -603,12 +556,15 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
603
556
|
}
|
|
604
557
|
try {
|
|
605
558
|
/**
|
|
606
|
-
* NOTE
|
|
607
|
-
*
|
|
559
|
+
* NOTE: audioEnabled is set to true BEFORE setupAudioStream so that the
|
|
560
|
+
* AUDIO_TRACK_CHANGE event (emitted inside setupAudioStream) sees the
|
|
561
|
+
* correct enabled state and the Self.ts handler calls shareMic()
|
|
562
|
+
* immediately.
|
|
563
|
+
* If track acquisition fails, audioEnabled is rolled back to false below.
|
|
608
564
|
*/
|
|
565
|
+
this.audioEnabled = true;
|
|
609
566
|
if (!this.audioTrack || this.audioTrack.readyState === 'ended') {
|
|
610
|
-
|
|
611
|
-
await this.setupAudioStream((_this$currentDevices$6 = this.currentDevices.audio) === null || _this$currentDevices$6 === void 0 ? void 0 : _this$currentDevices$6.deviceId);
|
|
567
|
+
await this.setupAudioStream(this.currentDevices.audio?.deviceId);
|
|
612
568
|
}
|
|
613
569
|
// if we still can't get a track after setting up audio stream
|
|
614
570
|
// do not toggle the audio state
|
|
@@ -616,7 +572,6 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
616
572
|
this.audioEnabled = false;
|
|
617
573
|
return;
|
|
618
574
|
}
|
|
619
|
-
this.audioEnabled = true;
|
|
620
575
|
} catch (ex) {
|
|
621
576
|
this.audioEnabled = false;
|
|
622
577
|
this.audioTrack = undefined;
|
|
@@ -633,7 +588,6 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
633
588
|
await this.toggleVideo();
|
|
634
589
|
}
|
|
635
590
|
async toggleVideo() {
|
|
636
|
-
var _this$currentDevices$7;
|
|
637
591
|
if (this.permissions.video !== 'ACCEPTED') {
|
|
638
592
|
try {
|
|
639
593
|
const permResult = await (0, _PermissionHandler.setupPermissions)(false, true);
|
|
@@ -651,9 +605,8 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
651
605
|
return;
|
|
652
606
|
}
|
|
653
607
|
if (this.videoEnabled) {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
(_this$rawVideoTrack5 = this.rawVideoTrack) === null || _this$rawVideoTrack5 === void 0 || _this$rawVideoTrack5.release();
|
|
608
|
+
this.rawVideoTrack?.stop();
|
|
609
|
+
this.rawVideoTrack?.release();
|
|
657
610
|
this.rawVideoTrack = undefined;
|
|
658
611
|
this.videoEnabled = false;
|
|
659
612
|
return;
|
|
@@ -663,16 +616,15 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
663
616
|
* hence it must be set to true first.
|
|
664
617
|
*/
|
|
665
618
|
this.videoEnabled = true;
|
|
666
|
-
await this.setupVideoStream(
|
|
619
|
+
await this.setupVideoStream(this.currentDevices.video?.deviceId);
|
|
667
620
|
}
|
|
668
621
|
async setAudioDevice(device) {
|
|
669
622
|
await this.setupAudioStream(device.deviceId);
|
|
670
623
|
}
|
|
671
624
|
async setVideoDevice(device) {
|
|
672
625
|
if (this.videoEnabled) {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
(_this$rawVideoTrack7 = this.rawVideoTrack) === null || _this$rawVideoTrack7 === void 0 || _this$rawVideoTrack7.release();
|
|
626
|
+
this.rawVideoTrack?.stop();
|
|
627
|
+
this.rawVideoTrack?.release();
|
|
676
628
|
this.rawVideoTrack = undefined;
|
|
677
629
|
}
|
|
678
630
|
await this.setupVideoStream(device.deviceId);
|
|
@@ -681,15 +633,15 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
681
633
|
await this.setupSpeaker(device.deviceId);
|
|
682
634
|
}
|
|
683
635
|
async setDevice(route) {
|
|
684
|
-
await
|
|
636
|
+
await this.#localMediaUtils.chooseAudioRoute(route.deviceId);
|
|
685
637
|
}
|
|
686
638
|
async oniOSBroadcastStart() {
|
|
687
639
|
this.setScreenShareTracks(await _LocalMediaUtils.default.getScreenShareTracks());
|
|
688
640
|
this.screenShareEnabled = true;
|
|
689
|
-
|
|
641
|
+
this.#screenShareState = 'STARTED';
|
|
690
642
|
}
|
|
691
643
|
async oniOSBroadcastStop() {
|
|
692
|
-
|
|
644
|
+
this.#screenShareState = 'STOPPED';
|
|
693
645
|
if (this.screenShareEnabled) {
|
|
694
646
|
this.removeScreenShareTracks();
|
|
695
647
|
return;
|
|
@@ -713,13 +665,13 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
713
665
|
}
|
|
714
666
|
}
|
|
715
667
|
if (_reactNative.Platform.OS === 'ios') {
|
|
716
|
-
|
|
668
|
+
this.#screenShareState = 'PENDING';
|
|
717
669
|
_reactNative.NativeModules.RTKScreensharePickerView.showScreenSharePickerView();
|
|
718
670
|
await new Promise((resolve, reject) => {
|
|
719
671
|
let timeoutId;
|
|
720
672
|
let time = 0;
|
|
721
673
|
timeoutId = setInterval(() => {
|
|
722
|
-
if (
|
|
674
|
+
if (this.#screenShareState === 'STARTED') {
|
|
723
675
|
clearInterval(timeoutId);
|
|
724
676
|
resolve();
|
|
725
677
|
}
|
|
@@ -742,12 +694,12 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
742
694
|
|
|
743
695
|
// iOS: trigger the broadcast picker to stop the extension.
|
|
744
696
|
_reactNative.NativeModules.RTKScreensharePickerView.showScreenSharePickerView();
|
|
745
|
-
|
|
697
|
+
this.#screenShareState = 'PENDING';
|
|
746
698
|
await new Promise((resolve, reject) => {
|
|
747
699
|
let timeoutId;
|
|
748
700
|
let time = 0;
|
|
749
701
|
timeoutId = setInterval(() => {
|
|
750
|
-
if (
|
|
702
|
+
if (this.#screenShareState === 'STOPPED') {
|
|
751
703
|
clearInterval(timeoutId);
|
|
752
704
|
resolve();
|
|
753
705
|
}
|
|
@@ -760,22 +712,22 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
760
712
|
});
|
|
761
713
|
}
|
|
762
714
|
getAllDevices() {
|
|
763
|
-
return
|
|
715
|
+
return this.#localMediaUtils.availableDevices;
|
|
764
716
|
}
|
|
765
717
|
getCurrentDevices() {
|
|
766
718
|
return this.currentDevices;
|
|
767
719
|
}
|
|
768
720
|
getDeviceById(deviceId, kind) {
|
|
769
|
-
return
|
|
721
|
+
return this.#localMediaUtils.getDeviceById(deviceId, kind);
|
|
770
722
|
}
|
|
771
723
|
async getAudioDevices() {
|
|
772
|
-
const devices = await
|
|
724
|
+
const devices = await this.#localMediaUtils.getAudioDevices();
|
|
773
725
|
|
|
774
726
|
// Update current audio device from native layer
|
|
775
727
|
try {
|
|
776
728
|
const currentDeviceId = await _NativeAudioManager.default.getCurrentAudioDevice();
|
|
777
729
|
if (currentDeviceId) {
|
|
778
|
-
const currentDevice =
|
|
730
|
+
const currentDevice = this.#localMediaUtils.getDeviceById(currentDeviceId, 'audioinput');
|
|
779
731
|
if (currentDevice) {
|
|
780
732
|
this.currentDevices.audio = currentDevice;
|
|
781
733
|
}
|
|
@@ -786,16 +738,16 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
786
738
|
return devices;
|
|
787
739
|
}
|
|
788
740
|
async getVideoDevices() {
|
|
789
|
-
return await
|
|
741
|
+
return await this.#localMediaUtils.getVideoDevices();
|
|
790
742
|
}
|
|
791
743
|
async getSpeakerDevices() {
|
|
792
|
-
const devices = await
|
|
744
|
+
const devices = await this.#localMediaUtils.getSpeakerDevices();
|
|
793
745
|
|
|
794
746
|
// Update current speaker device from native layer
|
|
795
747
|
try {
|
|
796
748
|
const currentDeviceId = await _NativeAudioManager.default.getCurrentAudioDevice();
|
|
797
749
|
if (currentDeviceId) {
|
|
798
|
-
const currentDevice =
|
|
750
|
+
const currentDevice = this.#localMediaUtils.getDeviceById(currentDeviceId, 'audioinput');
|
|
799
751
|
if (currentDevice) {
|
|
800
752
|
this.currentDevices.speaker = currentDevice;
|
|
801
753
|
this.currentDevices.audio = currentDevice;
|
|
@@ -814,7 +766,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
814
766
|
|
|
815
767
|
// Update currentDevices.speaker when platform reports selected device change
|
|
816
768
|
if (changedDevices.selectedDevice) {
|
|
817
|
-
const selectedDeviceInfo =
|
|
769
|
+
const selectedDeviceInfo = this.#localMediaUtils.getDeviceById(changedDevices.selectedDevice, 'audioinput');
|
|
818
770
|
if (selectedDeviceInfo) {
|
|
819
771
|
this.currentDevices.speaker = selectedDeviceInfo;
|
|
820
772
|
this.currentDevices.audio = selectedDeviceInfo;
|
|
@@ -828,9 +780,9 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
828
780
|
*/
|
|
829
781
|
if (addedDevice) {
|
|
830
782
|
// Clear any pending device removal timeout when a device is added
|
|
831
|
-
if (
|
|
832
|
-
clearTimeout(
|
|
833
|
-
|
|
783
|
+
if (this.#deviceRemovalTimeout) {
|
|
784
|
+
clearTimeout(this.#deviceRemovalTimeout);
|
|
785
|
+
this.#deviceRemovalTimeout = null;
|
|
834
786
|
}
|
|
835
787
|
if (addedDevice.kind === 'audioinput') {
|
|
836
788
|
if (this.permissions.audio === 'DENIED' || this.permissions.audio === 'NOT_REQUESTED') {
|
|
@@ -868,7 +820,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
868
820
|
};
|
|
869
821
|
if (isBluetoothRemoved) {
|
|
870
822
|
// Wait 500ms before switching away from Bluetooth to allow for reconnection
|
|
871
|
-
|
|
823
|
+
this.#deviceRemovalTimeout = setTimeout(handleRemoval, 500);
|
|
872
824
|
} else {
|
|
873
825
|
// For other devices, handle removal immediately
|
|
874
826
|
await handleRemoval();
|
|
@@ -930,28 +882,25 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
930
882
|
return super.on(event, listener);
|
|
931
883
|
}
|
|
932
884
|
destruct() {
|
|
933
|
-
var _classPrivateFieldGet2;
|
|
934
885
|
this.stopAudioTrack();
|
|
935
886
|
this.stopVideoTrack();
|
|
936
887
|
this.stopScreenShareTracks();
|
|
937
|
-
if (_reactNative.Platform.OS === 'android')
|
|
888
|
+
if (_reactNative.Platform.OS === 'android') this.#appStateSubscription?.remove();
|
|
938
889
|
}
|
|
939
890
|
stopAudioTrack() {
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
(_this$audioTrack4 = this.audioTrack) === null || _this$audioTrack4 === void 0 || _this$audioTrack4.release();
|
|
891
|
+
this.rawAudioTrack?.stop();
|
|
892
|
+
this.audioTrack?.stop();
|
|
893
|
+
this.rawAudioTrack?.release();
|
|
894
|
+
this.audioTrack?.release();
|
|
945
895
|
this.audioEnabled = false;
|
|
946
896
|
this.audioTrack = undefined;
|
|
947
897
|
this.rawAudioTrack = undefined;
|
|
948
898
|
}
|
|
949
899
|
stopVideoTrack() {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
(_this$videoTrack4 = this.videoTrack) === null || _this$videoTrack4 === void 0 || _this$videoTrack4.release();
|
|
900
|
+
this.rawVideoTrack?.stop();
|
|
901
|
+
this.videoTrack?.stop();
|
|
902
|
+
this.rawVideoTrack?.release();
|
|
903
|
+
this.videoTrack?.release();
|
|
955
904
|
this.videoTrack = undefined;
|
|
956
905
|
this.rawVideoTrack = undefined;
|
|
957
906
|
}
|