@fishjam-cloud/react-native-client 0.4.1 → 0.6.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 (127) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +104 -20
  3. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +83 -99
  4. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +21 -30
  5. package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +6 -2
  6. package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +41 -3
  7. package/android/src/main/java/io/fishjam/reactnative/extensions/CaptureDevice.kt +17 -0
  8. package/android/src/main/java/io/fishjam/reactnative/foregroundService/FishjamForegroundService.kt +10 -4
  9. package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceManager.kt +41 -70
  10. package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceState.kt +46 -0
  11. package/android/src/main/java/io/fishjam/reactnative/managers/ListenerManager.kt +22 -0
  12. package/android/src/main/java/io/fishjam/reactnative/managers/LocalCameraTracksChangedListenersManager.kt +2 -15
  13. package/android/src/main/java/io/fishjam/reactnative/managers/LocalTracksSwitchListenersManager.kt +1 -11
  14. package/android/src/main/java/io/fishjam/reactnative/managers/TracksUpdateListenersManager.kt +1 -15
  15. package/build/RNFishjamClientModule.d.ts +28 -12
  16. package/build/RNFishjamClientModule.d.ts.map +1 -1
  17. package/build/RNFishjamClientModule.js +19 -4
  18. package/build/RNFishjamClientModule.js.map +1 -1
  19. package/build/common/client.d.ts +0 -4
  20. package/build/common/client.d.ts.map +1 -1
  21. package/build/common/client.js +0 -4
  22. package/build/common/client.js.map +1 -1
  23. package/build/common/metadata.d.ts +1 -1
  24. package/build/common/metadata.js +1 -1
  25. package/build/common/metadata.js.map +1 -1
  26. package/build/common/webRTC.d.ts +2 -1
  27. package/build/common/webRTC.d.ts.map +1 -1
  28. package/build/common/webRTC.js.map +1 -1
  29. package/build/components/FishjamRoom/GridTrackItem.d.ts +11 -0
  30. package/build/components/FishjamRoom/GridTrackItem.d.ts.map +1 -0
  31. package/build/components/FishjamRoom/GridTrackItem.js +56 -0
  32. package/build/components/FishjamRoom/GridTrackItem.js.map +1 -0
  33. package/build/components/FishjamRoom/VideosGrid.d.ts +3 -0
  34. package/build/components/FishjamRoom/VideosGrid.d.ts.map +1 -0
  35. package/build/components/FishjamRoom/VideosGrid.js +20 -0
  36. package/build/components/FishjamRoom/VideosGrid.js.map +1 -0
  37. package/build/components/FishjamRoom/index.d.ts +6 -0
  38. package/build/components/FishjamRoom/index.d.ts.map +1 -0
  39. package/build/components/FishjamRoom/index.js +29 -0
  40. package/build/components/FishjamRoom/index.js.map +1 -0
  41. package/build/components/FishjamRoom/parsePeersToTracks.d.ts +4 -0
  42. package/build/components/FishjamRoom/parsePeersToTracks.d.ts.map +1 -0
  43. package/build/components/FishjamRoom/parsePeersToTracks.js +34 -0
  44. package/build/components/FishjamRoom/parsePeersToTracks.js.map +1 -0
  45. package/build/components/VideoRendererView.d.ts +6 -1
  46. package/build/components/VideoRendererView.d.ts.map +1 -1
  47. package/build/components/VideoRendererView.js.map +1 -1
  48. package/build/debug/stats/useRTCStatistics.d.ts.map +1 -1
  49. package/build/debug/stats/useRTCStatistics.js +13 -13
  50. package/build/debug/stats/useRTCStatistics.js.map +1 -1
  51. package/build/hooks/internal/useFishjamEvent.d.ts +3 -0
  52. package/build/hooks/internal/useFishjamEvent.d.ts.map +1 -0
  53. package/build/hooks/internal/useFishjamEvent.js +11 -0
  54. package/build/hooks/internal/useFishjamEvent.js.map +1 -0
  55. package/build/hooks/internal/useFishjamEventState.d.ts +3 -0
  56. package/build/hooks/internal/useFishjamEventState.d.ts.map +1 -0
  57. package/build/hooks/internal/useFishjamEventState.js +18 -0
  58. package/build/hooks/internal/useFishjamEventState.js.map +1 -0
  59. package/build/hooks/useAppScreenShare.d.ts.map +1 -1
  60. package/build/hooks/useAppScreenShare.js +6 -8
  61. package/build/hooks/useAppScreenShare.js.map +1 -1
  62. package/build/hooks/useAudioSettings.d.ts.map +1 -1
  63. package/build/hooks/useAudioSettings.js +8 -11
  64. package/build/hooks/useAudioSettings.js.map +1 -1
  65. package/build/hooks/useBandwidthEstimation.d.ts.map +1 -1
  66. package/build/hooks/useBandwidthEstimation.js +3 -4
  67. package/build/hooks/useBandwidthEstimation.js.map +1 -1
  68. package/build/hooks/useCamera.d.ts +6 -2
  69. package/build/hooks/useCamera.d.ts.map +1 -1
  70. package/build/hooks/useCamera.js +19 -23
  71. package/build/hooks/useCamera.js.map +1 -1
  72. package/build/hooks/useConnection.d.ts +42 -0
  73. package/build/hooks/useConnection.d.ts.map +1 -0
  74. package/build/hooks/useConnection.js +33 -0
  75. package/build/hooks/useConnection.js.map +1 -0
  76. package/build/hooks/useForegroundService.d.ts +12 -20
  77. package/build/hooks/useForegroundService.d.ts.map +1 -1
  78. package/build/hooks/useForegroundService.js +14 -4
  79. package/build/hooks/useForegroundService.js.map +1 -1
  80. package/build/hooks/useMicrophone.d.ts.map +1 -1
  81. package/build/hooks/useMicrophone.js +5 -11
  82. package/build/hooks/useMicrophone.js.map +1 -1
  83. package/build/hooks/usePeerStatus.d.ts +2 -3
  84. package/build/hooks/usePeerStatus.d.ts.map +1 -1
  85. package/build/hooks/usePeerStatus.js +4 -10
  86. package/build/hooks/usePeerStatus.js.map +1 -1
  87. package/build/hooks/usePeers.d.ts +50 -11
  88. package/build/hooks/usePeers.d.ts.map +1 -1
  89. package/build/hooks/usePeers.js +42 -18
  90. package/build/hooks/usePeers.js.map +1 -1
  91. package/build/hooks/useReconnection.d.ts +1 -1
  92. package/build/hooks/useReconnection.d.ts.map +1 -1
  93. package/build/hooks/useReconnection.js +4 -10
  94. package/build/hooks/useReconnection.js.map +1 -1
  95. package/build/hooks/useScreenShare.d.ts.map +1 -1
  96. package/build/hooks/useScreenShare.js +11 -16
  97. package/build/hooks/useScreenShare.js.map +1 -1
  98. package/build/hooks/useUpdatePeerMetadata.d.ts +15 -0
  99. package/build/hooks/useUpdatePeerMetadata.d.ts.map +1 -0
  100. package/build/hooks/useUpdatePeerMetadata.js +21 -0
  101. package/build/hooks/useUpdatePeerMetadata.js.map +1 -0
  102. package/build/index.d.ts +24 -16
  103. package/build/index.d.ts.map +1 -1
  104. package/build/index.js +18 -6
  105. package/build/index.js.map +1 -1
  106. package/build/types.d.ts +1 -1
  107. package/build/types.d.ts.map +1 -1
  108. package/build/types.js.map +1 -1
  109. package/build/utils/errorListener.d.ts.map +1 -1
  110. package/build/utils/errorListener.js +3 -4
  111. package/build/utils/errorListener.js.map +1 -1
  112. package/ios/Events.swift +94 -19
  113. package/ios/RNFishjamClient.podspec +1 -1
  114. package/ios/RNFishjamClient.swift +84 -114
  115. package/ios/RNFishjamClientModule.swift +14 -10
  116. package/ios/Utils.swift +0 -20
  117. package/ios/VideoPreviewView.swift +13 -13
  118. package/ios/VideoRendererView.swift +28 -25
  119. package/ios/VideoRendererViewModule.swift +8 -4
  120. package/ios/extensions/AVCaptureDevice.swift +20 -0
  121. package/package.json +11 -14
  122. package/plugin/build/withFishjamAndroid.js +18 -20
  123. package/plugin/build/withFishjamIos.js +99 -103
  124. package/build/hooks/useFishjamEvent.d.ts +0 -18
  125. package/build/hooks/useFishjamEvent.d.ts.map +0 -1
  126. package/build/hooks/useFishjamEvent.js +0 -27
  127. package/build/hooks/useFishjamEvent.js.map +0 -1
@@ -1,12 +1,11 @@
1
- import { ReceivableEvents } from '../hooks/useFishjamEvent';
2
- import { nativeModuleEventEmitter } from '../RNFishjamClientModule';
1
+ import nativeModule, { ReceivableEvents } from '../RNFishjamClientModule';
3
2
  export const initializeWarningListener = () => {
4
3
  if (!__DEV__) {
5
4
  return;
6
5
  }
7
6
  try {
8
- nativeModuleEventEmitter.addListener(ReceivableEvents.Warning, ({ message }) => {
9
- console.warn(message);
7
+ nativeModule.addListener(ReceivableEvents.Warning, (event) => {
8
+ console.warn(event[ReceivableEvents.Warning]);
10
9
  });
11
10
  }
12
11
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"errorListener.js","sourceRoot":"","sources":["../../src/utils/errorListener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,EAAE;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,wBAAwB,CAAC,WAAW,CAClC,gBAAgB,CAAC,OAAO,EACxB,CAAC,EAAE,OAAO,EAAuB,EAAE,EAAE;YACnC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { ReceivableEvents } from '../hooks/useFishjamEvent';\nimport { nativeModuleEventEmitter } from '../RNFishjamClientModule';\n\nexport const initializeWarningListener = () => {\n if (!__DEV__) {\n return;\n }\n try {\n nativeModuleEventEmitter.addListener(\n ReceivableEvents.Warning,\n ({ message }: { message: string }) => {\n console.warn(message);\n },\n );\n } catch (error) {\n console.error(`Failed to start warning listener: ${error?.message ?? ''}`);\n }\n};\n"]}
1
+ {"version":3,"file":"errorListener.js","sourceRoot":"","sources":["../../src/utils/errorListener.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,EAAE,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE1E,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,EAAE;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,YAAY,CAAC,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3D,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,KAAK,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC,CAAC","sourcesContent":["import nativeModule, { ReceivableEvents } from '../RNFishjamClientModule';\n\nexport const initializeWarningListener = () => {\n if (!__DEV__) {\n return;\n }\n try {\n nativeModule.addListener(ReceivableEvents.Warning, (event) => {\n console.warn(event[ReceivableEvents.Warning]);\n });\n } catch (error) {\n console.error(`Failed to start warning listener: ${error?.message ?? ''}`);\n }\n};\n"]}
package/ios/Events.swift CHANGED
@@ -1,3 +1,6 @@
1
+ import AVKit
2
+ import FishjamCloudClient
3
+
1
4
  enum PeerStatus: String {
2
5
  case connecting
3
6
  case connected
@@ -5,27 +8,99 @@ enum PeerStatus: String {
5
8
  case idle
6
9
  }
7
10
 
8
- enum EmitableEvents: String, CaseIterable {
9
- case IsCameraOn
10
- case IsMicrophoneOn
11
- case IsScreenShareOn
12
- case IsAppScreenShareOn
13
- case SimulcastConfigUpdate
14
- case PeersUpdate
15
- case AudioDeviceUpdate
16
- case SendMediaEvent
17
- case BandwidthEstimation
18
- case ReconnectionRetriesLimitReached
19
- case ReconnectionStarted
20
- case Reconnected
21
- case Warning
22
- case PeerStatusChanged
23
-
24
- var name: String {
25
- rawValue
11
+ class EmitableEvent {
12
+ enum EventName: String, CaseIterable {
13
+ case IsMicrophoneOn
14
+ case IsScreenShareOn
15
+ case IsAppScreenShareOn
16
+ case SimulcastConfigUpdate
17
+ case PeersUpdate
18
+ case AudioDeviceUpdate
19
+ case BandwidthEstimation
20
+ case Warning
21
+ case PeerStatusChanged
22
+ case ReconnectionStatusChanged
23
+ case CurrentCameraChanged
24
+
25
+ var name: String {
26
+ rawValue
27
+ }
28
+ }
29
+
30
+ let event: EventName
31
+ let eventContent: Any?
32
+
33
+ var data: [String: Any?] {
34
+ [event.name: eventContent]
35
+ }
36
+
37
+ private init(event: EventName, eventContent: Any? = nil) {
38
+ self.event = event
39
+ self.eventContent = eventContent
40
+ }
41
+
42
+ static func isMicrophoneOn(enabled: Bool) -> EmitableEvent { .init(event: .IsMicrophoneOn, eventContent: enabled) }
43
+ static func isScreenShareOn(enabled: Bool) -> EmitableEvent {
44
+ .init(event: .IsScreenShareOn, eventContent: enabled)
45
+ }
46
+ static func isAppScreenShareOn(enabled: Bool) -> EmitableEvent {
47
+ .init(event: .IsAppScreenShareOn, eventContent: enabled)
48
+ }
49
+ static func bandwidthEstimation(estimation: Int) -> EmitableEvent {
50
+ .init(event: .BandwidthEstimation, eventContent: estimation)
51
+ }
52
+ static func warning(message: String) -> EmitableEvent { .init(event: .Warning, eventContent: message) }
53
+ static func peerStatusChanged(peerStatus: PeerStatus) -> EmitableEvent {
54
+ .init(event: .PeerStatusChanged, eventContent: peerStatus.rawValue)
55
+ }
56
+ static func reconnectionStatusChanged(reconnectionStatus: ReconnectionStatus) -> EmitableEvent {
57
+ .init(event: .ReconnectionStatusChanged, eventContent: reconnectionStatus.rawValue)
58
+ }
59
+
60
+ static func currentCameraChanged(localCamera: LocalCamera?, isCameraOn: Bool) -> EmitableEvent {
61
+ return .init(
62
+ event: .CurrentCameraChanged,
63
+ eventContent: [
64
+ "currentCamera": localCamera as Any,
65
+ "isCameraOn": isCameraOn,
66
+ ])
67
+ }
68
+
69
+ static func simulcastConfigUpdate(simulcastConfig: SimulcastConfig) -> EmitableEvent {
70
+ return .init(
71
+ event: .SimulcastConfigUpdate,
72
+ eventContent: [
73
+ "enabled": simulcastConfig.enabled,
74
+ "activeEncodings": simulcastConfig.activeEncodings.map { e in e.description },
75
+ ])
76
+ }
77
+
78
+ static func peersUpdate(peersData: [[String: Any?]]) -> EmitableEvent {
79
+ return .init(event: .PeersUpdate, eventContent: peersData)
80
+ }
81
+
82
+ static func audioDeviceUpdate(currentRoute: AVAudioSessionRouteDescription) -> EmitableEvent {
83
+ let output = currentRoute.outputs[0]
84
+ let deviceType = output.portType
85
+
86
+ let deviceTypeString =
87
+ switch deviceType {
88
+ case .bluetoothA2DP, .bluetoothLE, .bluetoothHFP: "bluetooth"
89
+ case .builtInSpeaker: "speaker"
90
+ case .builtInReceiver: "earpiece"
91
+ case .headphones: "headphones"
92
+ default: deviceType.rawValue
93
+ }
94
+
95
+ return .init(
96
+ event: .AudioDeviceUpdate,
97
+ eventContent: [
98
+ "selectedDevice": ["name": output.portName, "type": deviceTypeString],
99
+ "availableDevices": [],
100
+ ])
26
101
  }
27
102
 
28
103
  static var allEvents: [String] {
29
- EmitableEvents.allCases.map(\.name)
104
+ EventName.allCases.map(\.name)
30
105
  }
31
106
  }
@@ -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.4.1'
28
+ s.dependency 'FishjamCloudClient', '0.6.0'
29
29
 
30
30
  end
@@ -19,29 +19,35 @@ class RNFishjamClient: FishjamClientListener {
19
19
  var connectPromise: Promise? = nil
20
20
 
21
21
  var videoSimulcastConfig: SimulcastConfig = SimulcastConfig()
22
- var localUserMetadata: Metadata = .init()
23
22
 
24
23
  var screenShareSimulcastConfig: SimulcastConfig = SimulcastConfig()
25
24
  var screenShareMaxBandwidth: TrackBandwidthLimit = .BandwidthLimit(0)
26
25
 
27
26
  var cameraId: String? = nil
28
27
 
29
- var audioSessionMode: AVAudioSession.Mode = AVAudioSession.Mode.videoChat
28
+ var audioSessionMode: AVAudioSession.Mode = .videoChat
30
29
  var errorMessage: String?
31
30
 
31
+ var currentCamera: LocalCamera? { getLocalCameraTrack()?.currentCaptureDevice?.toLocalCamera() }
32
+
32
33
  private(set) var peerStatus: PeerStatus = .idle {
33
34
  didSet {
34
- let event = EmitableEvents.PeerStatusChanged
35
- emit(event: event, data: [event.name: peerStatus.rawValue])
35
+ emit(event: .peerStatusChanged(peerStatus: peerStatus))
36
+ }
37
+ }
38
+
39
+ private(set) var reconnectionStatus: ReconnectionStatus = .idle {
40
+ didSet {
41
+ emit(event: .reconnectionStatusChanged(reconnectionStatus: reconnectionStatus))
36
42
  }
37
43
  }
38
44
 
39
- let sendEvent: (_ eventName: String, _ data: [String: Any]) -> Void
45
+ let sendEvent: (_ eventName: String, _ data: [String: Any?]) -> Void
40
46
 
41
47
  static var tracksUpdateListenersManager = TracksUpdateListenersManager()
42
48
  static var localCameraTracksChangedListenersManager = LocalCameraTracksChangedListenersManager()
43
49
 
44
- init(sendEvent: @escaping (_ eventName: String, _ data: [String: Any]) -> Void) {
50
+ init(sendEvent: @escaping (_ eventName: String, _ data: [String: Any?]) -> Void) {
45
51
  self.sendEvent = sendEvent
46
52
  NotificationCenter.default.addObserver(
47
53
  self,
@@ -206,7 +212,6 @@ class RNFishjamClient: FishjamClientListener {
206
212
  ) {
207
213
  peerStatus = .connecting
208
214
  connectPromise = promise
209
- localUserMetadata = ["server": [:], "peer": peerMetadata].toMetadata()
210
215
 
211
216
  let reconnectConfig = FishjamCloudClient.ReconnectConfig(
212
217
  maxAttempts: config.reconnectConfig.maxAttempts, initialDelayMs: config.reconnectConfig.initialDelayMs,
@@ -214,7 +219,7 @@ class RNFishjamClient: FishjamClientListener {
214
219
 
215
220
  RNFishjamClient.fishjamClient?.connect(
216
221
  config: FishjamCloudClient.ConnectConfig(
217
- websocketUrl: url, token: peerToken, peerMetadata: localUserMetadata,
222
+ websocketUrl: url, token: peerToken, peerMetadata: peerMetadata.toMetadata(),
218
223
  reconnectConfig: reconnectConfig
219
224
  ))
220
225
 
@@ -239,23 +244,36 @@ class RNFishjamClient: FishjamClientListener {
239
244
  }
240
245
  }
241
246
 
242
- func startCamera(config: CameraConfig) async throws {
243
- try ensureCreated()
247
+ func startCamera(config: CameraConfig) async throws -> Bool {
248
+ #if targetEnvironment(simulator)
249
+ emit(
250
+ event: .warning(
251
+ message: "Camera is not supported on simulator."))
252
+ return false
253
+ #else
254
+ try ensureCreated()
244
255
 
245
- guard !isCameraInitialized else {
246
- emit(warning: "Camera already started. You may only call startCamera once before leaveRoom is called.")
247
- return
248
- }
256
+ guard !isCameraInitialized else {
257
+ emit(
258
+ event: .warning(
259
+ message:
260
+ "Camera already started. You may only call startCamera once before leaveRoom is called."))
249
261
 
250
- guard await PermissionUtils.requestCameraPermission() else {
251
- emit(warning: "Camera permission not granted.")
252
- return
253
- }
262
+ return true
263
+ }
254
264
 
255
- let cameraTrack = try createCameraTrack(config: config)
256
- setCameraTrackState(cameraTrack, enabled: config.cameraEnabled)
257
- emitEndpoints()
258
- isCameraInitialized = true
265
+ guard await PermissionUtils.requestCameraPermission() else {
266
+ emit(event: .warning(message: "Camera permission not granted."))
267
+ return false
268
+ }
269
+
270
+ let cameraTrack = try createCameraTrack(config: config)
271
+ cameraTrack.captureDeviceChangedListener = self
272
+ setCameraTrackState(cameraTrack, enabled: config.cameraEnabled)
273
+ emitEndpoints()
274
+ isCameraInitialized = true
275
+ return true
276
+ #endif
259
277
  }
260
278
 
261
279
  private func createCameraTrack(config: CameraConfig) throws -> LocalCameraTrack {
@@ -272,9 +290,9 @@ class RNFishjamClient: FishjamClientListener {
272
290
  private func setCameraTrackState(_ cameraTrack: LocalCameraTrack, enabled: Bool) {
273
291
  cameraTrack.enabled = enabled
274
292
  isCameraOn = enabled
275
- let event = EmitableEvents.IsCameraOn
276
- let isCameraEnabledMap = [event.name: enabled]
277
- emit(event: event, data: isCameraEnabledMap)
293
+ emit(
294
+ event: .currentCameraChanged(
295
+ localCamera: cameraTrack.currentCaptureDevice?.toLocalCamera(), isCameraOn: enabled))
278
296
  RNFishjamClient.localCameraTracksChangedListenersManager.notifyListeners()
279
297
  }
280
298
 
@@ -301,12 +319,19 @@ class RNFishjamClient: FishjamClientListener {
301
319
  } else {
302
320
  try await startMicrophone()
303
321
  }
322
+
323
+ try updateLocalAudioTrackMetadata(metadata: [
324
+ "active": isMicrophoneOn,
325
+ "paused": !isMicrophoneOn, //TODO: FCE-711
326
+ "type": "microphone",
327
+ ])
328
+
304
329
  return isMicrophoneOn
305
330
  }
306
331
 
307
332
  func startMicrophone() async throws {
308
333
  guard await PermissionUtils.requestMicrophonePermission() else {
309
- emit(warning: "Microphone permission not granted.")
334
+ emit(event: .warning(message: "Microphone permission not granted."))
310
335
  return
311
336
  }
312
337
  let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(metadata: Metadata())
@@ -318,9 +343,7 @@ class RNFishjamClient: FishjamClientListener {
318
343
  private func setMicrophoneTrackState(_ microphoneTrack: LocalAudioTrack, enabled: Bool) {
319
344
  microphoneTrack.enabled = enabled
320
345
  isMicrophoneOn = enabled
321
- let event = EmitableEvents.IsMicrophoneOn
322
- let isMicrophoneOnMap = [event.name: enabled]
323
- emit(event: event, data: isMicrophoneOnMap)
346
+ emit(event: .isMicrophoneOn(enabled: enabled))
324
347
  }
325
348
 
326
349
  func setAudioSessionMode() {
@@ -345,7 +368,7 @@ class RNFishjamClient: FishjamClientListener {
345
368
  try ensureCreated()
346
369
  try ensureConnected()
347
370
  guard isAppScreenShareOn == false else {
348
- emit(warning: "Screensharing screen not available during screensharing app.")
371
+ emit(event: .warning(message: "Screensharing screen not available during screensharing app."))
349
372
  return
350
373
  }
351
374
  guard let screenShareExtensionBundleId = Bundle.main.infoDictionary?["ScreenShareExtensionBundleId"] as? String
@@ -383,7 +406,7 @@ class RNFishjamClient: FishjamClientListener {
383
406
  metadata: screenShareMetadata,
384
407
  canStart: {
385
408
  if self.isAppScreenShareOn {
386
- self.emit(warning: "Screensharing screen not available during screensharing app.")
409
+ self.emit(event: .warning(message: "Screensharing screen not available during screensharing app."))
387
410
  }
388
411
  return !self.isAppScreenShareOn
389
412
  },
@@ -418,9 +441,7 @@ class RNFishjamClient: FishjamClientListener {
418
441
 
419
442
  private func setScreenShareTrackState(enabled: Bool) throws {
420
443
  isScreenShareOn = enabled
421
- let event = EmitableEvents.IsScreenShareOn
422
- let isScreenShareEnabled = [event.name: enabled]
423
- emit(event: event, data: isScreenShareEnabled)
444
+ emit(event: .isScreenShareOn(enabled: enabled))
424
445
  }
425
446
 
426
447
  func startScreenAppShare(screenShareOptions: ScreenShareOptions) throws {
@@ -449,7 +470,7 @@ class RNFishjamClient: FishjamClientListener {
449
470
 
450
471
  func toggleAppScreenShare(screenShareOptions: ScreenShareOptions) throws {
451
472
  guard isScreenShareOn == false else {
452
- emit(warning: "App screensharing not available during screensharing.")
473
+ emit(event: .warning(message: "App screensharing not available during screensharing."))
453
474
  return
454
475
  }
455
476
  if getLocalScreenAppTrack() != nil {
@@ -462,9 +483,7 @@ class RNFishjamClient: FishjamClientListener {
462
483
  private func setScreenAppTrackState(_ track: LocalAppScreenShareTrack, enabled: Bool) {
463
484
  track.enabled = enabled
464
485
  isAppScreenShareOn = enabled
465
- let event = EmitableEvents.IsAppScreenShareOn
466
- let eventMap = [event.name: enabled]
467
- emit(event: event, data: eventMap)
486
+ emit(event: .isAppScreenShareOn(enabled: enabled))
468
487
  }
469
488
 
470
489
  //returns local endpoint and remote endpoints
@@ -474,13 +493,12 @@ class RNFishjamClient: FishjamClientListener {
474
493
  return [localEndpoint] + remoteEndpoints
475
494
  }
476
495
 
477
- func getPeers() throws -> [[String: Any?]] {
496
+ func getPeers() -> [[String: Any?]] {
478
497
  let endpoints = RNFishjamClient.getLocalAndRemoteEndpoints()
479
498
  return endpoints.compactMap { endpoint in
480
499
  [
481
500
  "id": endpoint.id,
482
501
  "isLocal": endpoint.id == RNFishjamClient.fishjamClient!.getLocalEndpoint().id,
483
- "type": endpoint.type,
484
502
  "metadata": endpoint.metadata.toDict(),
485
503
  "tracks": endpoint.tracks.values.compactMap { track -> [String: Any?]? in
486
504
  switch track {
@@ -498,7 +516,7 @@ class RNFishjamClient: FishjamClientListener {
498
516
  "id": track.id,
499
517
  "type": "Audio",
500
518
  "metadata": track.metadata.toDict(),
501
- "vadStatus": track.vadStatus.rawValue,
519
+ "vadStatus": track.vadStatus == .speech ? "speech" : "silence",
502
520
  ]
503
521
 
504
522
  case let track as LocalCameraTrack:
@@ -539,19 +557,7 @@ class RNFishjamClient: FishjamClientListener {
539
557
 
540
558
  func getCaptureDevices() -> [[String: Any]] {
541
559
  let devices = LocalCameraTrack.getCaptureDevices()
542
- return devices.map { device -> [String: Any] in
543
- let facingDirection =
544
- switch device.position {
545
- case .front: "front"
546
- case .back: "back"
547
- default: "unspecified"
548
- }
549
- return [
550
- "id": device.uniqueID,
551
- "name": device.localizedName,
552
- "facingDirection": facingDirection,
553
- ]
554
- }
560
+ return devices.map { $0.toLocalCamera() }
555
561
  }
556
562
 
557
563
  func updatePeerMetadata(metadata: [String: Any]) throws {
@@ -571,7 +577,7 @@ class RNFishjamClient: FishjamClientListener {
571
577
  }
572
578
  }
573
579
 
574
- func updateLocalAudioTrackMetadata(metadata: [String: Any]) throws {
580
+ private func updateLocalAudioTrackMetadata(metadata: [String: Any]) throws {
575
581
  try ensureAudioTrack()
576
582
  if let track = getLocalAudioTrack() {
577
583
  updateTrackMetadata(trackId: track.id, metadata: metadata)
@@ -604,13 +610,14 @@ class RNFishjamClient: FishjamClientListener {
604
610
  return SimulcastConfig(enabled: true, activeEncodings: updatedEncodings)
605
611
  }
606
612
 
607
- func toggleScreenShareTrackEncoding(encoding: String) throws -> [String: Any] {
613
+ func toggleScreenShareTrackEncoding(encoding: String) throws -> [String: Any?] {
608
614
  try ensureScreenBroadcastTrack()
609
615
  if let track = getLocalScreenBroadcastTrack() {
610
616
  screenShareSimulcastConfig = try toggleTrackEncoding(
611
617
  encoding: encoding, trackId: track.id, simulcastConfig: screenShareSimulcastConfig)
612
618
  }
613
- return getSimulcastConfigAsRNMap(screenShareSimulcastConfig)
619
+
620
+ return EmitableEvent.simulcastConfigUpdate(simulcastConfig: screenShareSimulcastConfig).data
614
621
  }
615
622
 
616
623
  func setScreenShareTrackBandwidth(bandwidth: Int) throws {
@@ -634,7 +641,7 @@ class RNFishjamClient: FishjamClientListener {
634
641
  RNFishjamClient.fishjamClient?.setTargetTrackEncoding(trackId: trackId, encoding: trackEncoding)
635
642
  }
636
643
 
637
- func toggleVideoTrackEncoding(encoding: String) throws -> [String: Any] {
644
+ func toggleVideoTrackEncoding(encoding: String) throws -> [String: Any?] {
638
645
  try ensureCameraTrack()
639
646
  try ensureConnected()
640
647
 
@@ -642,11 +649,10 @@ class RNFishjamClient: FishjamClientListener {
642
649
  videoSimulcastConfig = try toggleTrackEncoding(
643
650
  encoding: encoding, trackId: track.id, simulcastConfig: videoSimulcastConfig)
644
651
 
645
- let event = EmitableEvents.SimulcastConfigUpdate
646
- let simulcastConfigAsRNMap = getSimulcastConfigAsRNMap(videoSimulcastConfig)
647
- emit(event: event, data: simulcastConfigAsRNMap)
652
+ let event = EmitableEvent.simulcastConfigUpdate(simulcastConfig: videoSimulcastConfig)
653
+ emit(event: event)
648
654
 
649
- return simulcastConfigAsRNMap
655
+ return event.data
650
656
  }
651
657
 
652
658
  func setVideoTrackEncodingBandwidth(encoding: String, bandwidth: Int) throws {
@@ -759,20 +765,14 @@ class RNFishjamClient: FishjamClientListener {
759
765
  )
760
766
  }
761
767
 
762
- func emit(event: EmitableEvents, data: [String: Any] = [:]) {
768
+ func emit(event: EmitableEvent) {
763
769
  DispatchQueue.main.async { [weak self] in
764
- self?.sendEvent(event.name, data)
770
+ self?.sendEvent(event.event.name, event.data)
765
771
  }
766
772
  }
767
773
 
768
- func emit(warning: String) {
769
- emit(event: .Warning, data: ["message": warning])
770
- }
771
-
772
774
  func emitEndpoints() {
773
- let event = EmitableEvents.PeersUpdate
774
- let EndpointsUpdateMap = [event.name: (try? getPeers()) ?? []]
775
- emit(event: event, data: EndpointsUpdateMap)
775
+ emit(event: .peersUpdate(peersData: getPeers()))
776
776
  }
777
777
 
778
778
  func onJoined(peerID: String, peersInRoom: [String: Endpoint]) {
@@ -840,7 +840,7 @@ class RNFishjamClient: FishjamClientListener {
840
840
  "E_MEMBRANE_CONNECT", "Failed to connect: socket close, code: \(code), reason: \(reason)")
841
841
  }
842
842
  connectPromise = nil
843
- peerStatus = .error
843
+ peerStatus = .idle
844
844
  }
845
845
 
846
846
  func onSocketError() {
@@ -848,6 +848,7 @@ class RNFishjamClient: FishjamClientListener {
848
848
  connectPromise.reject("E_MEMBRANE_CONNECT", "Failed to connect: socket error")
849
849
  }
850
850
  connectPromise = nil
851
+ peerStatus = .error
851
852
  }
852
853
 
853
854
  func onSocketOpen() {}
@@ -856,13 +857,6 @@ class RNFishjamClient: FishjamClientListener {
856
857
  peerStatus = .idle
857
858
  }
858
859
 
859
- func getSimulcastConfigAsRNMap(_ simulcastConfig: SimulcastConfig) -> [String: Any] {
860
- return [
861
- "enabled": simulcastConfig.enabled,
862
- "activeEncodings": simulcastConfig.activeEncodings.map { e in e.description },
863
- ]
864
- }
865
-
866
860
  func selectAudioSessionMode(sessionMode: String) throws {
867
861
  switch sessionMode {
868
862
  case "videoChat":
@@ -895,53 +889,29 @@ class RNFishjamClient: FishjamClientListener {
895
889
  }
896
890
 
897
891
  @objc func onRouteChangeNotification() {
898
- let currentRoute = AVAudioSession.sharedInstance().currentRoute
899
- let output = currentRoute.outputs[0]
900
- let deviceType = output.portType
901
- var deviceTypeString: String = ""
902
-
903
- switch deviceType {
904
- case .bluetoothA2DP, .bluetoothLE, .bluetoothHFP:
905
- deviceTypeString = "bluetooth"
906
- break
907
- case .builtInSpeaker:
908
- deviceTypeString = "speaker"
909
- break
910
- case .builtInReceiver:
911
- deviceTypeString = "earpiece"
912
- break
913
- case .headphones:
914
- deviceTypeString = "headphones"
915
- break
916
- default:
917
- deviceTypeString = deviceType.rawValue
918
- }
919
- let event = EmitableEvents.AudioDeviceUpdate
920
- emit(
921
- event: event,
922
- data: [
923
- event.name: [
924
- "selectedDevice": ["name": output.portName, "type": deviceTypeString],
925
- "availableDevices": [],
926
- ]
927
- ] as [String: [String: Any]])
892
+ emit(event: .audioDeviceUpdate(currentRoute: AVAudioSession.sharedInstance().currentRoute))
928
893
  }
929
894
 
930
895
  func onBandwidthEstimationChanged(estimation: Int) {
931
- let event = EmitableEvents.BandwidthEstimation
932
- emit(event: event, data: [event.name: estimation])
896
+ emit(event: .bandwidthEstimation(estimation: estimation))
933
897
  }
934
898
 
935
899
  func onReconnectionStarted() {
936
- emit(event: .ReconnectionStarted)
900
+ reconnectionStatus = .reconnecting
937
901
  }
938
902
 
939
903
  func onReconnected() {
940
- emit(event: .Reconnected)
904
+ reconnectionStatus = .idle
941
905
  }
942
906
 
943
907
  func onReconnectionRetriesLimitReached() {
944
- emit(event: .ReconnectionRetriesLimitReached)
908
+ reconnectionStatus = .error
945
909
  }
946
910
 
947
911
  }
912
+
913
+ extension RNFishjamClient: CameraCapturerDeviceChangedListener {
914
+ func onCaptureDeviceChanged(_ device: AVCaptureDevice?) {
915
+ emit(event: .currentCameraChanged(localCamera: device?.toLocalCamera(), isCameraOn: isCameraOn))
916
+ }
917
+ }
@@ -75,7 +75,7 @@ public class RNFishjamClientModule: Module {
75
75
  public func definition() -> ModuleDefinition {
76
76
  let rnFishjamClient: RNFishjamClient = {
77
77
  let client = RNFishjamClient {
78
- (eventName: String, data: [String: Any]) in
78
+ (eventName: String, data: [String: Any?]) in
79
79
  self.sendEvent(eventName, data)
80
80
  }
81
81
  client.create()
@@ -84,12 +84,16 @@ public class RNFishjamClientModule: Module {
84
84
 
85
85
  Name("RNFishjamClient")
86
86
 
87
- Events(EmitableEvents.allEvents)
87
+ Events(EmitableEvent.allEvents)
88
88
 
89
89
  Property("peerStatus") {
90
90
  return rnFishjamClient.peerStatus.rawValue
91
91
  }
92
92
 
93
+ Property("reconnectionStatus") {
94
+ return rnFishjamClient.reconnectionStatus.rawValue
95
+ }
96
+
93
97
  Property("isMicrophoneOn") {
94
98
  return rnFishjamClient.isMicrophoneOn
95
99
  }
@@ -102,6 +106,10 @@ public class RNFishjamClientModule: Module {
102
106
  return rnFishjamClient.getCaptureDevices()
103
107
  }
104
108
 
109
+ Property("currentCamera") {
110
+ return rnFishjamClient.currentCamera
111
+ }
112
+
105
113
  Property("isScreenShareOn") {
106
114
  return rnFishjamClient.isScreenShareOn
107
115
  }
@@ -110,6 +118,10 @@ public class RNFishjamClientModule: Module {
110
118
  return rnFishjamClient.isAppScreenShareOn
111
119
  }
112
120
 
121
+ Function("getPeers") {
122
+ return rnFishjamClient.getPeers()
123
+ }
124
+
113
125
  AsyncFunction("joinRoom") {
114
126
  (
115
127
  url: String, peerToken: String, peerMetadata: [String: Any], config: ConnectConfig,
@@ -152,10 +164,6 @@ public class RNFishjamClientModule: Module {
152
164
  try rnFishjamClient.toggleAppScreenShare(screenShareOptions: screenShareOptions)
153
165
  }
154
166
 
155
- AsyncFunction("getPeers") {
156
- try rnFishjamClient.getPeers()
157
- }
158
-
159
167
  AsyncFunction("updatePeerMetadata") { (metadata: [String: Any]) in
160
168
  try rnFishjamClient.updatePeerMetadata(metadata: metadata)
161
169
  }
@@ -164,10 +172,6 @@ public class RNFishjamClientModule: Module {
164
172
  try rnFishjamClient.updateLocalVideoTrackMetadata(metadata: metadata)
165
173
  }
166
174
 
167
- AsyncFunction("updateAudioTrackMetadata") { (metadata: [String: Any]) in
168
- try rnFishjamClient.updateLocalAudioTrackMetadata(metadata: metadata)
169
- }
170
-
171
175
  AsyncFunction("updateScreenShareTrackMetadata") { (metadata: [String: Any]) in
172
176
  try rnFishjamClient.updateLocalScreenShareTrackMetadata(metadata: metadata)
173
177
  }
package/ios/Utils.swift CHANGED
@@ -21,23 +21,3 @@ let log = OSLog(subsystem: "com.fishjamcloud.react-native-client", category: "Er
21
21
  }
22
22
  }
23
23
  #endif
24
-
25
- extension [String: Any] {
26
- public func toMetadata() -> Metadata {
27
- var res: Metadata = .init()
28
- self.forEach { entry in
29
- res[entry.key] = entry.value
30
- }
31
- return res
32
- }
33
- }
34
-
35
- extension AnyJson {
36
- public func toDict() -> [String: Any] {
37
- var res: [String: Any] = [:]
38
- self.keys.forEach { key in
39
- res[key] = self[key]
40
- }
41
- return res
42
- }
43
- }