@fishjam-cloud/react-native-client 0.2.4 → 0.4.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 (108) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +9 -8
  3. package/android/build.gradle +4 -4
  4. package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +25 -12
  5. package/android/src/main/java/io/fishjam/reactnative/Errors.kt +1 -2
  6. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +94 -52
  7. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +42 -90
  8. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewView.kt +14 -3
  9. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewViewModule.kt +5 -0
  10. package/android/src/main/java/io/fishjam/reactnative/VideoRendererView.kt +4 -3
  11. package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +2 -0
  12. package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +3 -2
  13. package/android/src/main/java/io/fishjam/reactnative/{FishjamForegroundService.kt → foregroundService/FishjamForegroundService.kt} +7 -2
  14. package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceManager.kt +147 -0
  15. package/android/src/main/java/io/fishjam/reactnative/managers/LocalCameraTracksChangedListenersManager.kt +21 -0
  16. package/android/src/main/java/io/fishjam/reactnative/managers/LocalTracksSwitchListenersManager.kt +27 -0
  17. package/android/src/main/java/io/fishjam/reactnative/managers/TracksUpdateListenersManager.kt +21 -0
  18. package/android/src/main/java/io/fishjam/reactnative/utils/PermissionUtils.kt +45 -0
  19. package/build/RNFishjamClientModule.d.ts +16 -10
  20. package/build/RNFishjamClientModule.d.ts.map +1 -1
  21. package/build/RNFishjamClientModule.js.map +1 -1
  22. package/build/common/client.d.ts +3 -3
  23. package/build/common/client.d.ts.map +1 -1
  24. package/build/common/client.js +4 -4
  25. package/build/common/client.js.map +1 -1
  26. package/build/common/metadata.d.ts +3 -3
  27. package/build/common/metadata.d.ts.map +1 -1
  28. package/build/common/metadata.js +4 -4
  29. package/build/common/metadata.js.map +1 -1
  30. package/build/common/webRTC.d.ts +0 -8
  31. package/build/common/webRTC.d.ts.map +1 -1
  32. package/build/common/webRTC.js +0 -9
  33. package/build/common/webRTC.js.map +1 -1
  34. package/build/components/VideoRendererView.d.ts +1 -1
  35. package/build/components/VideoRendererView.js +1 -1
  36. package/build/components/VideoRendererView.js.map +1 -1
  37. package/build/debug/common/webRTC.d.ts +9 -0
  38. package/build/debug/common/webRTC.d.ts.map +1 -0
  39. package/build/debug/common/webRTC.js +11 -0
  40. package/build/debug/common/webRTC.js.map +1 -0
  41. package/build/debug/index.d.ts +4 -0
  42. package/build/debug/index.d.ts.map +1 -0
  43. package/build/debug/index.js +3 -0
  44. package/build/debug/index.js.map +1 -0
  45. package/build/debug/stats/types.d.ts.map +1 -0
  46. package/build/debug/stats/types.js.map +1 -0
  47. package/build/debug/stats/useRTCStatistics.d.ts.map +1 -0
  48. package/build/{stats → debug/stats}/useRTCStatistics.js +1 -1
  49. package/build/debug/stats/useRTCStatistics.js.map +1 -0
  50. package/build/hooks/useAppScreenShare.d.ts +11 -0
  51. package/build/hooks/useAppScreenShare.d.ts.map +1 -0
  52. package/build/hooks/useAppScreenShare.js +54 -0
  53. package/build/hooks/useAppScreenShare.js.map +1 -0
  54. package/build/hooks/useFishjamEvent.d.ts +2 -0
  55. package/build/hooks/useFishjamEvent.d.ts.map +1 -1
  56. package/build/hooks/useFishjamEvent.js +2 -0
  57. package/build/hooks/useFishjamEvent.js.map +1 -1
  58. package/build/hooks/useForegroundService.d.ts +44 -0
  59. package/build/hooks/useForegroundService.d.ts.map +1 -0
  60. package/build/hooks/useForegroundService.js +57 -0
  61. package/build/hooks/useForegroundService.js.map +1 -0
  62. package/build/hooks/useMicrophone.d.ts +1 -1
  63. package/build/hooks/useMicrophone.js +1 -1
  64. package/build/hooks/useMicrophone.js.map +1 -1
  65. package/build/hooks/usePeerStatus.d.ts +19 -0
  66. package/build/hooks/usePeerStatus.d.ts.map +1 -0
  67. package/build/hooks/usePeerStatus.js +18 -0
  68. package/build/hooks/usePeerStatus.js.map +1 -0
  69. package/build/hooks/{useParticipants.d.ts → usePeers.d.ts} +11 -11
  70. package/build/hooks/usePeers.d.ts.map +1 -0
  71. package/build/hooks/usePeers.js +34 -0
  72. package/build/hooks/usePeers.js.map +1 -0
  73. package/build/hooks/useScreenShare.d.ts +1 -0
  74. package/build/hooks/useScreenShare.d.ts.map +1 -1
  75. package/build/hooks/useScreenShare.js +20 -13
  76. package/build/hooks/useScreenShare.js.map +1 -1
  77. package/build/index.d.ts +8 -7
  78. package/build/index.d.ts.map +1 -1
  79. package/build/index.js +5 -5
  80. package/build/index.js.map +1 -1
  81. package/build/types.d.ts +0 -25
  82. package/build/types.d.ts.map +1 -1
  83. package/build/types.js +1 -10
  84. package/build/types.js.map +1 -1
  85. package/debug/package.json +4 -0
  86. package/ios/Events.swift +30 -13
  87. package/ios/RNFishjamClient.podspec +1 -1
  88. package/ios/RNFishjamClient.swift +196 -106
  89. package/ios/RNFishjamClientModule.swift +34 -34
  90. package/ios/VideoPreviewView.swift +26 -12
  91. package/ios/VideoRendererView.swift +5 -14
  92. package/package.json +7 -6
  93. package/plugin/build/withFishjamAndroid.js +1 -1
  94. package/plugin/build/withFishjamIos.js +2 -2
  95. package/build/hooks/useParticipants.d.ts.map +0 -1
  96. package/build/hooks/useParticipants.js +0 -34
  97. package/build/hooks/useParticipants.js.map +0 -1
  98. package/build/stats/types.d.ts.map +0 -1
  99. package/build/stats/types.js.map +0 -1
  100. package/build/stats/useRTCStatistics.d.ts.map +0 -1
  101. package/build/stats/useRTCStatistics.js.map +0 -1
  102. package/build/utils/foregroundService.d.ts +0 -32
  103. package/build/utils/foregroundService.d.ts.map +0 -1
  104. package/build/utils/foregroundService.js +0 -43
  105. package/build/utils/foregroundService.js.map +0 -1
  106. /package/build/{stats → debug/stats}/types.d.ts +0 -0
  107. /package/build/{stats → debug/stats}/types.js +0 -0
  108. /package/build/{stats → debug/stats}/useRTCStatistics.d.ts +0 -0
@@ -11,6 +11,7 @@ class RNFishjamClient: FishjamClientListener {
11
11
  var isMicrophoneOn = false
12
12
  var isCameraOn = false
13
13
  var isScreenShareOn = false
14
+ var isAppScreenShareOn = false
14
15
  var isConnected = false
15
16
 
16
17
  private var isCameraInitialized = false
@@ -28,9 +29,17 @@ class RNFishjamClient: FishjamClientListener {
28
29
  var audioSessionMode: AVAudioSession.Mode = AVAudioSession.Mode.videoChat
29
30
  var errorMessage: String?
30
31
 
32
+ private(set) var peerStatus: PeerStatus = .idle {
33
+ didSet {
34
+ let event = EmitableEvents.PeerStatusChanged
35
+ emit(event: event, data: [event.name: peerStatus.rawValue])
36
+ }
37
+ }
38
+
31
39
  let sendEvent: (_ eventName: String, _ data: [String: Any]) -> Void
32
40
 
33
- static var onTracksUpdateListeners: [OnTrackUpdateListener] = []
41
+ static var tracksUpdateListenersManager = TracksUpdateListenersManager()
42
+ static var localCameraTracksChangedListenersManager = LocalCameraTracksChangedListenersManager()
34
43
 
35
44
  init(sendEvent: @escaping (_ eventName: String, _ data: [String: Any]) -> Void) {
36
45
  self.sendEvent = sendEvent
@@ -103,26 +112,34 @@ class RNFishjamClient: FishjamClientListener {
103
112
  }
104
113
  }()
105
114
  let videoParameters = VideoParameters(
106
- dimensions: flipDimensions ? preset.dimensions.flip() : preset.dimensions,
115
+ dimensions: flipDimensions ? preset.dimensions.flipped : preset.dimensions,
107
116
  maxBandwidth: videoBandwidthLimit,
108
117
  simulcastConfig: simulcastConfig
109
118
  )
110
119
  return videoParameters
111
120
  }
112
121
 
113
- private func getLocalVideoTrack() -> LocalVideoTrack? {
114
- return RNFishjamClient.fishjamClient?.getLocalEndpoint().tracks.first { $0.value is LocalVideoTrack }?.value
115
- as? LocalVideoTrack
122
+ private var localEndpoint: Endpoint? {
123
+ RNFishjamClient.fishjamClient?.getLocalEndpoint()
124
+ }
125
+
126
+ private func getLocalCameraTrack() -> LocalCameraTrack? {
127
+ return localEndpoint?.tracks.compactMap { $0.value as? LocalCameraTrack }.first
128
+
116
129
  }
117
130
 
118
131
  private func getLocalAudioTrack() -> LocalAudioTrack? {
119
- return RNFishjamClient.fishjamClient?.getLocalEndpoint().tracks.first { $0.value is LocalAudioTrack }?.value
120
- as? LocalAudioTrack
132
+ return localEndpoint?.tracks.compactMap { $0.value as? LocalAudioTrack }.first
133
+
121
134
  }
122
135
 
123
- private func getLocalScreenShareTrack() -> LocalScreenShareTrack? {
124
- return RNFishjamClient.fishjamClient?.getLocalEndpoint().tracks.first { $0.value is LocalScreenShareTrack }?
125
- .value as? LocalScreenShareTrack
136
+ private func getLocalScreenBroadcastTrack() -> LocalBroadcastScreenShareTrack? {
137
+ return localEndpoint?.tracks.compactMap { $0.value as? LocalBroadcastScreenShareTrack }.first
138
+
139
+ }
140
+
141
+ private func getLocalScreenAppTrack() -> LocalAppScreenShareTrack? {
142
+ return localEndpoint?.tracks.compactMap { $0.value as? LocalAppScreenShareTrack }.first
126
143
  }
127
144
 
128
145
  private func ensureCreated() throws {
@@ -143,8 +160,8 @@ class RNFishjamClient: FishjamClientListener {
143
160
  }
144
161
  }
145
162
 
146
- private func ensureVideoTrack() throws {
147
- if getLocalVideoTrack() == nil {
163
+ private func ensureCameraTrack() throws {
164
+ if getLocalCameraTrack() == nil {
148
165
  throw Exception(
149
166
  name: "E_NO_LOCAL_VIDEO_TRACK",
150
167
  description: "No local video track. Make sure to call connect() first!")
@@ -159,11 +176,19 @@ class RNFishjamClient: FishjamClientListener {
159
176
  }
160
177
  }
161
178
 
162
- private func ensureScreenShareTrack() throws {
163
- if getLocalScreenShareTrack() == nil {
179
+ private func ensureScreenBroadcastTrack() throws {
180
+ if getLocalScreenBroadcastTrack() == nil {
181
+ throw Exception(
182
+ name: "E_NO_LOCAL_SCREENSHARE_TRACK",
183
+ description: "No local screen broadcast track. Make sure to toggle screen broadcast on first!")
184
+ }
185
+ }
186
+
187
+ private func ensureScreenAppTrack() throws {
188
+ if getLocalScreenAppTrack() == nil {
164
189
  throw Exception(
165
190
  name: "E_NO_LOCAL_SCREENSHARE_TRACK",
166
- description: "No local screen share track. Make sure to toggle screen share on first!")
191
+ description: "No local screen app track. Make sure to toggle screen app on first!")
167
192
  }
168
193
  }
169
194
 
@@ -172,18 +197,16 @@ class RNFishjamClient: FishjamClientListener {
172
197
  connectPromise.reject("E_MEMBRANE_CONNECT", "Failed to connect: socket error")
173
198
  }
174
199
  connectPromise = nil
175
- }
176
-
177
- func onAuthSuccess() {
178
- join()
200
+ peerStatus = .error
179
201
  }
180
202
 
181
203
  func joinRoom(
182
- url: String, participantToken: String, participantMetadata: [String: Any], config: ConnectConfig,
204
+ url: String, peerToken: String, peerMetadata: [String: Any], config: ConnectConfig,
183
205
  promise: Promise
184
206
  ) {
207
+ peerStatus = .connecting
185
208
  connectPromise = promise
186
- localUserMetadata = participantMetadata.toMetadata()
209
+ localUserMetadata = ["server": [:], "peer": peerMetadata].toMetadata()
187
210
 
188
211
  let reconnectConfig = FishjamCloudClient.ReconnectConfig(
189
212
  maxAttempts: config.reconnectConfig.maxAttempts, initialDelayMs: config.reconnectConfig.initialDelayMs,
@@ -191,16 +214,12 @@ class RNFishjamClient: FishjamClientListener {
191
214
 
192
215
  RNFishjamClient.fishjamClient?.connect(
193
216
  config: FishjamCloudClient.ConnectConfig(
194
- websocketUrl: url, token: participantToken, participantMetadata: .init(participantMetadata),
217
+ websocketUrl: url, token: peerToken, peerMetadata: localUserMetadata,
195
218
  reconnectConfig: reconnectConfig
196
219
  ))
197
220
 
198
221
  }
199
222
 
200
- func join() {
201
- RNFishjamClient.fishjamClient?.join(peerMetadata: localUserMetadata)
202
- }
203
-
204
223
  func leaveRoom() {
205
224
  if isScreenShareOn {
206
225
  let screenShareExtensionBundleId =
@@ -212,12 +231,15 @@ class RNFishjamClient: FishjamClientListener {
212
231
  isMicrophoneOn = false
213
232
  isCameraOn = false
214
233
  isScreenShareOn = false
234
+ isAppScreenShareOn = false
215
235
  isConnected = false
216
236
  isCameraInitialized = false
217
- RNFishjamClient.fishjamClient?.leave()
237
+ RNFishjamClient.fishjamClient?.leave { [weak self] in
238
+ self?.emitEndpoints()
239
+ }
218
240
  }
219
241
 
220
- func startCamera(config: CameraConfig) throws {
242
+ func startCamera(config: CameraConfig) async throws {
221
243
  try ensureCreated()
222
244
 
223
245
  guard !isCameraInitialized else {
@@ -225,13 +247,18 @@ class RNFishjamClient: FishjamClientListener {
225
247
  return
226
248
  }
227
249
 
250
+ guard await PermissionUtils.requestCameraPermission() else {
251
+ emit(warning: "Camera permission not granted.")
252
+ return
253
+ }
254
+
228
255
  let cameraTrack = try createCameraTrack(config: config)
229
256
  setCameraTrackState(cameraTrack, enabled: config.cameraEnabled)
230
257
  emitEndpoints()
231
258
  isCameraInitialized = true
232
259
  }
233
260
 
234
- private func createCameraTrack(config: CameraConfig) throws -> LocalVideoTrack {
261
+ private func createCameraTrack(config: CameraConfig) throws -> LocalCameraTrack {
235
262
  try ensureCreated()
236
263
  let videoParameters = try getVideoParametersFromOptions(connectionOptions: config)
237
264
  videoSimulcastConfig = try getSimulcastConfigFromOptions(simulcastConfig: config.simulcastConfig)
@@ -242,43 +269,47 @@ class RNFishjamClient: FishjamClientListener {
242
269
  )
243
270
  }
244
271
 
245
- private func setCameraTrackState(_ cameraTrack: LocalVideoTrack, enabled: Bool) {
272
+ private func setCameraTrackState(_ cameraTrack: LocalCameraTrack, enabled: Bool) {
246
273
  cameraTrack.enabled = enabled
247
274
  isCameraOn = enabled
248
- let eventName = EmitableEvents.IsCameraOn
249
- let isCameraEnabledMap = [eventName: enabled]
250
- emitEvent(name: eventName, data: isCameraEnabledMap)
275
+ let event = EmitableEvents.IsCameraOn
276
+ let isCameraEnabledMap = [event.name: enabled]
277
+ emit(event: event, data: isCameraEnabledMap)
278
+ RNFishjamClient.localCameraTracksChangedListenersManager.notifyListeners()
251
279
  }
252
280
 
253
281
  func toggleCamera() throws -> Bool {
254
- try ensureVideoTrack()
255
- setCameraTrackState(getLocalVideoTrack()!, enabled: !isCameraOn)
282
+ try ensureCameraTrack()
283
+ setCameraTrackState(getLocalCameraTrack()!, enabled: !isCameraOn)
256
284
  return isCameraOn
257
285
  }
258
286
 
259
287
  func flipCamera() throws {
260
- try ensureVideoTrack()
261
- getLocalVideoTrack()?.flipCamera()
288
+ try ensureCameraTrack()
289
+ getLocalCameraTrack()?.flipCamera()
262
290
  }
263
291
 
264
292
  func switchCamera(cameraId: String) throws {
265
- try ensureVideoTrack()
266
- getLocalVideoTrack()?.switchCamera(deviceId: cameraId)
293
+ try ensureCameraTrack()
294
+ getLocalCameraTrack()?.switchCamera(deviceId: cameraId)
267
295
 
268
296
  }
269
297
 
270
- func toggleMicrophone() throws -> Bool {
298
+ func toggleMicrophone() async throws -> Bool {
271
299
  if let audioTrack = getLocalAudioTrack() {
272
300
  setMicrophoneTrackState(audioTrack, enabled: !isMicrophoneOn)
273
301
  } else {
274
- try startMicrophone()
302
+ try await startMicrophone()
275
303
  }
276
304
  return isMicrophoneOn
277
305
  }
278
306
 
279
- func startMicrophone() throws {
280
- let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(
281
- metadata: Metadata())
307
+ func startMicrophone() async throws {
308
+ guard await PermissionUtils.requestMicrophonePermission() else {
309
+ emit(warning: "Microphone permission not granted.")
310
+ return
311
+ }
312
+ let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(metadata: Metadata())
282
313
  setAudioSessionMode()
283
314
  setMicrophoneTrackState(microphoneTrack, enabled: true)
284
315
  emitEndpoints()
@@ -287,10 +318,9 @@ class RNFishjamClient: FishjamClientListener {
287
318
  private func setMicrophoneTrackState(_ microphoneTrack: LocalAudioTrack, enabled: Bool) {
288
319
  microphoneTrack.enabled = enabled
289
320
  isMicrophoneOn = enabled
290
- let eventName = EmitableEvents.IsMicrophoneOn
291
- let isMicrophoneOnMap = [eventName: enabled]
292
- print(isMicrophoneOnMap)
293
- emitEvent(name: eventName, data: isMicrophoneOnMap)
321
+ let event = EmitableEvents.IsMicrophoneOn
322
+ let isMicrophoneOnMap = [event.name: enabled]
323
+ emit(event: event, data: isMicrophoneOnMap)
294
324
  }
295
325
 
296
326
  func setAudioSessionMode() {
@@ -314,6 +344,10 @@ class RNFishjamClient: FishjamClientListener {
314
344
  func toggleScreenShare(screenShareOptions: ScreenShareOptions) throws {
315
345
  try ensureCreated()
316
346
  try ensureConnected()
347
+ guard isAppScreenShareOn == false else {
348
+ emit(warning: "Screensharing screen not available during screensharing app.")
349
+ return
350
+ }
317
351
  guard let screenShareExtensionBundleId = Bundle.main.infoDictionary?["ScreenShareExtensionBundleId"] as? String
318
352
  else {
319
353
  throw Exception(
@@ -343,16 +377,20 @@ class RNFishjamClient: FishjamClientListener {
343
377
  maxBandwidth: screenShareOptions.maxBandwidth)
344
378
  let screenShareMetadata = screenShareOptions.screenShareMetadata.toMetadata()
345
379
  let videoParameters = getScreenShareVideoParameters(options: screenShareOptions)
346
- RNFishjamClient.fishjamClient!.createScreenShareTrack(
380
+ RNFishjamClient.fishjamClient!.prepareForScreenBroadcast(
347
381
  appGroup: appGroupName,
348
382
  videoParameters: videoParameters,
349
383
  metadata: screenShareMetadata,
350
- onStart: { [weak self] screenShareTrack in
351
- guard let self = self else { return }
352
-
384
+ canStart: {
385
+ if self.isAppScreenShareOn {
386
+ self.emit(warning: "Screensharing screen not available during screensharing app.")
387
+ }
388
+ return !self.isAppScreenShareOn
389
+ },
390
+ onStart: { [weak self] in
391
+ guard let self else { return }
353
392
  do {
354
- //not sure should it be here, or outside or where?
355
- try setScreenShareTrackState(screenShareTrack, enabled: true)
393
+ try setScreenShareTrackState(enabled: true)
356
394
  } catch {
357
395
  os_log(
358
396
  "Error starting screen share: %{public}s", log: log, type: .error,
@@ -361,11 +399,10 @@ class RNFishjamClient: FishjamClientListener {
361
399
  }
362
400
 
363
401
  },
364
- onStop: { [weak self] screenShareTrack in
365
- guard let self = self else { return }
402
+ onStop: { [weak self] in
403
+ guard let self else { return }
366
404
  do {
367
- //not sure should it be here, or outside or where?
368
- try setScreenShareTrackState(screenShareTrack, enabled: false)
405
+ try setScreenShareTrackState(enabled: false)
369
406
  } catch {
370
407
  os_log(
371
408
  "Error stopping screen share: %{public}s", log: log, type: .error,
@@ -379,13 +416,55 @@ class RNFishjamClient: FishjamClientListener {
379
416
  }
380
417
  }
381
418
 
382
- private func setScreenShareTrackState(_ screenShareTrack: LocalScreenShareTrack, enabled: Bool) throws {
383
- //was not present before, test and maybe delete?
384
- screenShareTrack.enabled = enabled
419
+ private func setScreenShareTrackState(enabled: Bool) throws {
385
420
  isScreenShareOn = enabled
386
- let eventName = EmitableEvents.IsScreenShareOn
387
- let isScreenShareEnabled = [eventName: enabled]
388
- emitEvent(name: eventName, data: isScreenShareEnabled)
421
+ let event = EmitableEvents.IsScreenShareOn
422
+ let isScreenShareEnabled = [event.name: enabled]
423
+ emit(event: event, data: isScreenShareEnabled)
424
+ }
425
+
426
+ func startScreenAppShare(screenShareOptions: ScreenShareOptions) throws {
427
+ try ensureCreated()
428
+ try ensureConnected()
429
+
430
+ let simulcastConfig = try getSimulcastConfigFromOptions(simulcastConfig: screenShareOptions.simulcastConfig)
431
+
432
+ screenShareSimulcastConfig = simulcastConfig
433
+ screenShareMaxBandwidth = getMaxBandwidthFromOptions(maxBandwidth: screenShareOptions.maxBandwidth)
434
+ let metadata = screenShareOptions.screenShareMetadata.toMetadata()
435
+ let videoParameters = getScreenShareVideoParameters(options: screenShareOptions)
436
+ let screenAppTrack = RNFishjamClient.fishjamClient!.createScreenAppTrack(
437
+ videoParameters: videoParameters, metadata: metadata)
438
+ setScreenAppTrackState(screenAppTrack, enabled: true)
439
+ emitEndpoints()
440
+ }
441
+
442
+ func stopAppScreenShare() throws {
443
+ try ensureScreenAppTrack()
444
+ let track = getLocalScreenAppTrack()!
445
+ setScreenAppTrackState(track, enabled: false)
446
+ RNFishjamClient.fishjamClient?.removeTrack(trackId: track.id)
447
+ emitEndpoints()
448
+ }
449
+
450
+ func toggleAppScreenShare(screenShareOptions: ScreenShareOptions) throws {
451
+ guard isScreenShareOn == false else {
452
+ emit(warning: "App screensharing not available during screensharing.")
453
+ return
454
+ }
455
+ if getLocalScreenAppTrack() != nil {
456
+ try stopAppScreenShare()
457
+ } else {
458
+ try startScreenAppShare(screenShareOptions: screenShareOptions)
459
+ }
460
+ }
461
+
462
+ private func setScreenAppTrackState(_ track: LocalAppScreenShareTrack, enabled: Bool) {
463
+ track.enabled = enabled
464
+ isAppScreenShareOn = enabled
465
+ let event = EmitableEvents.IsAppScreenShareOn
466
+ let eventMap = [event.name: enabled]
467
+ emit(event: event, data: eventMap)
389
468
  }
390
469
 
391
470
  //returns local endpoint and remote endpoints
@@ -402,7 +481,7 @@ class RNFishjamClient: FishjamClientListener {
402
481
  "id": endpoint.id,
403
482
  "isLocal": endpoint.id == RNFishjamClient.fishjamClient!.getLocalEndpoint().id,
404
483
  "type": endpoint.type,
405
- "metadata": endpoint.metadata,
484
+ "metadata": endpoint.metadata.toDict(),
406
485
  "tracks": endpoint.tracks.values.compactMap { track -> [String: Any?]? in
407
486
  switch track {
408
487
  case let track as RemoteVideoTrack:
@@ -422,14 +501,21 @@ class RNFishjamClient: FishjamClientListener {
422
501
  "vadStatus": track.vadStatus.rawValue,
423
502
  ]
424
503
 
425
- case let track as LocalVideoTrack:
504
+ case let track as LocalCameraTrack:
426
505
  return [
427
506
  "id": track.id,
428
507
  "type": "Video",
429
508
  "metadata": track.metadata.toDict(),
430
509
  ]
431
510
 
432
- case let track as LocalScreenShareTrack:
511
+ case let track as LocalBroadcastScreenShareTrack:
512
+ return [
513
+ "id": track.id,
514
+ "type": "Video",
515
+ "metadata": track.metadata.toDict(),
516
+ ]
517
+
518
+ case let track as LocalAppScreenShareTrack:
433
519
  return [
434
520
  "id": track.id,
435
521
  "type": "Video",
@@ -452,7 +538,7 @@ class RNFishjamClient: FishjamClientListener {
452
538
  }
453
539
 
454
540
  func getCaptureDevices() -> [[String: Any]] {
455
- let devices = LocalVideoTrack.getCaptureDevices()
541
+ let devices = LocalCameraTrack.getCaptureDevices()
456
542
  return devices.map { device -> [String: Any] in
457
543
  let facingDirection =
458
544
  switch device.position {
@@ -479,8 +565,8 @@ class RNFishjamClient: FishjamClientListener {
479
565
  }
480
566
 
481
567
  func updateLocalVideoTrackMetadata(metadata: [String: Any]) throws {
482
- try ensureVideoTrack()
483
- if let track = getLocalVideoTrack() {
568
+ try ensureCameraTrack()
569
+ if let track = getLocalCameraTrack() {
484
570
  updateTrackMetadata(trackId: track.id, metadata: metadata)
485
571
  }
486
572
  }
@@ -493,8 +579,8 @@ class RNFishjamClient: FishjamClientListener {
493
579
  }
494
580
 
495
581
  func updateLocalScreenShareTrackMetadata(metadata: [String: Any]) throws {
496
- try ensureScreenShareTrack()
497
- if let track = getLocalScreenShareTrack() {
582
+ try ensureScreenBroadcastTrack()
583
+ if let track = getLocalScreenBroadcastTrack() {
498
584
  updateTrackMetadata(trackId: track.id, metadata: metadata)
499
585
  }
500
586
  }
@@ -519,8 +605,8 @@ class RNFishjamClient: FishjamClientListener {
519
605
  }
520
606
 
521
607
  func toggleScreenShareTrackEncoding(encoding: String) throws -> [String: Any] {
522
- try ensureScreenShareTrack()
523
- if let track = getLocalScreenShareTrack() {
608
+ try ensureScreenBroadcastTrack()
609
+ if let track = getLocalScreenBroadcastTrack() {
524
610
  screenShareSimulcastConfig = try toggleTrackEncoding(
525
611
  encoding: encoding, trackId: track.id, simulcastConfig: screenShareSimulcastConfig)
526
612
  }
@@ -528,15 +614,15 @@ class RNFishjamClient: FishjamClientListener {
528
614
  }
529
615
 
530
616
  func setScreenShareTrackBandwidth(bandwidth: Int) throws {
531
- try ensureScreenShareTrack()
532
- if let track = getLocalScreenShareTrack() {
617
+ try ensureScreenBroadcastTrack()
618
+ if let track = getLocalScreenBroadcastTrack() {
533
619
  RNFishjamClient.fishjamClient?.setTrackBandwidth(trackId: track.id, bandwidthLimit: bandwidth)
534
620
  }
535
621
  }
536
622
 
537
623
  func setScreenShareTrackEncodingBandwidth(encoding: String, bandwidth: Int) throws {
538
- try ensureScreenShareTrack()
539
- if let track = getLocalScreenShareTrack() {
624
+ try ensureScreenBroadcastTrack()
625
+ if let track = getLocalScreenBroadcastTrack() {
540
626
  RNFishjamClient.fishjamClient?.setEncodingBandwidth(
541
627
  trackId: track.id, encoding: encoding, bandwidthLimit: bandwidth)
542
628
  }
@@ -549,30 +635,30 @@ class RNFishjamClient: FishjamClientListener {
549
635
  }
550
636
 
551
637
  func toggleVideoTrackEncoding(encoding: String) throws -> [String: Any] {
552
- try ensureVideoTrack()
638
+ try ensureCameraTrack()
553
639
  try ensureConnected()
554
640
 
555
- let track = getLocalVideoTrack()!
641
+ let track = getLocalCameraTrack()!
556
642
  videoSimulcastConfig = try toggleTrackEncoding(
557
643
  encoding: encoding, trackId: track.id, simulcastConfig: videoSimulcastConfig)
558
644
 
559
- let eventName = EmitableEvents.SimulcastConfigUpdate
645
+ let event = EmitableEvents.SimulcastConfigUpdate
560
646
  let simulcastConfigAsRNMap = getSimulcastConfigAsRNMap(videoSimulcastConfig)
561
- emitEvent(name: eventName, data: simulcastConfigAsRNMap)
647
+ emit(event: event, data: simulcastConfigAsRNMap)
562
648
 
563
649
  return simulcastConfigAsRNMap
564
650
  }
565
651
 
566
652
  func setVideoTrackEncodingBandwidth(encoding: String, bandwidth: Int) throws {
567
- try ensureVideoTrack()
568
- let track = getLocalVideoTrack()!
653
+ try ensureCameraTrack()
654
+ let track = getLocalCameraTrack()!
569
655
  RNFishjamClient.fishjamClient?.setEncodingBandwidth(
570
656
  trackId: track.id, encoding: encoding, bandwidthLimit: bandwidth)
571
657
  }
572
658
 
573
659
  func setVideoTrackBandwidth(bandwidth: Int) throws {
574
- try ensureVideoTrack()
575
- let track = getLocalVideoTrack()!
660
+ try ensureCameraTrack()
661
+ let track = getLocalCameraTrack()!
576
662
  RNFishjamClient.fishjamClient?.setTrackBandwidth(trackId: track.id, bandwidthLimit: bandwidth)
577
663
  }
578
664
 
@@ -666,25 +752,27 @@ class RNFishjamClient: FishjamClientListener {
666
752
  preset = VideoParameters.presetScreenShareHD15
667
753
  }
668
754
  return VideoParameters(
669
- dimensions: preset.dimensions.flip(),
755
+ dimensions: preset.dimensions.flipped,
670
756
  maxBandwidth: screenShareMaxBandwidth,
671
757
  maxFps: preset.maxFps,
672
758
  simulcastConfig: screenShareSimulcastConfig
673
759
  )
674
760
  }
675
761
 
676
- func emitEvent(name: String, data: [String: Any]) {
677
- sendEvent(name, data)
762
+ func emit(event: EmitableEvents, data: [String: Any] = [:]) {
763
+ DispatchQueue.main.async { [weak self] in
764
+ self?.sendEvent(event.name, data)
765
+ }
678
766
  }
679
767
 
680
768
  func emit(warning: String) {
681
- emitEvent(name: EmitableEvents.Warning, data: ["message": warning])
769
+ emit(event: .Warning, data: ["message": warning])
682
770
  }
683
771
 
684
772
  func emitEndpoints() {
685
- let eventName = EmitableEvents.PeersUpdate
686
- let EndpointsUpdateMap = [eventName: (try? getPeers()) ?? []]
687
- emitEvent(name: eventName, data: EndpointsUpdateMap)
773
+ let event = EmitableEvents.PeersUpdate
774
+ let EndpointsUpdateMap = [event.name: (try? getPeers()) ?? []]
775
+ emit(event: event, data: EndpointsUpdateMap)
688
776
  }
689
777
 
690
778
  func onJoined(peerID: String, peersInRoom: [String: Endpoint]) {
@@ -692,6 +780,7 @@ class RNFishjamClient: FishjamClientListener {
692
780
  connectPromise?.resolve(nil)
693
781
  connectPromise = nil
694
782
  emitEndpoints()
783
+ peerStatus = .connected
695
784
  }
696
785
 
697
786
  func onJoinError(metadata: Any) {
@@ -712,9 +801,7 @@ class RNFishjamClient: FishjamClientListener {
712
801
  }
713
802
  }
714
803
 
715
- RNFishjamClient.onTracksUpdateListeners.forEach {
716
- $0.onTrackUpdate()
717
- }
804
+ RNFishjamClient.tracksUpdateListenersManager.notifyListeners()
718
805
 
719
806
  emitEndpoints()
720
807
  }
@@ -753,6 +840,7 @@ class RNFishjamClient: FishjamClientListener {
753
840
  "E_MEMBRANE_CONNECT", "Failed to connect: socket close, code: \(code), reason: \(reason)")
754
841
  }
755
842
  connectPromise = nil
843
+ peerStatus = .error
756
844
  }
757
845
 
758
846
  func onSocketError() {
@@ -764,7 +852,9 @@ class RNFishjamClient: FishjamClientListener {
764
852
 
765
853
  func onSocketOpen() {}
766
854
 
767
- func onDisconnected() {}
855
+ func onDisconnected() {
856
+ peerStatus = .idle
857
+ }
768
858
 
769
859
  func getSimulcastConfigAsRNMap(_ simulcastConfig: SimulcastConfig) -> [String: Any] {
770
860
  return [
@@ -826,11 +916,11 @@ class RNFishjamClient: FishjamClientListener {
826
916
  default:
827
917
  deviceTypeString = deviceType.rawValue
828
918
  }
829
- let eventName = EmitableEvents.AudioDeviceUpdate
830
- emitEvent(
831
- name: eventName,
919
+ let event = EmitableEvents.AudioDeviceUpdate
920
+ emit(
921
+ event: event,
832
922
  data: [
833
- eventName: [
923
+ event.name: [
834
924
  "selectedDevice": ["name": output.portName, "type": deviceTypeString],
835
925
  "availableDevices": [],
836
926
  ]
@@ -838,20 +928,20 @@ class RNFishjamClient: FishjamClientListener {
838
928
  }
839
929
 
840
930
  func onBandwidthEstimationChanged(estimation: Int) {
841
- let eventName = EmitableEvents.BandwidthEstimation
842
- emitEvent(name: eventName, data: [eventName: estimation])
931
+ let event = EmitableEvents.BandwidthEstimation
932
+ emit(event: event, data: [event.name: estimation])
843
933
  }
844
934
 
845
935
  func onReconnectionStarted() {
846
- emitEvent(name: EmitableEvents.ReconnectionStarted, data: [:])
936
+ emit(event: .ReconnectionStarted)
847
937
  }
848
938
 
849
939
  func onReconnected() {
850
- emitEvent(name: EmitableEvents.Reconnected, data: [:])
940
+ emit(event: .Reconnected)
851
941
  }
852
942
 
853
943
  func onReconnectionRetriesLimitReached() {
854
- emitEvent(name: EmitableEvents.ReconnectionRetriesLimitReached, data: [:])
944
+ emit(event: .ReconnectionRetriesLimitReached)
855
945
  }
856
946
 
857
947
  }