@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.
Files changed (84) hide show
  1. package/RealtimeKitCore.podspec +1 -1
  2. package/ios/scripts/screenshare_sources.rb +74 -0
  3. package/lib/commonjs/AudioSampleHandler.js +1 -7
  4. package/lib/commonjs/AudioSampleHandler.js.map +1 -1
  5. package/lib/commonjs/BackgroundHandler.js +0 -7
  6. package/lib/commonjs/BackgroundHandler.js.map +1 -1
  7. package/lib/commonjs/DeviceInfo.js +0 -4
  8. package/lib/commonjs/DeviceInfo.js.map +1 -1
  9. package/lib/commonjs/LocalMediaError.js +0 -4
  10. package/lib/commonjs/LocalMediaError.js.map +1 -1
  11. package/lib/commonjs/LocalMediaHandler.js +129 -183
  12. package/lib/commonjs/LocalMediaHandler.js.map +1 -1
  13. package/lib/commonjs/LocalMediaInterfaces.js.map +1 -1
  14. package/lib/commonjs/LocalMediaUtils.js +19 -27
  15. package/lib/commonjs/LocalMediaUtils.js.map +1 -1
  16. package/lib/commonjs/NativeAudioManager.js +3 -3
  17. package/lib/commonjs/NativeAudioManager.js.map +1 -1
  18. package/lib/commonjs/PermissionHandler.js.map +1 -1
  19. package/lib/commonjs/ReactContext.js +39 -43
  20. package/lib/commonjs/ReactContext.js.map +1 -1
  21. package/lib/commonjs/ReactHooks.js +7 -9
  22. package/lib/commonjs/ReactHooks.js.map +1 -1
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/package.json +1 -0
  25. package/lib/commonjs/utils/crypto.js.map +1 -1
  26. package/lib/commonjs/utils/version.js +1 -1
  27. package/lib/commonjs/utils/version.js.map +1 -1
  28. package/lib/module/AudioSampleHandler.js +3 -7
  29. package/lib/module/AudioSampleHandler.js.map +1 -1
  30. package/lib/module/BackgroundHandler.js +2 -7
  31. package/lib/module/BackgroundHandler.js.map +1 -1
  32. package/lib/module/DeviceInfo.js +2 -4
  33. package/lib/module/DeviceInfo.js.map +1 -1
  34. package/lib/module/LocalMediaError.js +2 -4
  35. package/lib/module/LocalMediaError.js.map +1 -1
  36. package/lib/module/LocalMediaHandler.js +129 -183
  37. package/lib/module/LocalMediaHandler.js.map +1 -1
  38. package/lib/module/LocalMediaInterfaces.js +1 -1
  39. package/lib/module/LocalMediaInterfaces.js.map +1 -1
  40. package/lib/module/LocalMediaUtils.js +21 -27
  41. package/lib/module/LocalMediaUtils.js.map +1 -1
  42. package/lib/module/NativeAudioManager.js +5 -3
  43. package/lib/module/NativeAudioManager.js.map +1 -1
  44. package/lib/module/PermissionHandler.js +2 -0
  45. package/lib/module/PermissionHandler.js.map +1 -1
  46. package/lib/module/ReactContext.js +39 -43
  47. package/lib/module/ReactContext.js.map +1 -1
  48. package/lib/module/ReactHooks.js +9 -9
  49. package/lib/module/ReactHooks.js.map +1 -1
  50. package/lib/module/index.js +2 -0
  51. package/lib/module/index.js.map +1 -1
  52. package/lib/module/utils/crypto.js +2 -0
  53. package/lib/module/utils/crypto.js.map +1 -1
  54. package/lib/module/utils/version.js +3 -1
  55. package/lib/module/utils/version.js.map +1 -1
  56. package/lib/typescript/AudioSampleHandler.d.ts +1 -0
  57. package/lib/typescript/AudioSampleHandler.d.ts.map +1 -0
  58. package/lib/typescript/BackgroundHandler.d.ts +1 -0
  59. package/lib/typescript/BackgroundHandler.d.ts.map +1 -0
  60. package/lib/typescript/DeviceInfo.d.ts +1 -0
  61. package/lib/typescript/DeviceInfo.d.ts.map +1 -0
  62. package/lib/typescript/LocalMediaError.d.ts +1 -0
  63. package/lib/typescript/LocalMediaError.d.ts.map +1 -0
  64. package/lib/typescript/LocalMediaHandler.d.ts +1 -0
  65. package/lib/typescript/LocalMediaHandler.d.ts.map +1 -0
  66. package/lib/typescript/LocalMediaInterfaces.d.ts +1 -0
  67. package/lib/typescript/LocalMediaInterfaces.d.ts.map +1 -0
  68. package/lib/typescript/LocalMediaUtils.d.ts +1 -0
  69. package/lib/typescript/LocalMediaUtils.d.ts.map +1 -0
  70. package/lib/typescript/NativeAudioManager.d.ts +1 -0
  71. package/lib/typescript/NativeAudioManager.d.ts.map +1 -0
  72. package/lib/typescript/PermissionHandler.d.ts +1 -0
  73. package/lib/typescript/PermissionHandler.d.ts.map +1 -0
  74. package/lib/typescript/ReactContext.d.ts +1 -0
  75. package/lib/typescript/ReactContext.d.ts.map +1 -0
  76. package/lib/typescript/ReactHooks.d.ts +1 -0
  77. package/lib/typescript/ReactHooks.d.ts.map +1 -0
  78. package/lib/typescript/index.d.ts +1 -0
  79. package/lib/typescript/index.d.ts.map +1 -0
  80. package/lib/typescript/utils/crypto.d.ts +1 -0
  81. package/lib/typescript/utils/crypto.d.ts.map +1 -0
  82. package/lib/typescript/utils/version.d.ts +2 -1
  83. package/lib/typescript/utils/version.d.ts.map +1 -0
  84. 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
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
15
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
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
- _classPrivateFieldInitSpec(this, _localMediaUtils, void 0);
70
- _classPrivateFieldInitSpec(this, _appState, void 0);
71
- _classPrivateFieldInitSpec(this, _appStateSubscription, void 0);
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
- _classPrivateFieldGet(_localMediaUtils, this).onDeviceChange(async changedDevices => {
110
+ this.#localMediaUtils.onDeviceChange(async changedDevices => {
145
111
  await this.onDeviceChange(changedDevices, false);
146
112
  });
147
113
  if (_reactNative.Platform.OS === 'ios') {
148
- _classPrivateFieldSet(_broadcastStartedSubscription, this, _classPrivateFieldGet(_broadcastEmitter, this).addListener('iOS_BroadcastStarted', () => {
114
+ this.#broadcastStartedSubscription = this.#broadcastEmitter.addListener('iOS_BroadcastStarted', () => {
149
115
  this.oniOSBroadcastStart();
150
- }));
151
- _classPrivateFieldSet(_broadcastStoppedSubscription, this, _classPrivateFieldGet(_broadcastEmitter, this).addListener('iOS_BroadcastStopped', () => {
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
- var _this$audioTrack;
165
- return (_this$audioTrack = this.audioTrack) === null || _this$audioTrack === void 0 ? void 0 : _this$audioTrack.addEventListener('unmute', e => {
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((_this$currentDevices$ = this.currentDevices.audio) === null || _this$currentDevices$ === void 0 ? void 0 : _this$currentDevices$.deviceId);
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
- var _this$currentDevices$2;
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 (((_this$currentDevices$2 = this.currentDevices.audio) === null || _this$currentDevices$2 === void 0 ? void 0 : _this$currentDevices$2.deviceId) !== audioDeviceId) {
249
- this.currentDevices.audio = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(audioDeviceId, 'audioinput');
206
+ if (this.currentDevices.audio?.deviceId !== audioDeviceId) {
207
+ this.currentDevices.audio = this.#localMediaUtils.getDeviceById(audioDeviceId, 'audioinput');
250
208
  }
251
209
  if (forceStopTrack) {
252
- var _this$audioTrack2, _this$rawAudioTrack;
253
- (_this$audioTrack2 = this.audioTrack) === null || _this$audioTrack2 === void 0 || _this$audioTrack2.stop();
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 _classPrivateFieldGet(_localMediaUtils, this).repopulateAvailableDevices();
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
- var _this$currentDevices$3;
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 (((_this$currentDevices$3 = this.currentDevices.video) === null || _this$currentDevices$3 === void 0 ? void 0 : _this$currentDevices$3.deviceId) !== videoDeviceId) {
296
- this.currentDevices.video = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(videoDeviceId, 'videoinput');
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
- var _this$videoTrack2, _this$rawVideoTrack;
321
- (_this$videoTrack2 = this.videoTrack) === null || _this$videoTrack2 === void 0 || _this$videoTrack2.stop();
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 _classPrivateFieldGet(_localMediaUtils, this).repopulateAvailableDevices();
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
- var _this$currentDevices$5;
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 = (bluetoothDevice === null || bluetoothDevice === void 0 ? void 0 : bluetoothDevice.deviceId) ?? (wiredDevice === null || wiredDevice === void 0 ? void 0 : wiredDevice.deviceId) ?? (speakerDevice === null || speakerDevice === void 0 ? void 0 : speakerDevice.deviceId) ?? speakerDevices[0].deviceId;
310
+ speakerDeviceId = bluetoothDevice?.deviceId ?? wiredDevice?.deviceId ?? speakerDevice?.deviceId ?? speakerDevices[0].deviceId;
360
311
  }
361
312
  }
362
- if (((_this$currentDevices$5 = this.currentDevices.speaker) === null || _this$currentDevices$5 === void 0 ? void 0 : _this$currentDevices$5.deviceId) !== speakerDeviceId) {
313
+ if (this.currentDevices.speaker?.deviceId !== speakerDeviceId) {
363
314
  // Audio Input devices are same as output devices in mobile
364
- this.currentDevices.audio = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(speakerDeviceId, 'audioinput');
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 _classPrivateFieldGet(_localMediaUtils, this).getVideoDevices();
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 _classPrivateFieldGet(_localMediaUtils, this).getAudioDevices();
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 _classPrivateFieldGet(_localMediaUtils, this).getAudioDevices();
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(audioDeviceId, 'audioinput');
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 _classPrivateFieldGet(_localMediaUtils, this).getVideoDevices();
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(videoDeviceId, 'videoinput');
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
- _classPrivateFieldSet(_appStateSubscription, this, _reactNative.AppState.addEventListener('change', this._handleAppStateChange));
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
- var _this$screenShareTrac, _this$screenShareTrac2;
514
- (_this$screenShareTrac = this.screenShareTracks) === null || _this$screenShareTrac === void 0 || (_this$screenShareTrac = _this$screenShareTrac.audio) === null || _this$screenShareTrac === void 0 || _this$screenShareTrac.stop();
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
- var _this$screenShareTrac3, _this$screenShareTrac4;
519
- (_this$screenShareTrac3 = this.screenShareTracks) === null || _this$screenShareTrac3 === void 0 || (_this$screenShareTrac3 = _this$screenShareTrac3.video) === null || _this$screenShareTrac3 === void 0 || _this$screenShareTrac3.stop();
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
- var _this$screenShareTrac5;
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
- var _this$rawAudioTrack2, _this$rawAudioTrack3;
541
- (_this$rawAudioTrack2 = this.rawAudioTrack) === null || _this$rawAudioTrack2 === void 0 || _this$rawAudioTrack2.stop();
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
- var _this$rawVideoTrack2, _this$rawVideoTrack3;
553
- (_this$rawVideoTrack2 = this.rawVideoTrack) === null || _this$rawVideoTrack2 === void 0 || _this$rawVideoTrack2.stop();
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
- (_this$screenShareTrac6 = this.screenShareTracks.video) === null || _this$screenShareTrac6 === void 0 || _this$screenShareTrac6.addEventListener('ended', this.onScreenShareEnded);
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
- var _this$currentDevices$6;
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
- var _this$rawVideoTrack4, _this$rawVideoTrack5;
658
- (_this$rawVideoTrack4 = this.rawVideoTrack) === null || _this$rawVideoTrack4 === void 0 || _this$rawVideoTrack4.stop();
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((_this$currentDevices$7 = this.currentDevices.video) === null || _this$currentDevices$7 === void 0 ? void 0 : _this$currentDevices$7.deviceId);
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
- var _this$rawVideoTrack6, _this$rawVideoTrack7;
677
- (_this$rawVideoTrack6 = this.rawVideoTrack) === null || _this$rawVideoTrack6 === void 0 || _this$rawVideoTrack6.stop();
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 _classPrivateFieldGet(_localMediaUtils, this).chooseAudioRoute(route.deviceId);
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
- _classPrivateFieldSet(_screenShareState, this, 'STARTED');
641
+ this.#screenShareState = 'STARTED';
693
642
  }
694
643
  async oniOSBroadcastStop() {
695
- _classPrivateFieldSet(_screenShareState, this, 'STOPPED');
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
- _classPrivateFieldSet(_screenShareState, this, 'PENDING');
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 (_classPrivateFieldGet(_screenShareState, this) === 'STARTED') {
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
- _classPrivateFieldSet(_screenShareState, this, 'PENDING');
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 (_classPrivateFieldGet(_screenShareState, this) === 'STOPPED') {
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 _classPrivateFieldGet(_localMediaUtils, this).availableDevices;
715
+ return this.#localMediaUtils.availableDevices;
767
716
  }
768
717
  getCurrentDevices() {
769
718
  return this.currentDevices;
770
719
  }
771
720
  getDeviceById(deviceId, kind) {
772
- return _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(deviceId, kind);
721
+ return this.#localMediaUtils.getDeviceById(deviceId, kind);
773
722
  }
774
723
  async getAudioDevices() {
775
- const devices = await _classPrivateFieldGet(_localMediaUtils, this).getAudioDevices();
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(currentDeviceId, 'audioinput');
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 _classPrivateFieldGet(_localMediaUtils, this).getVideoDevices();
741
+ return await this.#localMediaUtils.getVideoDevices();
793
742
  }
794
743
  async getSpeakerDevices() {
795
- const devices = await _classPrivateFieldGet(_localMediaUtils, this).getSpeakerDevices();
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(currentDeviceId, 'audioinput');
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(changedDevices.selectedDevice, 'audioinput');
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 (_classPrivateFieldGet(_deviceRemovalTimeout, this)) {
835
- clearTimeout(_classPrivateFieldGet(_deviceRemovalTimeout, this));
836
- _classPrivateFieldSet(_deviceRemovalTimeout, this, null);
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
- _classPrivateFieldSet(_deviceRemovalTimeout, this, setTimeout(handleRemoval, 500));
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') (_classPrivateFieldGet2 = _classPrivateFieldGet(_appStateSubscription, this)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.remove();
888
+ if (_reactNative.Platform.OS === 'android') this.#appStateSubscription?.remove();
941
889
  }
942
890
  stopAudioTrack() {
943
- var _this$rawAudioTrack4, _this$audioTrack3, _this$rawAudioTrack5, _this$audioTrack4;
944
- (_this$rawAudioTrack4 = this.rawAudioTrack) === null || _this$rawAudioTrack4 === void 0 || _this$rawAudioTrack4.stop();
945
- (_this$audioTrack3 = this.audioTrack) === null || _this$audioTrack3 === void 0 || _this$audioTrack3.stop();
946
- (_this$rawAudioTrack5 = this.rawAudioTrack) === null || _this$rawAudioTrack5 === void 0 || _this$rawAudioTrack5.release();
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
- var _this$rawVideoTrack8, _this$videoTrack3, _this$rawVideoTrack9, _this$videoTrack4;
954
- (_this$rawVideoTrack8 = this.rawVideoTrack) === null || _this$rawVideoTrack8 === void 0 || _this$rawVideoTrack8.stop();
955
- (_this$videoTrack3 = this.videoTrack) === null || _this$videoTrack3 === void 0 || _this$videoTrack3.stop();
956
- (_this$rawVideoTrack9 = this.rawVideoTrack) === null || _this$rawVideoTrack9 === void 0 || _this$rawVideoTrack9.release();
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
  }