@fishjam-cloud/react-native-client 0.2.4 → 0.3.0

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 (72) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -6
  3. package/android/build.gradle +3 -3
  4. package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +25 -12
  5. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +50 -33
  6. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +7 -16
  7. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewView.kt +13 -3
  8. package/build/RNFishjamClientModule.d.ts +10 -8
  9. package/build/RNFishjamClientModule.d.ts.map +1 -1
  10. package/build/RNFishjamClientModule.js.map +1 -1
  11. package/build/common/client.d.ts +3 -3
  12. package/build/common/client.d.ts.map +1 -1
  13. package/build/common/client.js +4 -4
  14. package/build/common/client.js.map +1 -1
  15. package/build/common/metadata.d.ts +3 -3
  16. package/build/common/metadata.d.ts.map +1 -1
  17. package/build/common/metadata.js +4 -4
  18. package/build/common/metadata.js.map +1 -1
  19. package/build/common/webRTC.d.ts +0 -8
  20. package/build/common/webRTC.d.ts.map +1 -1
  21. package/build/common/webRTC.js +0 -9
  22. package/build/common/webRTC.js.map +1 -1
  23. package/build/components/VideoRendererView.d.ts +1 -1
  24. package/build/components/VideoRendererView.js +1 -1
  25. package/build/components/VideoRendererView.js.map +1 -1
  26. package/build/debug/common/webRTC.d.ts +9 -0
  27. package/build/debug/common/webRTC.d.ts.map +1 -0
  28. package/build/debug/common/webRTC.js +11 -0
  29. package/build/debug/common/webRTC.js.map +1 -0
  30. package/build/debug/index.d.ts +4 -0
  31. package/build/debug/index.d.ts.map +1 -0
  32. package/build/debug/index.js +3 -0
  33. package/build/debug/index.js.map +1 -0
  34. package/build/debug/stats/types.d.ts.map +1 -0
  35. package/build/debug/stats/types.js.map +1 -0
  36. package/build/debug/stats/useRTCStatistics.d.ts.map +1 -0
  37. package/build/{stats → debug/stats}/useRTCStatistics.js +1 -1
  38. package/build/debug/stats/useRTCStatistics.js.map +1 -0
  39. package/build/hooks/useFishjamEvent.d.ts +1 -0
  40. package/build/hooks/useFishjamEvent.d.ts.map +1 -1
  41. package/build/hooks/useFishjamEvent.js +1 -0
  42. package/build/hooks/useFishjamEvent.js.map +1 -1
  43. package/build/hooks/usePeerStatus.d.ts +19 -0
  44. package/build/hooks/usePeerStatus.d.ts.map +1 -0
  45. package/build/hooks/usePeerStatus.js +18 -0
  46. package/build/hooks/usePeerStatus.js.map +1 -0
  47. package/build/hooks/{useParticipants.d.ts → usePeers.d.ts} +11 -11
  48. package/build/hooks/usePeers.d.ts.map +1 -0
  49. package/build/hooks/usePeers.js +34 -0
  50. package/build/hooks/usePeers.js.map +1 -0
  51. package/build/index.d.ts +5 -5
  52. package/build/index.d.ts.map +1 -1
  53. package/build/index.js +3 -3
  54. package/build/index.js.map +1 -1
  55. package/debug/package.json +4 -0
  56. package/ios/Events.swift +29 -13
  57. package/ios/RNFishjamClient.podspec +1 -1
  58. package/ios/RNFishjamClient.swift +58 -55
  59. package/ios/RNFishjamClientModule.swift +7 -15
  60. package/ios/VideoPreviewView.swift +27 -9
  61. package/package.json +4 -3
  62. package/plugin/build/withFishjamIos.js +2 -2
  63. package/build/hooks/useParticipants.d.ts.map +0 -1
  64. package/build/hooks/useParticipants.js +0 -34
  65. package/build/hooks/useParticipants.js.map +0 -1
  66. package/build/stats/types.d.ts.map +0 -1
  67. package/build/stats/types.js.map +0 -1
  68. package/build/stats/useRTCStatistics.d.ts.map +0 -1
  69. package/build/stats/useRTCStatistics.js.map +0 -1
  70. /package/build/{stats → debug/stats}/types.d.ts +0 -0
  71. /package/build/{stats → debug/stats}/types.js +0 -0
  72. /package/build/{stats → debug/stats}/useRTCStatistics.d.ts +0 -0
package/ios/Events.swift CHANGED
@@ -1,14 +1,30 @@
1
- struct EmitableEvents {
2
- static let IsCameraOn = "IsCameraOn"
3
- static let IsMicrophoneOn = "IsMicrophoneOn"
4
- static let IsScreenShareOn = "IsScreenShareOn"
5
- static let SimulcastConfigUpdate = "SimulcastConfigUpdate"
6
- static let PeersUpdate = "PeersUpdate"
7
- static let AudioDeviceUpdate = "AudioDeviceUpdate"
8
- static let SendMediaEvent = "SendMediaEvent"
9
- static let BandwidthEstimation = "BandwidthEstimation"
10
- static let ReconnectionRetriesLimitReached = "ReconnectionRetriesLimitReached"
11
- static let ReconnectionStarted = "ReconnectionStarted"
12
- static let Reconnected = "Reconnected"
13
- static let Warning = "Warning"
1
+ enum PeerStatus: String {
2
+ case connecting
3
+ case connected
4
+ case error
5
+ case idle
6
+ }
7
+
8
+ enum EmitableEvents: String, CaseIterable {
9
+ case IsCameraOn
10
+ case IsMicrophoneOn
11
+ case IsScreenShareOn
12
+ case SimulcastConfigUpdate
13
+ case PeersUpdate
14
+ case AudioDeviceUpdate
15
+ case SendMediaEvent
16
+ case BandwidthEstimation
17
+ case ReconnectionRetriesLimitReached
18
+ case ReconnectionStarted
19
+ case Reconnected
20
+ case Warning
21
+ case PeerStatusChanged
22
+
23
+ var name: String {
24
+ rawValue
25
+ }
26
+
27
+ static var allEvents: [String] {
28
+ EmitableEvents.allCases.map(\.name)
29
+ }
14
30
  }
@@ -25,6 +25,6 @@ Pod::Spec.new do |s|
25
25
 
26
26
  s.source_files = '**/*.{h,m,swift}'
27
27
 
28
- s.dependency 'FishjamCloudClient', '0.2.4'
28
+ s.dependency 'FishjamCloudClient', '0.3.0'
29
29
 
30
30
  end
@@ -28,9 +28,17 @@ class RNFishjamClient: FishjamClientListener {
28
28
  var audioSessionMode: AVAudioSession.Mode = AVAudioSession.Mode.videoChat
29
29
  var errorMessage: String?
30
30
 
31
+ private(set) var peerStatus: PeerStatus = .idle {
32
+ didSet {
33
+ let event = EmitableEvents.PeerStatusChanged
34
+ emit(event: event, data: [event.name: peerStatus.rawValue])
35
+ }
36
+ }
37
+
31
38
  let sendEvent: (_ eventName: String, _ data: [String: Any]) -> Void
32
39
 
33
40
  static var onTracksUpdateListeners: [OnTrackUpdateListener] = []
41
+ static var localCameraTrackListeners: [OnLocalCameraTrackChangedListener] = []
34
42
 
35
43
  init(sendEvent: @escaping (_ eventName: String, _ data: [String: Any]) -> Void) {
36
44
  self.sendEvent = sendEvent
@@ -172,18 +180,16 @@ class RNFishjamClient: FishjamClientListener {
172
180
  connectPromise.reject("E_MEMBRANE_CONNECT", "Failed to connect: socket error")
173
181
  }
174
182
  connectPromise = nil
175
- }
176
-
177
- func onAuthSuccess() {
178
- join()
183
+ peerStatus = .error
179
184
  }
180
185
 
181
186
  func joinRoom(
182
- url: String, participantToken: String, participantMetadata: [String: Any], config: ConnectConfig,
187
+ url: String, peerToken: String, peerMetadata: [String: Any], config: ConnectConfig,
183
188
  promise: Promise
184
189
  ) {
190
+ peerStatus = .connecting
185
191
  connectPromise = promise
186
- localUserMetadata = participantMetadata.toMetadata()
192
+ localUserMetadata = peerMetadata.toMetadata()
187
193
 
188
194
  let reconnectConfig = FishjamCloudClient.ReconnectConfig(
189
195
  maxAttempts: config.reconnectConfig.maxAttempts, initialDelayMs: config.reconnectConfig.initialDelayMs,
@@ -191,16 +197,12 @@ class RNFishjamClient: FishjamClientListener {
191
197
 
192
198
  RNFishjamClient.fishjamClient?.connect(
193
199
  config: FishjamCloudClient.ConnectConfig(
194
- websocketUrl: url, token: participantToken, participantMetadata: .init(participantMetadata),
200
+ websocketUrl: url, token: peerToken, peerMetadata: .init(peerMetadata),
195
201
  reconnectConfig: reconnectConfig
196
202
  ))
197
203
 
198
204
  }
199
205
 
200
- func join() {
201
- RNFishjamClient.fishjamClient?.join(peerMetadata: localUserMetadata)
202
- }
203
-
204
206
  func leaveRoom() {
205
207
  if isScreenShareOn {
206
208
  let screenShareExtensionBundleId =
@@ -214,7 +216,9 @@ class RNFishjamClient: FishjamClientListener {
214
216
  isScreenShareOn = false
215
217
  isConnected = false
216
218
  isCameraInitialized = false
217
- RNFishjamClient.fishjamClient?.leave()
219
+ RNFishjamClient.fishjamClient?.leave { [weak self] in
220
+ self?.emitEndpoints()
221
+ }
218
222
  }
219
223
 
220
224
  func startCamera(config: CameraConfig) throws {
@@ -245,9 +249,10 @@ class RNFishjamClient: FishjamClientListener {
245
249
  private func setCameraTrackState(_ cameraTrack: LocalVideoTrack, enabled: Bool) {
246
250
  cameraTrack.enabled = enabled
247
251
  isCameraOn = enabled
248
- let eventName = EmitableEvents.IsCameraOn
249
- let isCameraEnabledMap = [eventName: enabled]
250
- emitEvent(name: eventName, data: isCameraEnabledMap)
252
+ let event = EmitableEvents.IsCameraOn
253
+ let isCameraEnabledMap = [event.name: enabled]
254
+ emit(event: event, data: isCameraEnabledMap)
255
+ RNFishjamClient.localCameraTrackListeners.forEach { $0.onLocalCameraTrackChanged() }
251
256
  }
252
257
 
253
258
  func toggleCamera() throws -> Bool {
@@ -277,8 +282,7 @@ class RNFishjamClient: FishjamClientListener {
277
282
  }
278
283
 
279
284
  func startMicrophone() throws {
280
- let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(
281
- metadata: Metadata())
285
+ let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(metadata: Metadata())
282
286
  setAudioSessionMode()
283
287
  setMicrophoneTrackState(microphoneTrack, enabled: true)
284
288
  emitEndpoints()
@@ -287,10 +291,9 @@ class RNFishjamClient: FishjamClientListener {
287
291
  private func setMicrophoneTrackState(_ microphoneTrack: LocalAudioTrack, enabled: Bool) {
288
292
  microphoneTrack.enabled = enabled
289
293
  isMicrophoneOn = enabled
290
- let eventName = EmitableEvents.IsMicrophoneOn
291
- let isMicrophoneOnMap = [eventName: enabled]
292
- print(isMicrophoneOnMap)
293
- emitEvent(name: eventName, data: isMicrophoneOnMap)
294
+ let event = EmitableEvents.IsMicrophoneOn
295
+ let isMicrophoneOnMap = [event.name: enabled]
296
+ emit(event: event, data: isMicrophoneOnMap)
294
297
  }
295
298
 
296
299
  func setAudioSessionMode() {
@@ -343,16 +346,15 @@ class RNFishjamClient: FishjamClientListener {
343
346
  maxBandwidth: screenShareOptions.maxBandwidth)
344
347
  let screenShareMetadata = screenShareOptions.screenShareMetadata.toMetadata()
345
348
  let videoParameters = getScreenShareVideoParameters(options: screenShareOptions)
346
- RNFishjamClient.fishjamClient!.createScreenShareTrack(
349
+ RNFishjamClient.fishjamClient!.prepareForScreenSharing(
347
350
  appGroup: appGroupName,
348
351
  videoParameters: videoParameters,
349
352
  metadata: screenShareMetadata,
350
- onStart: { [weak self] screenShareTrack in
351
- guard let self = self else { return }
353
+ onStart: { [weak self] in
354
+ guard let self else { return }
352
355
 
353
356
  do {
354
- //not sure should it be here, or outside or where?
355
- try setScreenShareTrackState(screenShareTrack, enabled: true)
357
+ try setScreenShareTrackState(enabled: true)
356
358
  } catch {
357
359
  os_log(
358
360
  "Error starting screen share: %{public}s", log: log, type: .error,
@@ -361,11 +363,10 @@ class RNFishjamClient: FishjamClientListener {
361
363
  }
362
364
 
363
365
  },
364
- onStop: { [weak self] screenShareTrack in
365
- guard let self = self else { return }
366
+ onStop: { [weak self] in
367
+ guard let self else { return }
366
368
  do {
367
- //not sure should it be here, or outside or where?
368
- try setScreenShareTrackState(screenShareTrack, enabled: false)
369
+ try setScreenShareTrackState(enabled: false)
369
370
  } catch {
370
371
  os_log(
371
372
  "Error stopping screen share: %{public}s", log: log, type: .error,
@@ -379,13 +380,11 @@ class RNFishjamClient: FishjamClientListener {
379
380
  }
380
381
  }
381
382
 
382
- private func setScreenShareTrackState(_ screenShareTrack: LocalScreenShareTrack, enabled: Bool) throws {
383
- //was not present before, test and maybe delete?
384
- screenShareTrack.enabled = enabled
383
+ private func setScreenShareTrackState(enabled: Bool) throws {
385
384
  isScreenShareOn = enabled
386
- let eventName = EmitableEvents.IsScreenShareOn
387
- let isScreenShareEnabled = [eventName: enabled]
388
- emitEvent(name: eventName, data: isScreenShareEnabled)
385
+ let event = EmitableEvents.IsScreenShareOn
386
+ let isScreenShareEnabled = [event.name: enabled]
387
+ emit(event: event, data: isScreenShareEnabled)
389
388
  }
390
389
 
391
390
  //returns local endpoint and remote endpoints
@@ -402,7 +401,7 @@ class RNFishjamClient: FishjamClientListener {
402
401
  "id": endpoint.id,
403
402
  "isLocal": endpoint.id == RNFishjamClient.fishjamClient!.getLocalEndpoint().id,
404
403
  "type": endpoint.type,
405
- "metadata": endpoint.metadata,
404
+ "metadata": endpoint.metadata.toDict(),
406
405
  "tracks": endpoint.tracks.values.compactMap { track -> [String: Any?]? in
407
406
  switch track {
408
407
  case let track as RemoteVideoTrack:
@@ -556,9 +555,9 @@ class RNFishjamClient: FishjamClientListener {
556
555
  videoSimulcastConfig = try toggleTrackEncoding(
557
556
  encoding: encoding, trackId: track.id, simulcastConfig: videoSimulcastConfig)
558
557
 
559
- let eventName = EmitableEvents.SimulcastConfigUpdate
558
+ let event = EmitableEvents.SimulcastConfigUpdate
560
559
  let simulcastConfigAsRNMap = getSimulcastConfigAsRNMap(videoSimulcastConfig)
561
- emitEvent(name: eventName, data: simulcastConfigAsRNMap)
560
+ emit(event: event, data: simulcastConfigAsRNMap)
562
561
 
563
562
  return simulcastConfigAsRNMap
564
563
  }
@@ -673,18 +672,18 @@ class RNFishjamClient: FishjamClientListener {
673
672
  )
674
673
  }
675
674
 
676
- func emitEvent(name: String, data: [String: Any]) {
677
- sendEvent(name, data)
675
+ func emit(event: EmitableEvents, data: [String: Any] = [:]) {
676
+ sendEvent(event.name, data)
678
677
  }
679
678
 
680
679
  func emit(warning: String) {
681
- emitEvent(name: EmitableEvents.Warning, data: ["message": warning])
680
+ emit(event: .Warning, data: ["message": warning])
682
681
  }
683
682
 
684
683
  func emitEndpoints() {
685
- let eventName = EmitableEvents.PeersUpdate
686
- let EndpointsUpdateMap = [eventName: (try? getPeers()) ?? []]
687
- emitEvent(name: eventName, data: EndpointsUpdateMap)
684
+ let event = EmitableEvents.PeersUpdate
685
+ let EndpointsUpdateMap = [event.name: (try? getPeers()) ?? []]
686
+ emit(event: event, data: EndpointsUpdateMap)
688
687
  }
689
688
 
690
689
  func onJoined(peerID: String, peersInRoom: [String: Endpoint]) {
@@ -692,6 +691,7 @@ class RNFishjamClient: FishjamClientListener {
692
691
  connectPromise?.resolve(nil)
693
692
  connectPromise = nil
694
693
  emitEndpoints()
694
+ peerStatus = .connected
695
695
  }
696
696
 
697
697
  func onJoinError(metadata: Any) {
@@ -753,6 +753,7 @@ class RNFishjamClient: FishjamClientListener {
753
753
  "E_MEMBRANE_CONNECT", "Failed to connect: socket close, code: \(code), reason: \(reason)")
754
754
  }
755
755
  connectPromise = nil
756
+ peerStatus = .error
756
757
  }
757
758
 
758
759
  func onSocketError() {
@@ -764,7 +765,9 @@ class RNFishjamClient: FishjamClientListener {
764
765
 
765
766
  func onSocketOpen() {}
766
767
 
767
- func onDisconnected() {}
768
+ func onDisconnected() {
769
+ peerStatus = .idle
770
+ }
768
771
 
769
772
  func getSimulcastConfigAsRNMap(_ simulcastConfig: SimulcastConfig) -> [String: Any] {
770
773
  return [
@@ -826,11 +829,11 @@ class RNFishjamClient: FishjamClientListener {
826
829
  default:
827
830
  deviceTypeString = deviceType.rawValue
828
831
  }
829
- let eventName = EmitableEvents.AudioDeviceUpdate
830
- emitEvent(
831
- name: eventName,
832
+ let event = EmitableEvents.AudioDeviceUpdate
833
+ emit(
834
+ event: event,
832
835
  data: [
833
- eventName: [
836
+ event.name: [
834
837
  "selectedDevice": ["name": output.portName, "type": deviceTypeString],
835
838
  "availableDevices": [],
836
839
  ]
@@ -838,20 +841,20 @@ class RNFishjamClient: FishjamClientListener {
838
841
  }
839
842
 
840
843
  func onBandwidthEstimationChanged(estimation: Int) {
841
- let eventName = EmitableEvents.BandwidthEstimation
842
- emitEvent(name: eventName, data: [eventName: estimation])
844
+ let event = EmitableEvents.BandwidthEstimation
845
+ emit(event: event, data: [event.name: estimation])
843
846
  }
844
847
 
845
848
  func onReconnectionStarted() {
846
- emitEvent(name: EmitableEvents.ReconnectionStarted, data: [:])
849
+ emit(event: .ReconnectionStarted)
847
850
  }
848
851
 
849
852
  func onReconnected() {
850
- emitEvent(name: EmitableEvents.Reconnected, data: [:])
853
+ emit(event: .Reconnected)
851
854
  }
852
855
 
853
856
  func onReconnectionRetriesLimitReached() {
854
- emitEvent(name: EmitableEvents.ReconnectionRetriesLimitReached, data: [:])
857
+ emit(event: .ReconnectionRetriesLimitReached)
855
858
  }
856
859
 
857
860
  }
@@ -75,19 +75,7 @@ public class RNFishjamClientModule: Module {
75
75
  public func definition() -> ModuleDefinition {
76
76
  Name("RNFishjamClient")
77
77
 
78
- Events(
79
- "IsCameraOn",
80
- "IsMicrophoneOn",
81
- "IsScreenShareOn",
82
- "SimulcastConfigUpdate",
83
- "PeersUpdate",
84
- "AudioDeviceUpdate",
85
- "SendMediaEvent",
86
- "BandwidthEstimation",
87
- "ReconnectionRetriesLimitReached",
88
- "ReconnectionStarted",
89
- "Reconnected",
90
- "Warning")
78
+ Events(EmitableEvents.allEvents)
91
79
 
92
80
  let rnFishjamClient: RNFishjamClient = {
93
81
  let client = RNFishjamClient {
@@ -100,11 +88,11 @@ public class RNFishjamClientModule: Module {
100
88
 
101
89
  AsyncFunction("joinRoom") {
102
90
  (
103
- url: String, participantToken: String, participantMetadata: [String: Any], config: ConnectConfig,
91
+ url: String, peerToken: String, peerMetadata: [String: Any], config: ConnectConfig,
104
92
  promise: Promise
105
93
  ) in
106
94
  rnFishjamClient.joinRoom(
107
- url: url, participantToken: participantToken, participantMetadata: participantMetadata, config: config,
95
+ url: url, peerToken: peerToken, peerMetadata: peerMetadata, config: config,
108
96
  promise: promise)
109
97
  }
110
98
 
@@ -221,5 +209,9 @@ public class RNFishjamClientModule: Module {
221
209
  AsyncFunction("startAudioSwitcher") {
222
210
  rnFishjamClient.startAudioSwitcher()
223
211
  }
212
+
213
+ Property("peerStatus") {
214
+ return rnFishjamClient.peerStatus.rawValue
215
+ }
224
216
  }
225
217
  }
@@ -1,7 +1,11 @@
1
1
  import ExpoModulesCore
2
2
  import FishjamCloudClient
3
3
 
4
- class VideoPreviewView: ExpoView {
4
+ protocol OnLocalCameraTrackChangedListener: AnyObject {
5
+ func onLocalCameraTrackChanged()
6
+ }
7
+
8
+ class VideoPreviewView: ExpoView, OnLocalCameraTrackChangedListener {
5
9
  var videoView: VideoView? = nil
6
10
  private var localVideoTrack: LocalVideoTrack? = nil
7
11
 
@@ -13,11 +17,9 @@ class VideoPreviewView: ExpoView {
13
17
  addSubview(videoView!)
14
18
  }
15
19
 
16
- override func willMove(toSuperview newSuperview: UIView?) {
17
- super.willMove(toSuperview: newSuperview)
18
- if newSuperview == nil {
19
- localVideoTrack?.stop()
20
- } else {
20
+ private func trySetLocalCameraTrack() {
21
+ DispatchQueue.main.async { [weak self] in
22
+ guard let self else { return }
21
23
  guard let tracks = RNFishjamClient.fishjamClient?.getLocalEndpoint().tracks else {
22
24
  os_log(
23
25
  "Error moving VideoPreviewView: %{public}s", log: log, type: .error,
@@ -26,12 +28,23 @@ class VideoPreviewView: ExpoView {
26
28
  return
27
29
  }
28
30
 
29
- localVideoTrack =
31
+ self.localVideoTrack =
30
32
  tracks.first(where: { (key, track) in
31
33
  track is LocalVideoTrack
32
34
  })?.value as? LocalVideoTrack
33
- localVideoTrack?.start()
34
- videoView?.track = localVideoTrack
35
+ self.localVideoTrack?.start()
36
+ self.videoView?.track = self.localVideoTrack
37
+ }
38
+ }
39
+
40
+ override func willMove(toSuperview newSuperview: UIView?) {
41
+ super.willMove(toSuperview: newSuperview)
42
+ if newSuperview == nil {
43
+ RNFishjamClient.localCameraTrackListeners.removeAll(where: { $0 === self })
44
+ localVideoTrack?.stop()
45
+ } else {
46
+ RNFishjamClient.localCameraTrackListeners.append(self)
47
+ trySetLocalCameraTrack()
35
48
  }
36
49
  }
37
50
 
@@ -61,4 +74,9 @@ class VideoPreviewView: ExpoView {
61
74
  }
62
75
  }
63
76
  }
77
+
78
+ func onLocalCameraTrackChanged() {
79
+ guard localVideoTrack == nil else { return }
80
+ trySetLocalCameraTrack()
81
+ }
64
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishjam-cloud/react-native-client",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "description": "A React Native client for Fishjam Cloud",
5
5
  "author": "Fishjam Cloud Team",
6
6
  "license": "Apache-2.0",
@@ -45,10 +45,10 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "@testing-library/react": "^15.0.7",
48
- "@types/lodash": "^4.17.7",
48
+ "@types/lodash": "^4.17.9",
49
49
  "@types/phoenix": "^1.6.5",
50
50
  "@types/promise-fs": "^2.1.2",
51
- "@types/react": "^18.3.7",
51
+ "@types/react": "^18.3.9",
52
52
  "expo": "^51.0.32",
53
53
  "expo-module-scripts": "^3.5.2",
54
54
  "expo-modules-core": "^1.12.24",
@@ -81,6 +81,7 @@
81
81
  },
82
82
  "files": [
83
83
  "build/**",
84
+ "debug",
84
85
  "android/build.gradle",
85
86
  "android/src/**",
86
87
  "ios/*.swift",
@@ -106,7 +106,7 @@ const withInfoPlistConstants = (config) => {
106
106
  };
107
107
  /**
108
108
  * Updates and copies required extension files.
109
- * Our extension needs to be properly setup inside the XCode project. In order to do that we need to copy the files and update the pbxproj.
109
+ * Our extension needs to be properly setup inside the Xcode project. In order to do that we need to copy the files and update the pbxproj.
110
110
  */
111
111
  const withFishjamSBE = (config, options) => {
112
112
  return (0, config_plugins_1.withXcodeProject)(config, async (props) => {
@@ -128,7 +128,7 @@ const withFishjamSBE = (config, options) => {
128
128
  console.error(`Error parsing iOS project: ${JSON.stringify(err)}`);
129
129
  return;
130
130
  }
131
- if (xcodeProject.pbxTargetByName(`"${SBE_TARGET_NAME}"`)) {
131
+ if (xcodeProject.pbxTargetByName(SBE_TARGET_NAME)) {
132
132
  console.log(`${SBE_TARGET_NAME} already exists in project. Skipping...`);
133
133
  return;
134
134
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"useParticipants.d.ts","sourceRoot":"","sources":["../../src/hooks/useParticipants.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAiB,MAAM,UAAU,CAAC;AAIzE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7C,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACnC,IAAI,EAAE,OAAO,CAAC;IAEd,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAE/B,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,UAAU,CAAC;AAC5C;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,mBAAmB,GAAG,eAAe,CAAC;AAE7E,MAAM,MAAM,WAAW,CACrB,mBAAmB,SAAS,eAAe,GAAG,eAAe,IAC3D;IACF;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,mBAAmB,CAAC;IAC9B;;OAEG;IACH,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC;AAgBF;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,mBAAmB,SAAS,eAAe,GAAG,eAAe;;EA0B9D"}
@@ -1,34 +0,0 @@
1
- import { useCallback, useEffect, useState } from 'react';
2
- import RNFishjamClientModule from '../RNFishjamClientModule';
3
- import { ReceivableEvents, useFishjamEvent } from './useFishjamEvent';
4
- function addIsActiveToTracks(participants) {
5
- return participants.map((participant) => ({
6
- ...participant,
7
- tracks: participant.tracks.map((track) => ({
8
- ...track,
9
- isActive: track?.metadata?.active ?? true,
10
- })),
11
- }));
12
- }
13
- /**
14
- * This hook provides live updates of room participants.
15
- * @returns An array of room participants.
16
- * @category Connection
17
- * @group Hooks
18
- */
19
- export function useParticipants() {
20
- const [participants, setParticipants] = useState([]);
21
- const updateActiveParticipants = useCallback((participants) => {
22
- setParticipants(addIsActiveToTracks(participants));
23
- }, []);
24
- useFishjamEvent(ReceivableEvents.PeersUpdate, updateActiveParticipants);
25
- useEffect(() => {
26
- async function updateParticipants() {
27
- const participants = await RNFishjamClientModule.getPeers();
28
- setParticipants(addIsActiveToTracks(participants));
29
- }
30
- updateParticipants();
31
- }, []);
32
- return { participants };
33
- }
34
- //# sourceMappingURL=useParticipants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useParticipants.js","sourceRoot":"","sources":["../../src/hooks/useParticipants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGzD,OAAO,qBAAqB,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA8DtE,SAAS,mBAAmB,CAG1B,YAA6D;IAE7D,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACxC,GAAG,WAAW;QACd,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACzC,GAAG,KAAK;YACR,QAAQ,EACL,KAAsC,EAAE,QAAQ,EAAE,MAAM,IAAI,IAAI;SACpE,CAAC,CAAC;KACJ,CAAC,CAAC,CAAC;AACN,CAAC;AACD;;;;;GAKG;AACH,MAAM,UAAU,eAAe;IAG7B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAE9C,EAAE,CAAC,CAAC;IAEN,MAAM,wBAAwB,GAAG,WAAW,CAC1C,CAAC,YAAgD,EAAE,EAAE;QACnD,eAAe,CAAC,mBAAmB,CAAsB,YAAY,CAAC,CAAC,CAAC;IAC1E,CAAC,EACD,EAAE,CACH,CAAC;IAEF,eAAe,CAAC,gBAAgB,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAC;IAExE,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,UAAU,kBAAkB;YAC/B,MAAM,YAAY,GAChB,MAAM,qBAAqB,CAAC,QAAQ,EAAuB,CAAC;YAC9D,eAAe,CAAC,mBAAmB,CAAsB,YAAY,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,kBAAkB,EAAE,CAAC;IACvB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC","sourcesContent":["import { useCallback, useEffect, useState } from 'react';\n\nimport { GenericMetadata, TrackEncoding, TrackMetadata } from '../types';\nimport RNFishjamClientModule from '../RNFishjamClientModule';\nimport { ReceivableEvents, useFishjamEvent } from './useFishjamEvent';\n\nexport type TrackType = 'Audio' | 'Video';\n\n/**\n * Type describing Voice Activity Detection statuses.\n *\n * speech - voice activity has been detected\n * silence - lack of voice activity has been detected\n */\nexport type VadStatus = 'silence' | 'speech';\n\ntype TrackBase = {\n id: string;\n type: TrackType;\n isActive: boolean;\n};\n\nexport type AudioTrack = TrackBase & {\n type: 'Audio';\n vadStatus: VadStatus | undefined;\n};\n\nexport type VideoTrack = TrackBase & {\n type: 'Video';\n // Encoding that is currently received. Only present for remote tracks.\n encoding: TrackEncoding | null;\n // The reason of currently selected encoding. Only present for remote tracks.\n encodingReason: EncodingReason | null;\n};\n\nexport type Track = VideoTrack | AudioTrack;\n/**\n * Type describing possible reasons of currently selected encoding.\n *\n * - other - the exact reason couldn't be determined\n * - encoding_inactive - previously selected encoding became inactive\n * - low_bandwidth - there is no longer enough bandwidth to maintain previously selected encoding\n */\nexport type EncodingReason = 'other' | 'encoding_inactive' | 'low_bandwidth';\n\nexport type Participant<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n> = {\n /**\n * id used to identify a participant\n */\n id: string;\n /**\n * whether the participant is local or remote\n */\n isLocal: boolean;\n /**\n * a map indexed by strings, containing participant metadata from the server\n */\n metadata: ParticipantMetadata;\n /**\n * a list of participants's video and audio tracks\n */\n tracks: Track[];\n};\n\nfunction addIsActiveToTracks<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n>(\n participants: ReadonlyArray<Participant<ParticipantMetadata>>,\n): Participant<ParticipantMetadata>[] {\n return participants.map((participant) => ({\n ...participant,\n tracks: participant.tracks.map((track) => ({\n ...track,\n isActive:\n (track as { metadata?: TrackMetadata })?.metadata?.active ?? true,\n })),\n }));\n}\n/**\n * This hook provides live updates of room participants.\n * @returns An array of room participants.\n * @category Connection\n * @group Hooks\n */\nexport function useParticipants<\n ParticipantMetadata extends GenericMetadata = GenericMetadata,\n>() {\n const [participants, setParticipants] = useState<\n Participant<ParticipantMetadata>[]\n >([]);\n\n const updateActiveParticipants = useCallback(\n (participants: Participant<ParticipantMetadata>[]) => {\n setParticipants(addIsActiveToTracks<ParticipantMetadata>(participants));\n },\n [],\n );\n\n useFishjamEvent(ReceivableEvents.PeersUpdate, updateActiveParticipants);\n\n useEffect(() => {\n async function updateParticipants() {\n const participants =\n await RNFishjamClientModule.getPeers<ParticipantMetadata>();\n setParticipants(addIsActiveToTracks<ParticipantMetadata>(participants));\n }\n\n updateParticipants();\n }, []);\n\n return { participants };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/stats/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B,EAAE,0BAA0B,CAAC;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;CAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/stats/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * A record of the total time, in seconds,\n * that this stream has spent in each quality limitation state.\n * none: The resolution and/or framerate is not limited.\n * bandwidth: The resolution and/or framerate is primarily limited due to\n * congestion cues during bandwidth estimation.\n * Typical, congestion control algorithms use inter-arrival time,\n * round-trip time, packet or other congestion cues to perform bandwidth estimation.\n * cpu: The resolution and/or framerate is primarily limited due to CPU load.\n * other: The resolution and/or framerate is primarily limited\n * for a reason other than the above.\n */\nexport type QualityLimitationDurations = {\n bandwidth: number;\n cpu: number;\n none: number;\n other: number;\n};\n\nexport type RTCOutboundStats = {\n 'kind': string;\n 'rid': string;\n 'bytesSent': number;\n 'targetBitrate': number;\n 'packetsSent': number;\n 'framesEncoded': number;\n 'framesPerSecond': number;\n 'frameWidth': number;\n 'frameHeight': number;\n 'qualityLimitationDurations': QualityLimitationDurations;\n 'bytesSent/s': number;\n 'packetsSent/s': number;\n 'framesEncoded/s': number;\n};\n\nexport type RTCInboundStats = {\n 'kind': number;\n 'jitter': number;\n 'packetsLost': number;\n 'packetsReceived': number;\n 'bytesReceived': number;\n 'framesReceived': number;\n 'frameWidth': number;\n 'frameHeight': number;\n 'framesPerSecond': number;\n 'framesDropped': number;\n 'packetsLost/s': number;\n 'packetsReceived/s': number;\n 'bytesReceived/s': number;\n 'framesReceived/s': number;\n 'framesDropped/s': number;\n};\n\nexport type RTCTrackStats = RTCOutboundStats | RTCInboundStats;\n\nexport type RTCStats = { [key: string]: RTCTrackStats };\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"useRTCStatistics.d.ts","sourceRoot":"","sources":["../../src/stats/useRTCStatistics.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAqC,QAAQ,EAAE,MAAM,SAAS,CAAC;AAG3E;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,eAAe,EAAE,MAAM;;EAuFvD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"useRTCStatistics.js","sourceRoot":"","sources":["../../src/stats/useRTCStatistics.ts"],"names":[],"mappings":"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","sourcesContent":["import { takeRight } from 'lodash';\nimport { useCallback, useEffect, useState } from 'react';\n\nimport type { RTCInboundStats, RTCOutboundStats, RTCStats } from './types';\nimport RNFishjamClientModule from '../RNFishjamClientModule';\n\n/**\n * This hook provides access to current rtc statistics data.\n * @category Debugging\n */\nexport function useRTCStatistics(refreshInterval: number) {\n const MAX_SIZE = 120;\n const [statistics, setStatistics] = useState<RTCStats[]>([]);\n\n // Calculates diff between pervious and current stats,\n // providing end users with a per second metric.\n const processIncomingStats = useCallback(\n (statistics: ReadonlyArray<RTCStats>, stats: Readonly<RTCStats>) => {\n Object.keys(stats).forEach((obj) => {\n if (obj.includes('Inbound')) {\n const rtcStats = stats[obj] as RTCInboundStats;\n\n if (\n statistics.length > 0 &&\n Object.keys(statistics[statistics.length - 1]).includes(obj)\n ) {\n const prevRtcStats = statistics[statistics.length - 1][\n obj\n ] as RTCInboundStats;\n\n rtcStats['packetsLost/s'] =\n rtcStats['packetsLost'] - prevRtcStats['packetsLost'];\n rtcStats['packetsReceived/s'] =\n rtcStats['packetsReceived'] - prevRtcStats['packetsReceived'];\n rtcStats['bytesReceived/s'] =\n rtcStats['bytesReceived'] - prevRtcStats['bytesReceived'];\n rtcStats['framesReceived/s'] =\n rtcStats['framesReceived'] - prevRtcStats['framesReceived'];\n rtcStats['framesDropped/s'] =\n rtcStats['framesDropped'] - prevRtcStats['framesDropped'];\n } else {\n rtcStats['packetsLost/s'] = 0;\n rtcStats['packetsReceived/s'] = 0;\n rtcStats['bytesReceived/s'] = 0;\n rtcStats['framesReceived/s'] = 0;\n rtcStats['framesDropped/s'] = 0;\n }\n return stats;\n }\n // Outbound\n const rtcStats = stats[obj] as RTCOutboundStats;\n\n if (\n statistics.length > 0 &&\n Object.keys(statistics[statistics.length - 1]).includes(obj)\n ) {\n const prevRtcStats = statistics[statistics.length - 1][\n obj\n ] as RTCOutboundStats;\n\n rtcStats['bytesSent/s'] =\n rtcStats['bytesSent'] - prevRtcStats['bytesSent'];\n rtcStats['packetsSent/s'] =\n rtcStats['packetsSent'] - prevRtcStats['packetsSent'];\n rtcStats['framesEncoded/s'] =\n rtcStats['framesEncoded'] - prevRtcStats['framesEncoded'];\n } else {\n rtcStats['bytesSent/s'] = 0;\n rtcStats['packetsSent/s'] = 0;\n rtcStats['framesEncoded/s'] = 0;\n }\n return stats;\n });\n return stats;\n },\n [],\n );\n\n // Gets stats from the native libraries.\n const getStatistics = useCallback(async () => {\n const stats = await RNFishjamClientModule.getStatistics();\n setStatistics((prev) => {\n const newStats = [...prev, processIncomingStats(prev, stats)];\n takeRight(newStats, MAX_SIZE);\n return newStats;\n });\n }, [processIncomingStats]);\n\n useEffect(() => {\n const intervalId = setInterval(getStatistics, refreshInterval);\n return () => {\n clearInterval(intervalId);\n setStatistics([]);\n };\n }, [getStatistics, refreshInterval]);\n\n return { statistics };\n}\n"]}
File without changes
File without changes