@cloudflare/realtimekit-react-native 0.1.2-staging.7 → 0.1.2-staging.9

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.
@@ -549,6 +549,11 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
549
549
  {
550
550
  // NSLog(@"👉 Checking if Bluetooth device is connected");
551
551
  NSMutableArray *devices = [NSMutableArray array];
552
+ NSError *error = nil;
553
+ [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
554
+ withOptions:AVAudioSessionCategoryOptionAllowBluetooth
555
+ error:&error];
556
+ [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
552
557
  AVAudioSessionRouteDescription* route = [[AVAudioSession sharedInstance] currentRoute];
553
558
  for (AVAudioSessionPortDescription* desc in [route outputs]) {
554
559
  // NSLog(@"🧑‍💻 Bluetooth Desc: %@", desc);
@@ -558,6 +563,20 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
558
563
  [devices addObject:[desc portName]];
559
564
  }
560
565
  }
566
+
567
+ // If no Bluetooth device found in current route, check available outputs
568
+ if (devices.count == 0) {
569
+ NSArray<AVAudioSessionPortDescription *> *inputs = [route inputs];
570
+
571
+ // Check if Bluetooth is available in inputs (for headsets that function as both input and output)
572
+ for (AVAudioSessionPortDescription* desc in inputs) {
573
+ if ([[desc portType] isEqualToString:AVAudioSessionPortBluetoothHFP] ||
574
+ [[desc portType] isEqualToString:AVAudioSessionPortBluetoothLE]) {
575
+ [devices addObject:[desc portName]];
576
+ }
577
+ }
578
+ }
579
+
561
580
  // NSLog(@"🧑‍💻 Bluetooth Devices %@", devices);
562
581
  if (!devices || !devices.count){
563
582
  resolve(@NO);
@@ -1018,16 +1037,7 @@ RCT_EXPORT_METHOD(isBluetoothHeadsetConnected: (RCTPromiseResolveBlock) resolve
1018
1037
  // NSLog(@"🧑‍💻 RNInCallManager.AudioRouteChange.Reason: CategoryChange. category=%@ mode=%@", self->_audioSession.category, self->_audioSession.mode);
1019
1038
  break;
1020
1039
  case AVAudioSessionRouteChangeReasonOverride:
1021
- @try {
1022
- // NSLog(@"🧑‍💻 RNInCallManager.AudioRouteChange.Reason: Override");
1023
- [self sendEventWithName:@"onAudioDeviceChanged"
1024
- body:@{
1025
- @"availableAudioDeviceList": @"[speaker, earpiece]",
1026
- @"selectedAudioDevice": @"speaker",
1027
- }];
1028
- } @catch (NSException *exception) {
1029
- NSLog(@"Error sending event 'onAudioDeviceChanged' (Override): %@", exception.reason);
1030
- }
1040
+ // NSLog(@"🧑‍💻 RNInCallManager.AudioRouteChange.Reason: Override");
1031
1041
  break;
1032
1042
  case AVAudioSessionRouteChangeReasonWakeFromSleep:
1033
1043
  // NSLog(@"RNInCallManager.AudioRouteChange.Reason: WakeFromSleep");
@@ -39,8 +39,6 @@ export default class LocalMediaHandler extends EventEmitter {
39
39
  _handleAppStateChange: (nextAppState: any) => void;
40
40
  private configureForeground;
41
41
  constructor(localMediaUtils: LocalMediaUtils);
42
- destructor(): void;
43
- private handlePermissionErrors;
44
42
  private conditionallyRestartAudio;
45
43
  private conditionallyRestartVideo;
46
44
  private shouldReacquireTrack;
@@ -64,16 +62,11 @@ export default class LocalMediaHandler extends EventEmitter {
64
62
  audio: boolean;
65
63
  video: boolean;
66
64
  }): Promise<void>;
67
- private stopAudioTrack;
68
- private stopVideoTrack;
69
65
  private stopScreenShareTracks;
70
- removeAudioTrack(): void;
71
- removeVideoTrack(): void;
72
66
  removeScreenShareTracks(tracks?: {
73
67
  audio?: boolean;
74
68
  video?: boolean;
75
69
  }): void;
76
- removeAllTracks(): void;
77
70
  private setAudioTrack;
78
71
  private setVideoTrack;
79
72
  private setScreenShareTracks;
@@ -87,13 +80,12 @@ export default class LocalMediaHandler extends EventEmitter {
87
80
  setAudioDevice(device: MediaDeviceInfo): Promise<void>;
88
81
  setVideoDevice(device: MediaDeviceInfo): Promise<void>;
89
82
  setSpeakerDevice(device?: MediaDeviceInfo): Promise<void>;
90
- setDevice(route: MediaDeviceInfo): Promise<any>;
83
+ setDevice(route: MediaDeviceInfo): Promise<void>;
91
84
  private oniOSBroadcastStart;
92
85
  private oniOSBroadcastStop;
93
86
  toggleScreenShare(): Promise<void>;
94
87
  enableScreenShare(): Promise<void>;
95
88
  disableScreenShare(): Promise<void>;
96
- destruct(): void;
97
89
  getAllDevices(): MediaDeviceInfo[];
98
90
  getCurrentDevices(): {
99
91
  audio?: MediaDeviceInfo;
@@ -115,11 +107,18 @@ export default class LocalMediaHandler extends EventEmitter {
115
107
  added: MediaDeviceInfo[];
116
108
  removed: MediaDeviceInfo[];
117
109
  }, forceDeviceChange: boolean): Promise<void>;
118
- cleanUpTracks(): void;
119
- destructMediaHandler(): Promise<void>;
120
110
  static init(_: any): Promise<LocalMediaHandler>;
121
111
  emit(event: keyof typeof MediaEvents, ...args: any[]): boolean;
122
112
  on(event: keyof typeof MediaEvents, listener: (...args: any[]) => void): this;
113
+ destruct(): void;
114
+ destructMediaHandler(): Promise<void>;
115
+ cleanUpTracks(): void;
116
+ destructor(): void;
117
+ removeAllTracks(): void;
118
+ private stopAudioTrack;
119
+ removeAudioTrack(): void;
120
+ private stopVideoTrack;
121
+ removeVideoTrack(): void;
123
122
  removeAllListeners(event?: keyof typeof MediaEvents): this;
124
123
  }
125
124
  export interface RNLocalMediaHandler {
@@ -77,7 +77,6 @@ class LocalMediaHandler extends EventEmitter {
77
77
  _LocalMediaHandler_interval.set(this, void 0);
78
78
  this._pendingScreenShare = false;
79
79
  this._handleAppStateChange = (nextAppState) => {
80
- // console.log('App state changed to : ', nextAppState);
81
80
  if (__classPrivateFieldGet(this, _LocalMediaHandler_appState, "f").match(/inactive|background/) &&
82
81
  nextAppState === 'active') {
83
82
  BackgroundTimer.clearInterval(__classPrivateFieldGet(this, _LocalMediaHandler_interval, "f"));
@@ -130,15 +129,6 @@ class LocalMediaHandler extends EventEmitter {
130
129
  }
131
130
  InCallManger.start({});
132
131
  }
133
- destructor() {
134
- __classPrivateFieldGet(this, _LocalMediaHandler_appStateSubscription, "f").remove();
135
- broadcastEmitter.removeAllListeners('iOS_BroadcastStarted');
136
- broadcastEmitter.removeAllListeners('iOS_BroadcastStopped');
137
- BackgroundTimer.stop();
138
- }
139
- handlePermissionErrors(kind, err) {
140
- // pass
141
- }
142
132
  conditionallyRestartAudio() {
143
133
  return __awaiter(this, void 0, void 0, function* () {
144
134
  var _a;
@@ -267,9 +257,8 @@ class LocalMediaHandler extends EventEmitter {
267
257
  }
268
258
  this.setAudioTrack(this.rawAudioTrack);
269
259
  this.addMediaStreamTrackListeners(this.audioTrack);
260
+ this.emit('AUDIO_TRACK_CHANGE');
270
261
  this.setDevice(this.currentDevices.audio);
271
- // await InCallManger.chooseAudioRoute(audioDeviceId);
272
- // console.log('Device selected: ', audioDeviceId);
273
262
  /**
274
263
  * NOTE(roerohan): Firefox does not show device labels until permissions are granted.
275
264
  * So, we need to repopulate the devices once permission is granted.
@@ -280,10 +269,6 @@ class LocalMediaHandler extends EventEmitter {
280
269
  this.emit('DEVICE_CHANGE', {
281
270
  device: this.currentDevices.audio,
282
271
  });
283
- /*
284
- TODO
285
- callStats.mediaPermission('AUDIO', CallStatsPermissionEnum.ACCEPTED);
286
- callStats.selectedDevice('AUDIO', this.currentDevices.audio); */
287
272
  });
288
273
  }
289
274
  onVisibilityChange() {
@@ -322,6 +307,7 @@ class LocalMediaHandler extends EventEmitter {
322
307
  }
323
308
  this.setVideoTrack(this.rawVideoTrack);
324
309
  this.addMediaStreamTrackListeners(this.rawVideoTrack);
310
+ this.emit('VIDEO_TRACK_CHANGE');
325
311
  }
326
312
  if (forceStopTrack) {
327
313
  (_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
@@ -486,19 +472,6 @@ class LocalMediaHandler extends EventEmitter {
486
472
  }
487
473
  });
488
474
  }
489
- stopAudioTrack() {
490
- var _a, _b;
491
- (_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
492
- (_b = this.audioTrack) === null || _b === void 0 ? void 0 : _b.release();
493
- this.audioEnabled = false;
494
- }
495
- stopVideoTrack() {
496
- var _a, _b, _c, _d;
497
- (_a = this.rawVideoTrack) === null || _a === void 0 ? void 0 : _a.stop();
498
- (_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
499
- (_c = this.rawVideoTrack) === null || _c === void 0 ? void 0 : _c.release();
500
- (_d = this.videoTrack) === null || _d === void 0 ? void 0 : _d.release();
501
- }
502
475
  stopScreenShareTracks(tracks = {}) {
503
476
  var _a, _b, _c, _d;
504
477
  const { audio = true, video = true } = tracks;
@@ -512,16 +485,6 @@ class LocalMediaHandler extends EventEmitter {
512
485
  this.screenShareEnabled = false;
513
486
  }
514
487
  }
515
- removeAudioTrack() {
516
- this.stopAudioTrack();
517
- this.audioTrack = undefined;
518
- this.rawAudioTrack = undefined;
519
- }
520
- removeVideoTrack() {
521
- this.stopVideoTrack();
522
- this.videoTrack = undefined;
523
- this.rawVideoTrack = undefined;
524
- }
525
488
  removeScreenShareTracks(tracks) {
526
489
  var _a;
527
490
  (_a = this.screenShareTracks.video) === null || _a === void 0 ? void 0 : _a.removeEventListener('ended', this.onScreenShareEnded);
@@ -531,11 +494,6 @@ class LocalMediaHandler extends EventEmitter {
531
494
  video: undefined,
532
495
  };
533
496
  }
534
- removeAllTracks() {
535
- this.removeAudioTrack();
536
- this.removeVideoTrack();
537
- this.removeScreenShareTracks();
538
- }
539
497
  setAudioTrack(audioTrack) {
540
498
  if (audioTrack === this.audioTrack) {
541
499
  return;
@@ -677,10 +635,7 @@ class LocalMediaHandler extends EventEmitter {
677
635
  }
678
636
  setAudioDevice(device) {
679
637
  return __awaiter(this, void 0, void 0, function* () {
680
- yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").chooseAudioRoute(device.deviceId);
681
- this.setupAudioStream(device.deviceId);
682
- this.emit('AUDIO_TRACK_CHANGE');
683
- this.emit('DEVICE_CHANGE', { device });
638
+ yield this.setupAudioStream(device.deviceId);
684
639
  });
685
640
  }
686
641
  setVideoDevice(device) {
@@ -689,8 +644,6 @@ class LocalMediaHandler extends EventEmitter {
689
644
  this.removeVideoTrack();
690
645
  }
691
646
  yield this.setupVideoStream(device.deviceId);
692
- this.emit('VIDEO_TRACK_CHANGE');
693
- this.emit('DEVICE_CHANGE', { device });
694
647
  });
695
648
  }
696
649
  setSpeakerDevice(device) {
@@ -700,7 +653,7 @@ class LocalMediaHandler extends EventEmitter {
700
653
  }
701
654
  setDevice(route) {
702
655
  return __awaiter(this, void 0, void 0, function* () {
703
- return yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").chooseAudioRoute(route.deviceId);
656
+ yield __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").chooseAudioRoute(route.deviceId);
704
657
  });
705
658
  }
706
659
  oniOSBroadcastStart() {
@@ -767,11 +720,6 @@ class LocalMediaHandler extends EventEmitter {
767
720
  yield this.toggleScreenShare();
768
721
  });
769
722
  }
770
- destruct() {
771
- this.removeAllTracks();
772
- this.removeAllListeners();
773
- InCallManger.stop(undefined);
774
- }
775
723
  getAllDevices() {
776
724
  return __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").availableDevices;
777
725
  }
@@ -844,40 +792,85 @@ class LocalMediaHandler extends EventEmitter {
844
792
  }
845
793
  });
846
794
  }
847
- cleanUpTracks() {
848
- var _a, _b, _c, _d;
849
- (_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
850
- (_b = this.rawAudioTrack) === null || _b === void 0 ? void 0 : _b.stop();
851
- (_c = this.videoTrack) === null || _c === void 0 ? void 0 : _c.stop();
852
- (_d = this.rawVideoTrack) === null || _d === void 0 ? void 0 : _d.stop();
853
- this.destructor();
795
+ static init(_) {
796
+ return __awaiter(this, void 0, void 0, function* () {
797
+ const localMediaUtils = yield LocalMediaUtils.init();
798
+ return new LocalMediaHandler(localMediaUtils);
799
+ });
800
+ }
801
+ emit(event, ...args) {
802
+ return super.emit(event, ...args);
803
+ }
804
+ on(event, listener) {
805
+ return super.on(event, listener);
806
+ }
807
+ destruct() {
808
+ this.destructMediaHandler();
854
809
  }
855
810
  destructMediaHandler() {
856
811
  return __awaiter(this, void 0, void 0, function* () {
812
+ this.removeAllTracks();
813
+ this.removeAllListeners();
814
+ this.cleanUpTracks();
857
815
  __classPrivateFieldGet(this, _LocalMediaHandler_localMediaUtils, "f").destruct();
858
816
  try {
859
- yield DyteHelper.stopService();
817
+ if (Platform.OS === 'android')
818
+ yield DyteHelper.stopService();
860
819
  }
861
820
  catch (e) {
862
821
  console.warn('Failed to stop foreground service', e);
863
822
  }
864
- return this.destruct();
823
+ InCallManger.stop(undefined);
865
824
  });
866
825
  }
867
- static init(_) {
868
- return __awaiter(this, void 0, void 0, function* () {
869
- const localMediaUtils = yield LocalMediaUtils.init();
870
- return new LocalMediaHandler(localMediaUtils);
871
- });
826
+ cleanUpTracks() {
827
+ var _a, _b, _c, _d;
828
+ (_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
829
+ (_b = this.rawAudioTrack) === null || _b === void 0 ? void 0 : _b.stop();
830
+ (_c = this.videoTrack) === null || _c === void 0 ? void 0 : _c.stop();
831
+ (_d = this.rawVideoTrack) === null || _d === void 0 ? void 0 : _d.stop();
832
+ this.destructor();
872
833
  }
873
- emit(event, ...args) {
874
- return super.emit(event, ...args);
834
+ destructor() {
835
+ if (Platform.OS === 'android')
836
+ __classPrivateFieldGet(this, _LocalMediaHandler_appStateSubscription, "f").remove();
837
+ broadcastEmitter.removeAllListeners('iOS_BroadcastStarted');
838
+ broadcastEmitter.removeAllListeners('iOS_BroadcastStopped');
839
+ BackgroundTimer.stop();
875
840
  }
876
- on(event, listener) {
877
- return super.on(event, listener);
841
+ removeAllTracks() {
842
+ this.removeAudioTrack();
843
+ this.removeVideoTrack();
844
+ this.removeScreenShareTracks();
845
+ }
846
+ stopAudioTrack() {
847
+ var _a, _b;
848
+ (_a = this.audioTrack) === null || _a === void 0 ? void 0 : _a.stop();
849
+ (_b = this.audioTrack) === null || _b === void 0 ? void 0 : _b.release();
850
+ this.audioEnabled = false;
851
+ }
852
+ removeAudioTrack() {
853
+ this.stopAudioTrack();
854
+ this.audioTrack = undefined;
855
+ this.rawAudioTrack = undefined;
856
+ }
857
+ stopVideoTrack() {
858
+ var _a, _b, _c, _d;
859
+ (_a = this.rawVideoTrack) === null || _a === void 0 ? void 0 : _a.stop();
860
+ (_b = this.videoTrack) === null || _b === void 0 ? void 0 : _b.stop();
861
+ (_c = this.rawVideoTrack) === null || _c === void 0 ? void 0 : _c.release();
862
+ (_d = this.videoTrack) === null || _d === void 0 ? void 0 : _d.release();
863
+ }
864
+ removeVideoTrack() {
865
+ this.stopVideoTrack();
866
+ this.videoTrack = undefined;
867
+ this.rawVideoTrack = undefined;
878
868
  }
879
869
  removeAllListeners(event) {
880
- if (event === 'SCREENSHARE_TRACK_CHANGE' || !event) {
870
+ if (event === 'SCREENSHARE_TRACK_CHANGE' ||
871
+ event === 'DEVICE_LIST_UPDATED' ||
872
+ event === 'DEVICE_CHANGE' ||
873
+ !event) {
881
874
  return null;
882
875
  }
883
876
  return super.removeAllListeners(event);
@@ -120,7 +120,6 @@ class LocalMediaUtils {
120
120
  return Object.assign(Object.assign({}, audioDeviceProps), { deviceId: audioDevice, label: audioDevice, kind: 'audioinput' });
121
121
  })
122
122
  .filter((audioDevice) => audioDevice.connected);
123
- // console.log('Resp: ', JSON.stringify(resp, null, 2));
124
123
  return resp;
125
124
  });
126
125
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/realtimekit-react-native",
3
- "version": "0.1.2-staging.7",
3
+ "version": "0.1.2-staging.9",
4
4
  "description": "Cloudflare RealtimeKit SDK for react native",
5
5
  "main": "lib/index.js",
6
6
  "author": "Cloudflare",