@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.
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 +135 -186
  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 +135 -186
  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
  }
@@ -603,12 +556,15 @@ class LocalMediaHandler extends _events.EventEmitter {
603
556
  }
604
557
  try {
605
558
  /**
606
- * NOTE (@madhugb): We need to setup new stream,
607
- * if the audio track is not preset or it has ended
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
- var _this$currentDevices$6;
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
- var _this$rawVideoTrack4, _this$rawVideoTrack5;
655
- (_this$rawVideoTrack4 = this.rawVideoTrack) === null || _this$rawVideoTrack4 === void 0 || _this$rawVideoTrack4.stop();
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((_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);
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
- var _this$rawVideoTrack6, _this$rawVideoTrack7;
674
- (_this$rawVideoTrack6 = this.rawVideoTrack) === null || _this$rawVideoTrack6 === void 0 || _this$rawVideoTrack6.stop();
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 _classPrivateFieldGet(_localMediaUtils, this).chooseAudioRoute(route.deviceId);
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
- _classPrivateFieldSet(_screenShareState, this, 'STARTED');
641
+ this.#screenShareState = 'STARTED';
690
642
  }
691
643
  async oniOSBroadcastStop() {
692
- _classPrivateFieldSet(_screenShareState, this, 'STOPPED');
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
- _classPrivateFieldSet(_screenShareState, this, 'PENDING');
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 (_classPrivateFieldGet(_screenShareState, this) === 'STARTED') {
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
- _classPrivateFieldSet(_screenShareState, this, 'PENDING');
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 (_classPrivateFieldGet(_screenShareState, this) === 'STOPPED') {
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 _classPrivateFieldGet(_localMediaUtils, this).availableDevices;
715
+ return this.#localMediaUtils.availableDevices;
764
716
  }
765
717
  getCurrentDevices() {
766
718
  return this.currentDevices;
767
719
  }
768
720
  getDeviceById(deviceId, kind) {
769
- return _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(deviceId, kind);
721
+ return this.#localMediaUtils.getDeviceById(deviceId, kind);
770
722
  }
771
723
  async getAudioDevices() {
772
- const devices = await _classPrivateFieldGet(_localMediaUtils, this).getAudioDevices();
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(currentDeviceId, 'audioinput');
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 _classPrivateFieldGet(_localMediaUtils, this).getVideoDevices();
741
+ return await this.#localMediaUtils.getVideoDevices();
790
742
  }
791
743
  async getSpeakerDevices() {
792
- const devices = await _classPrivateFieldGet(_localMediaUtils, this).getSpeakerDevices();
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(currentDeviceId, 'audioinput');
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 = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(changedDevices.selectedDevice, 'audioinput');
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 (_classPrivateFieldGet(_deviceRemovalTimeout, this)) {
832
- clearTimeout(_classPrivateFieldGet(_deviceRemovalTimeout, this));
833
- _classPrivateFieldSet(_deviceRemovalTimeout, this, null);
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
- _classPrivateFieldSet(_deviceRemovalTimeout, this, setTimeout(handleRemoval, 500));
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') (_classPrivateFieldGet2 = _classPrivateFieldGet(_appStateSubscription, this)) === null || _classPrivateFieldGet2 === void 0 || _classPrivateFieldGet2.remove();
888
+ if (_reactNative.Platform.OS === 'android') this.#appStateSubscription?.remove();
938
889
  }
939
890
  stopAudioTrack() {
940
- var _this$rawAudioTrack4, _this$audioTrack3, _this$rawAudioTrack5, _this$audioTrack4;
941
- (_this$rawAudioTrack4 = this.rawAudioTrack) === null || _this$rawAudioTrack4 === void 0 || _this$rawAudioTrack4.stop();
942
- (_this$audioTrack3 = this.audioTrack) === null || _this$audioTrack3 === void 0 || _this$audioTrack3.stop();
943
- (_this$rawAudioTrack5 = this.rawAudioTrack) === null || _this$rawAudioTrack5 === void 0 || _this$rawAudioTrack5.release();
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
- var _this$rawVideoTrack8, _this$videoTrack3, _this$rawVideoTrack9, _this$videoTrack4;
951
- (_this$rawVideoTrack8 = this.rawVideoTrack) === null || _this$rawVideoTrack8 === void 0 || _this$rawVideoTrack8.stop();
952
- (_this$videoTrack3 = this.videoTrack) === null || _this$videoTrack3 === void 0 || _this$videoTrack3.stop();
953
- (_this$rawVideoTrack9 = this.rawVideoTrack) === null || _this$rawVideoTrack9 === void 0 || _this$rawVideoTrack9.release();
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
  }