@cloudflare/realtimekit-react-native 1.2.0-staging.4 → 2.0.0-staging.6
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 +129 -183
- 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 +129 -183
- 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
|
}
|
|
@@ -611,8 +564,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
611
564
|
*/
|
|
612
565
|
this.audioEnabled = true;
|
|
613
566
|
if (!this.audioTrack || this.audioTrack.readyState === 'ended') {
|
|
614
|
-
|
|
615
|
-
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);
|
|
616
568
|
}
|
|
617
569
|
// if we still can't get a track after setting up audio stream
|
|
618
570
|
// do not toggle the audio state
|
|
@@ -636,7 +588,6 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
636
588
|
await this.toggleVideo();
|
|
637
589
|
}
|
|
638
590
|
async toggleVideo() {
|
|
639
|
-
var _this$currentDevices$7;
|
|
640
591
|
if (this.permissions.video !== 'ACCEPTED') {
|
|
641
592
|
try {
|
|
642
593
|
const permResult = await (0, _PermissionHandler.setupPermissions)(false, true);
|
|
@@ -654,9 +605,8 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
654
605
|
return;
|
|
655
606
|
}
|
|
656
607
|
if (this.videoEnabled) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
(_this$rawVideoTrack5 = this.rawVideoTrack) === null || _this$rawVideoTrack5 === void 0 || _this$rawVideoTrack5.release();
|
|
608
|
+
this.rawVideoTrack?.stop();
|
|
609
|
+
this.rawVideoTrack?.release();
|
|
660
610
|
this.rawVideoTrack = undefined;
|
|
661
611
|
this.videoEnabled = false;
|
|
662
612
|
return;
|
|
@@ -666,16 +616,15 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
666
616
|
* hence it must be set to true first.
|
|
667
617
|
*/
|
|
668
618
|
this.videoEnabled = true;
|
|
669
|
-
await this.setupVideoStream(
|
|
619
|
+
await this.setupVideoStream(this.currentDevices.video?.deviceId);
|
|
670
620
|
}
|
|
671
621
|
async setAudioDevice(device) {
|
|
672
622
|
await this.setupAudioStream(device.deviceId);
|
|
673
623
|
}
|
|
674
624
|
async setVideoDevice(device) {
|
|
675
625
|
if (this.videoEnabled) {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
(_this$rawVideoTrack7 = this.rawVideoTrack) === null || _this$rawVideoTrack7 === void 0 || _this$rawVideoTrack7.release();
|
|
626
|
+
this.rawVideoTrack?.stop();
|
|
627
|
+
this.rawVideoTrack?.release();
|
|
679
628
|
this.rawVideoTrack = undefined;
|
|
680
629
|
}
|
|
681
630
|
await this.setupVideoStream(device.deviceId);
|
|
@@ -684,15 +633,15 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
684
633
|
await this.setupSpeaker(device.deviceId);
|
|
685
634
|
}
|
|
686
635
|
async setDevice(route) {
|
|
687
|
-
await
|
|
636
|
+
await this.#localMediaUtils.chooseAudioRoute(route.deviceId);
|
|
688
637
|
}
|
|
689
638
|
async oniOSBroadcastStart() {
|
|
690
639
|
this.setScreenShareTracks(await _LocalMediaUtils.default.getScreenShareTracks());
|
|
691
640
|
this.screenShareEnabled = true;
|
|
692
|
-
|
|
641
|
+
this.#screenShareState = 'STARTED';
|
|
693
642
|
}
|
|
694
643
|
async oniOSBroadcastStop() {
|
|
695
|
-
|
|
644
|
+
this.#screenShareState = 'STOPPED';
|
|
696
645
|
if (this.screenShareEnabled) {
|
|
697
646
|
this.removeScreenShareTracks();
|
|
698
647
|
return;
|
|
@@ -716,13 +665,13 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
716
665
|
}
|
|
717
666
|
}
|
|
718
667
|
if (_reactNative.Platform.OS === 'ios') {
|
|
719
|
-
|
|
668
|
+
this.#screenShareState = 'PENDING';
|
|
720
669
|
_reactNative.NativeModules.RTKScreensharePickerView.showScreenSharePickerView();
|
|
721
670
|
await new Promise((resolve, reject) => {
|
|
722
671
|
let timeoutId;
|
|
723
672
|
let time = 0;
|
|
724
673
|
timeoutId = setInterval(() => {
|
|
725
|
-
if (
|
|
674
|
+
if (this.#screenShareState === 'STARTED') {
|
|
726
675
|
clearInterval(timeoutId);
|
|
727
676
|
resolve();
|
|
728
677
|
}
|
|
@@ -745,12 +694,12 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
745
694
|
|
|
746
695
|
// iOS: trigger the broadcast picker to stop the extension.
|
|
747
696
|
_reactNative.NativeModules.RTKScreensharePickerView.showScreenSharePickerView();
|
|
748
|
-
|
|
697
|
+
this.#screenShareState = 'PENDING';
|
|
749
698
|
await new Promise((resolve, reject) => {
|
|
750
699
|
let timeoutId;
|
|
751
700
|
let time = 0;
|
|
752
701
|
timeoutId = setInterval(() => {
|
|
753
|
-
if (
|
|
702
|
+
if (this.#screenShareState === 'STOPPED') {
|
|
754
703
|
clearInterval(timeoutId);
|
|
755
704
|
resolve();
|
|
756
705
|
}
|
|
@@ -763,22 +712,22 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
763
712
|
});
|
|
764
713
|
}
|
|
765
714
|
getAllDevices() {
|
|
766
|
-
return
|
|
715
|
+
return this.#localMediaUtils.availableDevices;
|
|
767
716
|
}
|
|
768
717
|
getCurrentDevices() {
|
|
769
718
|
return this.currentDevices;
|
|
770
719
|
}
|
|
771
720
|
getDeviceById(deviceId, kind) {
|
|
772
|
-
return
|
|
721
|
+
return this.#localMediaUtils.getDeviceById(deviceId, kind);
|
|
773
722
|
}
|
|
774
723
|
async getAudioDevices() {
|
|
775
|
-
const devices = await
|
|
724
|
+
const devices = await this.#localMediaUtils.getAudioDevices();
|
|
776
725
|
|
|
777
726
|
// Update current audio device from native layer
|
|
778
727
|
try {
|
|
779
728
|
const currentDeviceId = await _NativeAudioManager.default.getCurrentAudioDevice();
|
|
780
729
|
if (currentDeviceId) {
|
|
781
|
-
const currentDevice =
|
|
730
|
+
const currentDevice = this.#localMediaUtils.getDeviceById(currentDeviceId, 'audioinput');
|
|
782
731
|
if (currentDevice) {
|
|
783
732
|
this.currentDevices.audio = currentDevice;
|
|
784
733
|
}
|
|
@@ -789,16 +738,16 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
789
738
|
return devices;
|
|
790
739
|
}
|
|
791
740
|
async getVideoDevices() {
|
|
792
|
-
return await
|
|
741
|
+
return await this.#localMediaUtils.getVideoDevices();
|
|
793
742
|
}
|
|
794
743
|
async getSpeakerDevices() {
|
|
795
|
-
const devices = await
|
|
744
|
+
const devices = await this.#localMediaUtils.getSpeakerDevices();
|
|
796
745
|
|
|
797
746
|
// Update current speaker device from native layer
|
|
798
747
|
try {
|
|
799
748
|
const currentDeviceId = await _NativeAudioManager.default.getCurrentAudioDevice();
|
|
800
749
|
if (currentDeviceId) {
|
|
801
|
-
const currentDevice =
|
|
750
|
+
const currentDevice = this.#localMediaUtils.getDeviceById(currentDeviceId, 'audioinput');
|
|
802
751
|
if (currentDevice) {
|
|
803
752
|
this.currentDevices.speaker = currentDevice;
|
|
804
753
|
this.currentDevices.audio = currentDevice;
|
|
@@ -817,7 +766,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
817
766
|
|
|
818
767
|
// Update currentDevices.speaker when platform reports selected device change
|
|
819
768
|
if (changedDevices.selectedDevice) {
|
|
820
|
-
const selectedDeviceInfo =
|
|
769
|
+
const selectedDeviceInfo = this.#localMediaUtils.getDeviceById(changedDevices.selectedDevice, 'audioinput');
|
|
821
770
|
if (selectedDeviceInfo) {
|
|
822
771
|
this.currentDevices.speaker = selectedDeviceInfo;
|
|
823
772
|
this.currentDevices.audio = selectedDeviceInfo;
|
|
@@ -831,9 +780,9 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
831
780
|
*/
|
|
832
781
|
if (addedDevice) {
|
|
833
782
|
// Clear any pending device removal timeout when a device is added
|
|
834
|
-
if (
|
|
835
|
-
clearTimeout(
|
|
836
|
-
|
|
783
|
+
if (this.#deviceRemovalTimeout) {
|
|
784
|
+
clearTimeout(this.#deviceRemovalTimeout);
|
|
785
|
+
this.#deviceRemovalTimeout = null;
|
|
837
786
|
}
|
|
838
787
|
if (addedDevice.kind === 'audioinput') {
|
|
839
788
|
if (this.permissions.audio === 'DENIED' || this.permissions.audio === 'NOT_REQUESTED') {
|
|
@@ -871,7 +820,7 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
871
820
|
};
|
|
872
821
|
if (isBluetoothRemoved) {
|
|
873
822
|
// Wait 500ms before switching away from Bluetooth to allow for reconnection
|
|
874
|
-
|
|
823
|
+
this.#deviceRemovalTimeout = setTimeout(handleRemoval, 500);
|
|
875
824
|
} else {
|
|
876
825
|
// For other devices, handle removal immediately
|
|
877
826
|
await handleRemoval();
|
|
@@ -933,28 +882,25 @@ class LocalMediaHandler extends _events.EventEmitter {
|
|
|
933
882
|
return super.on(event, listener);
|
|
934
883
|
}
|
|
935
884
|
destruct() {
|
|
936
|
-
var _classPrivateFieldGet2;
|
|
937
885
|
this.stopAudioTrack();
|
|
938
886
|
this.stopVideoTrack();
|
|
939
887
|
this.stopScreenShareTracks();
|
|
940
|
-
if (_reactNative.Platform.OS === 'android')
|
|
888
|
+
if (_reactNative.Platform.OS === 'android') this.#appStateSubscription?.remove();
|
|
941
889
|
}
|
|
942
890
|
stopAudioTrack() {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
(_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();
|
|
948
895
|
this.audioEnabled = false;
|
|
949
896
|
this.audioTrack = undefined;
|
|
950
897
|
this.rawAudioTrack = undefined;
|
|
951
898
|
}
|
|
952
899
|
stopVideoTrack() {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
(_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();
|
|
958
904
|
this.videoTrack = undefined;
|
|
959
905
|
this.rawVideoTrack = undefined;
|
|
960
906
|
}
|