@fishjam-cloud/react-native-client 0.24.0 → 0.25.0-rc.1

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 (266) hide show
  1. package/README.md +56 -15
  2. package/dist/index.d.ts +13 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +19 -0
  5. package/dist/overrides/RTCPeerConnection.d.ts +8 -0
  6. package/dist/overrides/RTCPeerConnection.d.ts.map +1 -0
  7. package/dist/overrides/RTCPeerConnection.js +16 -0
  8. package/dist/overrides/RTCView.d.ts +11 -0
  9. package/dist/overrides/RTCView.d.ts.map +1 -0
  10. package/dist/overrides/RTCView.js +21 -0
  11. package/dist/polyfills/local-storage.d.ts +10 -0
  12. package/dist/polyfills/local-storage.d.ts.map +1 -0
  13. package/dist/polyfills/local-storage.js +24 -0
  14. package/{build/hooks → dist}/useForegroundService.d.ts +10 -10
  15. package/dist/useForegroundService.d.ts.map +1 -0
  16. package/dist/useForegroundService.js +10 -0
  17. package/dist/webrtc-polyfill.d.ts +2 -0
  18. package/dist/webrtc-polyfill.d.ts.map +1 -0
  19. package/dist/webrtc-polyfill.js +14 -0
  20. package/package.json +44 -92
  21. package/plugin/broadcastExtensionFiles/Atomic.swift +37 -0
  22. package/plugin/broadcastExtensionFiles/DarwinNotificationCenter.swift +29 -0
  23. package/plugin/broadcastExtensionFiles/Info.plist +1 -1
  24. package/plugin/broadcastExtensionFiles/SampleHandler.swift +104 -0
  25. package/plugin/broadcastExtensionFiles/SampleUploader.swift +146 -0
  26. package/plugin/broadcastExtensionFiles/SocketConnection.swift +198 -0
  27. package/plugin/build/types.d.ts +5 -4
  28. package/plugin/build/withFishjam.d.ts +31 -2
  29. package/plugin/build/withFishjam.js +31 -5
  30. package/plugin/build/withFishjamAndroid.d.ts +2 -2
  31. package/plugin/build/withFishjamAndroid.js +48 -40
  32. package/plugin/build/withFishjamIos.d.ts +3 -8
  33. package/plugin/build/withFishjamIos.js +52 -72
  34. package/plugin/src/types.ts +19 -0
  35. package/plugin/src/withFishjam.ts +42 -0
  36. package/plugin/src/withFishjamAndroid.ts +112 -0
  37. package/plugin/src/withFishjamIos.ts +336 -0
  38. package/plugin/tsconfig.json +9 -0
  39. package/plugin/tsconfig.tsbuildinfo +1 -0
  40. package/LICENSE.txt +0 -201
  41. package/android/build.gradle +0 -95
  42. package/android/src/main/AndroidManifest.xml +0 -2
  43. package/android/src/main/java/io/fishjam/reactnative/AudioDeviceKind.kt +0 -34
  44. package/android/src/main/java/io/fishjam/reactnative/AudioSwitchManager.kt +0 -61
  45. package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +0 -126
  46. package/android/src/main/java/io/fishjam/reactnative/Errors.kt +0 -31
  47. package/android/src/main/java/io/fishjam/reactnative/PipContainerView.kt +0 -282
  48. package/android/src/main/java/io/fishjam/reactnative/PipContainerViewModule.kt +0 -41
  49. package/android/src/main/java/io/fishjam/reactnative/PipTrackSelector.kt +0 -98
  50. package/android/src/main/java/io/fishjam/reactnative/PipViewFactory.kt +0 -186
  51. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +0 -1001
  52. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +0 -358
  53. package/android/src/main/java/io/fishjam/reactnative/Utils.kt +0 -11
  54. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewView.kt +0 -40
  55. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewViewModule.kt +0 -22
  56. package/android/src/main/java/io/fishjam/reactnative/VideoRendererView.kt +0 -76
  57. package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +0 -33
  58. package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +0 -257
  59. package/android/src/main/java/io/fishjam/reactnative/extensions/CaptureDevice.kt +0 -17
  60. package/android/src/main/java/io/fishjam/reactnative/foregroundService/FishjamForegroundService.kt +0 -101
  61. package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceManager.kt +0 -118
  62. package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceState.kt +0 -46
  63. package/android/src/main/java/io/fishjam/reactnative/helpers/PictureInPictureHelperFragment.kt +0 -20
  64. package/android/src/main/java/io/fishjam/reactnative/managers/ListenerManager.kt +0 -24
  65. package/android/src/main/java/io/fishjam/reactnative/managers/LocalCameraTracksChangedListenersManager.kt +0 -8
  66. package/android/src/main/java/io/fishjam/reactnative/managers/LocalTracksSwitchListenersManager.kt +0 -17
  67. package/android/src/main/java/io/fishjam/reactnative/managers/TracksUpdateListenersManager.kt +0 -7
  68. package/android/src/main/java/io/fishjam/reactnative/utils/PermissionUtils.kt +0 -45
  69. package/build/RNFishjamClientModule.d.ts +0 -106
  70. package/build/RNFishjamClientModule.d.ts.map +0 -1
  71. package/build/RNFishjamClientModule.js +0 -21
  72. package/build/RNFishjamClientModule.js.map +0 -1
  73. package/build/common/metadata.d.ts +0 -9
  74. package/build/common/metadata.d.ts.map +0 -1
  75. package/build/common/metadata.js +0 -11
  76. package/build/common/metadata.js.map +0 -1
  77. package/build/components/FishjamRoom/GridTrackItem.d.ts +0 -12
  78. package/build/components/FishjamRoom/GridTrackItem.d.ts.map +0 -1
  79. package/build/components/FishjamRoom/GridTrackItem.js +0 -56
  80. package/build/components/FishjamRoom/GridTrackItem.js.map +0 -1
  81. package/build/components/FishjamRoom/VideosGrid.d.ts +0 -3
  82. package/build/components/FishjamRoom/VideosGrid.d.ts.map +0 -1
  83. package/build/components/FishjamRoom/VideosGrid.js +0 -20
  84. package/build/components/FishjamRoom/VideosGrid.js.map +0 -1
  85. package/build/components/FishjamRoom/index.d.ts +0 -33
  86. package/build/components/FishjamRoom/index.d.ts.map +0 -1
  87. package/build/components/FishjamRoom/index.js +0 -52
  88. package/build/components/FishjamRoom/index.js.map +0 -1
  89. package/build/components/FishjamRoom/parsePeersToTracks.d.ts +0 -4
  90. package/build/components/FishjamRoom/parsePeersToTracks.d.ts.map +0 -1
  91. package/build/components/FishjamRoom/parsePeersToTracks.js +0 -37
  92. package/build/components/FishjamRoom/parsePeersToTracks.js.map +0 -1
  93. package/build/components/PipContainerView.d.ts +0 -48
  94. package/build/components/PipContainerView.d.ts.map +0 -1
  95. package/build/components/PipContainerView.js +0 -34
  96. package/build/components/PipContainerView.js.map +0 -1
  97. package/build/components/VideoPreviewView.d.ts +0 -28
  98. package/build/components/VideoPreviewView.d.ts.map +0 -1
  99. package/build/components/VideoPreviewView.js +0 -17
  100. package/build/components/VideoPreviewView.js.map +0 -1
  101. package/build/components/VideoRendererView.d.ts +0 -39
  102. package/build/components/VideoRendererView.d.ts.map +0 -1
  103. package/build/components/VideoRendererView.js +0 -25
  104. package/build/components/VideoRendererView.js.map +0 -1
  105. package/build/consts/index.d.ts +0 -5
  106. package/build/consts/index.d.ts.map +0 -1
  107. package/build/consts/index.js +0 -8
  108. package/build/consts/index.js.map +0 -1
  109. package/build/debug/common/webRTC.d.ts +0 -9
  110. package/build/debug/common/webRTC.d.ts.map +0 -1
  111. package/build/debug/common/webRTC.js +0 -11
  112. package/build/debug/common/webRTC.js.map +0 -1
  113. package/build/debug/index.d.ts +0 -4
  114. package/build/debug/index.d.ts.map +0 -1
  115. package/build/debug/index.js +0 -3
  116. package/build/debug/index.js.map +0 -1
  117. package/build/debug/stats/types.d.ts +0 -55
  118. package/build/debug/stats/types.d.ts.map +0 -1
  119. package/build/debug/stats/types.js +0 -2
  120. package/build/debug/stats/types.js.map +0 -1
  121. package/build/debug/stats/useRTCStatistics.d.ts +0 -9
  122. package/build/debug/stats/useRTCStatistics.d.ts.map +0 -1
  123. package/build/debug/stats/useRTCStatistics.js +0 -79
  124. package/build/debug/stats/useRTCStatistics.js.map +0 -1
  125. package/build/hooks/internal/useFishjamEvent.d.ts +0 -4
  126. package/build/hooks/internal/useFishjamEvent.d.ts.map +0 -1
  127. package/build/hooks/internal/useFishjamEvent.js +0 -38
  128. package/build/hooks/internal/useFishjamEvent.js.map +0 -1
  129. package/build/hooks/internal/useFishjamEventState.d.ts +0 -3
  130. package/build/hooks/internal/useFishjamEventState.d.ts.map +0 -1
  131. package/build/hooks/internal/useFishjamEventState.js +0 -18
  132. package/build/hooks/internal/useFishjamEventState.js.map +0 -1
  133. package/build/hooks/useAppScreenShare.d.ts +0 -18
  134. package/build/hooks/useAppScreenShare.d.ts.map +0 -1
  135. package/build/hooks/useAppScreenShare.js +0 -46
  136. package/build/hooks/useAppScreenShare.js.map +0 -1
  137. package/build/hooks/useAudioSettings.d.ts +0 -49
  138. package/build/hooks/useAudioSettings.d.ts.map +0 -1
  139. package/build/hooks/useAudioSettings.js +0 -70
  140. package/build/hooks/useAudioSettings.js.map +0 -1
  141. package/build/hooks/useBandwidthEstimation.d.ts +0 -14
  142. package/build/hooks/useBandwidthEstimation.d.ts.map +0 -1
  143. package/build/hooks/useBandwidthEstimation.js +0 -19
  144. package/build/hooks/useBandwidthEstimation.js.map +0 -1
  145. package/build/hooks/useCallKit.d.ts +0 -121
  146. package/build/hooks/useCallKit.d.ts.map +0 -1
  147. package/build/hooks/useCallKit.js +0 -142
  148. package/build/hooks/useCallKit.js.map +0 -1
  149. package/build/hooks/useCamera.d.ts +0 -113
  150. package/build/hooks/useCamera.d.ts.map +0 -1
  151. package/build/hooks/useCamera.js +0 -93
  152. package/build/hooks/useCamera.js.map +0 -1
  153. package/build/hooks/useConnection.d.ts +0 -73
  154. package/build/hooks/useConnection.d.ts.map +0 -1
  155. package/build/hooks/useConnection.js +0 -46
  156. package/build/hooks/useConnection.js.map +0 -1
  157. package/build/hooks/useForegroundService.d.ts.map +0 -1
  158. package/build/hooks/useForegroundService.js +0 -66
  159. package/build/hooks/useForegroundService.js.map +0 -1
  160. package/build/hooks/useMicrophone.d.ts +0 -16
  161. package/build/hooks/useMicrophone.d.ts.map +0 -1
  162. package/build/hooks/useMicrophone.js +0 -31
  163. package/build/hooks/useMicrophone.js.map +0 -1
  164. package/build/hooks/usePeerStatus.d.ts +0 -10
  165. package/build/hooks/usePeerStatus.d.ts.map +0 -1
  166. package/build/hooks/usePeerStatus.js +0 -13
  167. package/build/hooks/usePeerStatus.js.map +0 -1
  168. package/build/hooks/usePeers.d.ts +0 -98
  169. package/build/hooks/usePeers.d.ts.map +0 -1
  170. package/build/hooks/usePeers.js +0 -81
  171. package/build/hooks/usePeers.js.map +0 -1
  172. package/build/hooks/usePermissions.d.ts +0 -24
  173. package/build/hooks/usePermissions.d.ts.map +0 -1
  174. package/build/hooks/usePermissions.js +0 -61
  175. package/build/hooks/usePermissions.js.map +0 -1
  176. package/build/hooks/useReconnection.d.ts +0 -11
  177. package/build/hooks/useReconnection.d.ts.map +0 -1
  178. package/build/hooks/useReconnection.js +0 -14
  179. package/build/hooks/useReconnection.js.map +0 -1
  180. package/build/hooks/useSandbox.d.ts +0 -20
  181. package/build/hooks/useSandbox.d.ts.map +0 -1
  182. package/build/hooks/useSandbox.js +0 -54
  183. package/build/hooks/useSandbox.js.map +0 -1
  184. package/build/hooks/useScreenShare.d.ts +0 -36
  185. package/build/hooks/useScreenShare.d.ts.map +0 -1
  186. package/build/hooks/useScreenShare.js +0 -45
  187. package/build/hooks/useScreenShare.js.map +0 -1
  188. package/build/hooks/useUpdatePeerMetadata.d.ts +0 -15
  189. package/build/hooks/useUpdatePeerMetadata.d.ts.map +0 -1
  190. package/build/hooks/useUpdatePeerMetadata.js +0 -21
  191. package/build/hooks/useUpdatePeerMetadata.js.map +0 -1
  192. package/build/index.d.ts +0 -36
  193. package/build/index.d.ts.map +0 -1
  194. package/build/index.js +0 -30
  195. package/build/index.js.map +0 -1
  196. package/build/livestream/components/LivestreamStreamer.d.ts +0 -24
  197. package/build/livestream/components/LivestreamStreamer.d.ts.map +0 -1
  198. package/build/livestream/components/LivestreamStreamer.js +0 -12
  199. package/build/livestream/components/LivestreamStreamer.js.map +0 -1
  200. package/build/livestream/components/LivestreamViewer.d.ts +0 -46
  201. package/build/livestream/components/LivestreamViewer.d.ts.map +0 -1
  202. package/build/livestream/components/LivestreamViewer.js +0 -10
  203. package/build/livestream/components/LivestreamViewer.js.map +0 -1
  204. package/build/livestream/hooks/useLivestreamScreenSharingStreamer.d.ts +0 -49
  205. package/build/livestream/hooks/useLivestreamScreenSharingStreamer.d.ts.map +0 -1
  206. package/build/livestream/hooks/useLivestreamScreenSharingStreamer.js +0 -58
  207. package/build/livestream/hooks/useLivestreamScreenSharingStreamer.js.map +0 -1
  208. package/build/livestream/hooks/useLivestreamStreamer.d.ts +0 -65
  209. package/build/livestream/hooks/useLivestreamStreamer.d.ts.map +0 -1
  210. package/build/livestream/hooks/useLivestreamStreamer.js +0 -71
  211. package/build/livestream/hooks/useLivestreamStreamer.js.map +0 -1
  212. package/build/livestream/hooks/useLivestreamViewer.d.ts +0 -36
  213. package/build/livestream/hooks/useLivestreamViewer.d.ts.map +0 -1
  214. package/build/livestream/hooks/useLivestreamViewer.js +0 -73
  215. package/build/livestream/hooks/useLivestreamViewer.js.map +0 -1
  216. package/build/livestream/index.d.ts +0 -12
  217. package/build/livestream/index.d.ts.map +0 -1
  218. package/build/livestream/index.js +0 -7
  219. package/build/livestream/index.js.map +0 -1
  220. package/build/protos/fishjam/peer_notifications.d.ts +0 -63
  221. package/build/protos/fishjam/peer_notifications.d.ts.map +0 -1
  222. package/build/protos/fishjam/peer_notifications.js +0 -235
  223. package/build/protos/fishjam/peer_notifications.js.map +0 -1
  224. package/build/types.d.ts +0 -34
  225. package/build/types.d.ts.map +0 -1
  226. package/build/types.js +0 -2
  227. package/build/types.js.map +0 -1
  228. package/build/utils/config.d.ts +0 -6
  229. package/build/utils/config.d.ts.map +0 -1
  230. package/build/utils/config.js +0 -10
  231. package/build/utils/config.js.map +0 -1
  232. package/build/utils/errorListener.d.ts +0 -2
  233. package/build/utils/errorListener.d.ts.map +0 -1
  234. package/build/utils/errorListener.js +0 -15
  235. package/build/utils/errorListener.js.map +0 -1
  236. package/build/utils/eventPayloadValidator.d.ts +0 -3
  237. package/build/utils/eventPayloadValidator.d.ts.map +0 -1
  238. package/build/utils/eventPayloadValidator.js +0 -86
  239. package/build/utils/eventPayloadValidator.js.map +0 -1
  240. package/build/utils/getFishjamUrl.d.ts +0 -2
  241. package/build/utils/getFishjamUrl.d.ts.map +0 -1
  242. package/build/utils/getFishjamUrl.js +0 -10
  243. package/build/utils/getFishjamUrl.js.map +0 -1
  244. package/debug/package.json +0 -4
  245. package/expo-module.config.json +0 -19
  246. package/ios/CameraPermissionsRequester.swift +0 -117
  247. package/ios/Events.swift +0 -152
  248. package/ios/PictureInPictureManager.swift +0 -215
  249. package/ios/PipContainerView.swift +0 -56
  250. package/ios/PipContainerViewModule.swift +0 -48
  251. package/ios/RNFishjamClient.podspec +0 -30
  252. package/ios/RNFishjamClient.swift +0 -995
  253. package/ios/RNFishjamClientModule.swift +0 -289
  254. package/ios/RNFishjamProxy.swift +0 -12
  255. package/ios/Utils/PermissionUtils.swift +0 -16
  256. package/ios/Utils.swift +0 -23
  257. package/ios/VideoPreviewView.swift +0 -54
  258. package/ios/VideoPreviewViewModule.swift +0 -21
  259. package/ios/VideoRendererView.swift +0 -98
  260. package/ios/VideoRendererViewModule.swift +0 -23
  261. package/ios/extensions/AVCaptureDevice.swift +0 -20
  262. package/ios/managers/LocalCameraTracksChangedListenersManager.swift +0 -23
  263. package/ios/managers/TracksUpdateListenersManager.swift +0 -21
  264. package/livestream/package.json +0 -4
  265. package/plugin/broadcastExtensionFiles/FishjamBroadcastSampleHandler.swift +0 -50
  266. /package/plugin/broadcastExtensionFiles/{FishjamScreenBroadcastExtension.entitlements → ScreenBroadcastExtension.entitlements} +0 -0
@@ -1,1001 +0,0 @@
1
- package io.fishjam.reactnative
2
-
3
- import android.app.Activity
4
- import android.content.ActivityNotFoundException
5
- import android.content.Intent
6
- import android.media.projection.MediaProjectionManager
7
- import android.util.Log
8
- import androidx.appcompat.app.AppCompatActivity
9
- import com.fishjamcloud.client.FishjamClient
10
- import com.fishjamcloud.client.FishjamClientListener
11
- import com.fishjamcloud.client.ReconnectionStatus
12
- import com.fishjamcloud.client.media.CaptureDevice
13
- import com.fishjamcloud.client.media.CaptureDeviceChangedListener
14
- import com.fishjamcloud.client.media.LocalAudioTrack
15
- import com.fishjamcloud.client.media.LocalScreenShareTrack
16
- import com.fishjamcloud.client.media.LocalVideoTrack
17
- import com.fishjamcloud.client.media.RemoteAudioTrack
18
- import com.fishjamcloud.client.media.RemoteVideoTrack
19
- import com.fishjamcloud.client.media.Track
20
- import com.fishjamcloud.client.media.VideoTrack
21
- import com.fishjamcloud.client.models.AuthError
22
- import com.fishjamcloud.client.models.CustomSource
23
- import com.fishjamcloud.client.models.Endpoint
24
- import com.fishjamcloud.client.models.Metadata
25
- import com.fishjamcloud.client.models.Peer
26
- import com.fishjamcloud.client.models.RTCInboundStats
27
- import com.fishjamcloud.client.models.RTCOutboundStats
28
- import com.fishjamcloud.client.models.ReconnectConfig
29
- import com.fishjamcloud.client.models.SimulcastConfig
30
- import com.fishjamcloud.client.models.TrackBandwidthLimit
31
- import com.fishjamcloud.client.models.TrackEncoding
32
- import com.fishjamcloud.client.models.VideoParameters
33
- import com.twilio.audioswitch.AudioDevice
34
- import expo.modules.kotlin.AppContext
35
- import expo.modules.kotlin.Promise
36
- import expo.modules.kotlin.exception.CodedException
37
- import fishjam.media_events.server.Server
38
- import io.fishjam.reactnative.extensions.toLocalCamera
39
- import io.fishjam.reactnative.foregroundService.ForegroundServiceManager
40
- import io.fishjam.reactnative.managers.LocalCameraTracksChangedListenersManager
41
- import io.fishjam.reactnative.managers.LocalTracksSwitchListenersManager
42
- import io.fishjam.reactnative.managers.TracksUpdateListenersManager
43
- import io.fishjam.reactnative.utils.PermissionUtils
44
- import kotlinx.coroutines.CoroutineScope
45
- import kotlinx.coroutines.Dispatchers
46
- import kotlinx.coroutines.SupervisorJob
47
- import kotlinx.coroutines.delay
48
- import kotlinx.coroutines.launch
49
- import org.webrtc.Logging
50
-
51
- class RNFishjamClient(
52
- private val sendEvent: (name: String, data: Map<String, Any?>) -> Unit
53
- ) : FishjamClientListener,
54
- CaptureDeviceChangedListener {
55
- private val SCREENSHARE_REQUEST = 1
56
-
57
- var isMicrophoneOn = false
58
- var isCameraOn = false
59
- var isScreenShareOn = false
60
- var isConnected = false
61
-
62
- var isCameraInitialized = false
63
- private set(value) {
64
- field = value
65
- emitEvent(
66
- EmitableEvent.currentCameraChanged(
67
- getCurrentCaptureDevice(),
68
- isCameraOn,
69
- value
70
- )
71
- )
72
- }
73
-
74
- private var connectPromise: Promise? = null
75
- private set(value) {
76
- field = value
77
- if (value == null) {
78
- return
79
- }
80
- coroutineScope.launch {
81
- delay(15000)
82
- // If promise is still assigned it means it was not resolved in that time,
83
- // so close the client and reject it with timeout error
84
- connectPromise?.let { promise ->
85
- fishjamClient.leave {
86
- promise.reject(SocketError("Failed to connect: Fishjam server is not responding"))
87
- connectPromise = null
88
- peerStatus = PeerStatus.Error
89
- }
90
- }
91
- }
92
- }
93
- private var screenSharePermissionPromise: Promise? = null
94
-
95
- var videoSimulcastConfig: SimulcastConfig = SimulcastConfig()
96
- private var localUserMetadata: Metadata = mutableMapOf()
97
-
98
- var screenShareQuality: String? = null
99
- var screenShareSimulcastConfig: SimulcastConfig = SimulcastConfig()
100
-
101
- var screenShareMetadata: Map<String, Any> = mutableMapOf()
102
-
103
- private var mediaProjectionIntent: Intent? = null
104
-
105
- var audioSwitchManager: AudioSwitchManager? = null
106
-
107
- var appContext: AppContext? = null
108
-
109
- var peerStatus = PeerStatus.Idle
110
- private set(value) {
111
- field = value
112
- emitEvent(EmitableEvent.peerStatusChanged(value))
113
- }
114
-
115
- var reconnectionStatus = ReconnectionStatus.Idle
116
- private set(value) {
117
- field = value
118
- emitEvent(EmitableEvent.reconnectionStatusChanged(value))
119
- }
120
-
121
- private val foregroundServiceManager by lazy {
122
- ForegroundServiceManager(appContext ?: throw CodedException("appContext not found"))
123
- }
124
-
125
- companion object {
126
- val trackUpdateListenersManager = TracksUpdateListenersManager()
127
-
128
- val localTracksSwitchListenerManager = LocalTracksSwitchListenersManager()
129
-
130
- val localCameraTracksChangedListenersManager = LocalCameraTracksChangedListenersManager()
131
-
132
- lateinit var fishjamClient: FishjamClient
133
-
134
- fun getAllPeers(): List<Peer> {
135
- val listOfPeers = fishjamClient.getRemotePeers().toMutableList()
136
- val localEndpoint = fishjamClient.getLocalEndpoint()
137
- listOfPeers.add(localEndpoint)
138
- return listOfPeers
139
- }
140
-
141
- private var eventEmitter: ((String, Map<String, Any?>) -> Unit)? = null
142
-
143
- private fun setEventEmitter(emitter: ((String, Map<String, Any?>) -> Unit)?) {
144
- if (emitter != null && eventEmitter != null) {
145
- throw IllegalStateException("Event emitter already set.")
146
- }
147
- eventEmitter = emitter
148
- }
149
-
150
- fun sendEvent(event: EmitableEvent) {
151
- if (eventEmitter == null) {
152
- Log.e("RNFishjamClient", "Event emitter is not set.")
153
- }
154
- eventEmitter?.invoke(event.name, event.data)
155
- }
156
-
157
- suspend fun createCustomSource(customSource: CustomSource) = fishjamClient.createCustomSource(customSource)
158
-
159
- suspend fun removeCustomSource(customSource: CustomSource) = fishjamClient.removeCustomSource(customSource)
160
- }
161
-
162
- fun onModuleCreate(appContext: AppContext) {
163
- this.appContext = appContext
164
- this.audioSwitchManager = AudioSwitchManager(appContext.reactContext!!)
165
- setEventEmitter(sendEvent)
166
- create()
167
- }
168
-
169
- fun onModuleDestroy() {
170
- audioSwitchManager?.stop()
171
- setEventEmitter(null)
172
- }
173
-
174
- private val coroutineScope: CoroutineScope =
175
- CoroutineScope(SupervisorJob() + Dispatchers.Default)
176
-
177
- fun onActivityResult(
178
- requestCode: Int,
179
- resultCode: Int,
180
- data: Intent?
181
- ) {
182
- coroutineScope.launch(Dispatchers.Main) {
183
- if (requestCode != SCREENSHARE_REQUEST) return@launch
184
- if (resultCode != Activity.RESULT_OK) {
185
- screenSharePermissionPromise?.resolve("denied")
186
- screenSharePermissionPromise = null
187
- return@launch
188
- }
189
-
190
- mediaProjectionIntent = data
191
- screenSharePermissionPromise?.resolve("granted")
192
- screenSharePermissionPromise = null
193
- }
194
- }
195
-
196
- private fun getSimulcastConfigFromOptions(simulcastConfigMap: io.fishjam.reactnative.SimulcastConfig): SimulcastConfig {
197
- val simulcastEnabled = simulcastConfigMap.enabled
198
- val activeEncodings = listOf(TrackEncoding.L, TrackEncoding.M, TrackEncoding.H)
199
- return SimulcastConfig(
200
- enabled = simulcastEnabled,
201
- activeEncodings = activeEncodings
202
- )
203
- }
204
-
205
- private fun create() {
206
- audioSwitchManager = AudioSwitchManager(appContext?.reactContext!!)
207
- fishjamClient =
208
- FishjamClient(
209
- appContext = appContext?.reactContext!!,
210
- listener = this
211
- )
212
- }
213
-
214
- private fun getVideoParametersFromOptions(createOptions: CameraConfig): VideoParameters {
215
- var videoParameters =
216
- when (createOptions.quality) {
217
- "QVGA169" -> VideoParameters.presetQVGA169
218
- "VGA169" -> VideoParameters.presetVGA169
219
- "QHD169" -> VideoParameters.presetQHD169
220
- "HD169" -> VideoParameters.presetHD169
221
- "FHD169" -> VideoParameters.presetFHD169
222
- "QVGA43" -> VideoParameters.presetQVGA43
223
- "VGA43" -> VideoParameters.presetVGA43
224
- "QHD43" -> VideoParameters.presetQHD43
225
- "HD43" -> VideoParameters.presetHD43
226
- "FHD43" -> VideoParameters.presetFHD43
227
- else -> VideoParameters.presetVGA169
228
- }
229
- videoParameters =
230
- videoParameters.copy(
231
- dimensions = if (createOptions.flipDimensions) videoParameters.dimensions.flip() else videoParameters.dimensions,
232
- simulcastConfig = getSimulcastConfigFromOptions(createOptions.simulcastConfig),
233
- maxBitrate = videoParameters.maxBitrate
234
- )
235
- return videoParameters
236
- }
237
-
238
- private fun getLocalVideoTrack(): LocalVideoTrack? =
239
- fishjamClient
240
- .getLocalEndpoint()
241
- .tracks
242
- .values
243
- .filterIsInstance<LocalVideoTrack>()
244
- .firstOrNull()
245
-
246
- private fun getLocalAudioTrack(): LocalAudioTrack? =
247
- fishjamClient
248
- .getLocalEndpoint()
249
- .tracks
250
- .values
251
- .filterIsInstance<LocalAudioTrack>()
252
- .firstOrNull()
253
-
254
- private fun getLocalScreenShareTrack(): LocalScreenShareTrack? =
255
- fishjamClient
256
- .getLocalEndpoint()
257
- .tracks
258
- .values
259
- .filterIsInstance<LocalScreenShareTrack>()
260
- .firstOrNull()
261
-
262
- private fun ensureConnected() {
263
- if (!isConnected) {
264
- throw ClientNotConnectedError()
265
- }
266
- }
267
-
268
- private fun ensureVideoTrack() {
269
- if (getLocalVideoTrack() == null) {
270
- throw NoLocalVideoTrackError()
271
- }
272
- }
273
-
274
- private fun ensureAudioTrack() {
275
- if (getLocalAudioTrack() == null) {
276
- throw NoLocalAudioTrackError()
277
- }
278
- }
279
-
280
- private fun ensureScreenShareTrack() {
281
- if (getLocalScreenShareTrack() == null) {
282
- throw NoScreenShareTrackError()
283
- }
284
- }
285
-
286
- override fun onAuthError(reason: AuthError) {
287
- CoroutineScope(Dispatchers.Main).launch {
288
- connectPromise?.reject(ConnectionError(reason))
289
- connectPromise = null
290
- peerStatus = PeerStatus.Error
291
- }
292
- }
293
-
294
- fun joinRoom(
295
- url: String,
296
- peerToken: String,
297
- peerMetadata: Map<String, Any>,
298
- config: ConnectConfig,
299
- promise: Promise
300
- ) {
301
- if (connectPromise != null || peerStatus == PeerStatus.Connected) {
302
- promise.reject(JoinError("Room already joined or it's connecting. You must call leaveRoom() before calling joinRoom() again."))
303
- return
304
- }
305
-
306
- peerStatus = PeerStatus.Connecting
307
- connectPromise = promise
308
- localUserMetadata = mapOf("server" to emptyMap(), "peer" to peerMetadata)
309
- fishjamClient.connect(
310
- com.fishjamcloud.client.ConnectConfig(
311
- url,
312
- peerToken,
313
- peerMetadata,
314
- ReconnectConfig(
315
- config.reconnectConfig.maxAttempts,
316
- config.reconnectConfig.initialDelayMs,
317
- config.reconnectConfig.delayMs
318
- )
319
- )
320
- )
321
- }
322
-
323
- fun leaveRoom() {
324
- connectPromise?.reject(JoinError("leaveRoom called before connected"))
325
- connectPromise = null
326
-
327
- if (isScreenShareOn) {
328
- stopScreenShare()
329
- }
330
- isMicrophoneOn = false
331
- isCameraOn = false
332
- isScreenShareOn = false
333
- isConnected = false
334
- isCameraInitialized = false
335
- fishjamClient.leave {
336
- emitEndpoints()
337
- }
338
- }
339
-
340
- suspend fun startCamera(config: CameraConfig): Boolean {
341
- if (isCameraInitialized) {
342
- return true
343
- }
344
- if (!PermissionUtils.requestCameraPermission(appContext)) {
345
- emitEvent(EmitableEvent.warning("Camera permission not granted."))
346
- return false
347
- }
348
-
349
- val cameraTrack = createCameraTrack(config)
350
- cameraTrack.captureDeviceChangedListener = this
351
- setCameraTrackState(cameraTrack, config.cameraEnabled)
352
- emitEndpoints()
353
- isCameraInitialized = true
354
- return true
355
- }
356
-
357
- private suspend fun createCameraTrack(config: CameraConfig): LocalVideoTrack {
358
- val videoParameters = getVideoParametersFromOptions(config)
359
- videoSimulcastConfig = getSimulcastConfigFromOptions(config.simulcastConfig)
360
- return fishjamClient.createVideoTrack(
361
- videoParameters,
362
- config.videoTrackMetadata,
363
- config.cameraId
364
- )
365
- }
366
-
367
- private fun setCameraTrackState(
368
- cameraTrack: LocalVideoTrack,
369
- isEnabled: Boolean
370
- ) {
371
- cameraTrack.setEnabled(isEnabled)
372
- isCameraOn = isEnabled
373
- emitEvent(
374
- EmitableEvent.currentCameraChanged(
375
- cameraTrack.getCaptureDevice()?.toLocalCamera(),
376
- isEnabled,
377
- isCameraInitialized
378
- )
379
- )
380
- localCameraTracksChangedListenersManager.notifyListeners()
381
- }
382
-
383
- fun toggleCamera(): Boolean {
384
- ensureVideoTrack()
385
- getLocalVideoTrack()?.let { setCameraTrackState(it, !isCameraOn) }
386
- return isCameraOn
387
- }
388
-
389
- suspend fun flipCamera() {
390
- ensureVideoTrack()
391
- localTracksSwitchListenerManager.notifyWillSwitch()
392
- getLocalVideoTrack()?.flipCamera()
393
- localTracksSwitchListenerManager.notifySwitched()
394
- }
395
-
396
- suspend fun switchCamera(cameraId: String) {
397
- ensureVideoTrack()
398
- localTracksSwitchListenerManager.notifyWillSwitch()
399
- getLocalVideoTrack()?.switchCamera(cameraId)
400
- localTracksSwitchListenerManager.notifySwitched()
401
- }
402
-
403
- suspend fun startMicrophone() {
404
- // If microphone track already exist, just enable it
405
- if (getLocalAudioTrack() != null) {
406
- getLocalAudioTrack()?.let { setMicrophoneTrackState(it, true) }
407
- } else {
408
- if (!PermissionUtils.requestMicrophonePermission(appContext)) {
409
- emitEvent(EmitableEvent.warning("Microphone permission not granted."))
410
- return
411
- }
412
-
413
- val microphoneTrack = fishjamClient.createAudioTrack(getMicrophoneTrackMetadata(true))
414
- setMicrophoneTrackState(microphoneTrack, true)
415
- emitEndpoints()
416
- }
417
- }
418
-
419
- fun stopMicrophone() {
420
- if (getLocalAudioTrack() != null) {
421
- getLocalAudioTrack()?.let { setMicrophoneTrackState(it, false) }
422
- }
423
- }
424
-
425
- private fun setMicrophoneTrackState(
426
- microphoneTrack: LocalAudioTrack,
427
- isEnabled: Boolean
428
- ) {
429
- microphoneTrack.setEnabled(isEnabled)
430
- isMicrophoneOn = isEnabled
431
- updateLocalAudioTrackMetadata(getMicrophoneTrackMetadata(isEnabled))
432
- emitEvent(EmitableEvent.isMicrophoneOn(isEnabled))
433
- }
434
-
435
- suspend fun toggleMicrophone(): Boolean {
436
- if (isMicrophoneOn) {
437
- stopMicrophone()
438
- } else {
439
- startMicrophone()
440
- }
441
-
442
- return isMicrophoneOn
443
- }
444
-
445
- private fun getMicrophoneTrackMetadata(isEnabled: Boolean): Map<String, Any> =
446
- mapOf(
447
- "active" to isEnabled,
448
- "paused" to !isEnabled, // TODO: FCE-711,
449
- "type" to "microphone"
450
- )
451
-
452
- fun handleScreenSharePermission(promise: Promise) {
453
- screenSharePermissionPromise = promise
454
- if (!isScreenShareOn) {
455
- ensureConnected()
456
- val currentActivity = appContext?.currentActivity ?: throw ActivityNotFoundException()
457
-
458
- val mediaProjectionManager =
459
- appContext?.reactContext!!.getSystemService(
460
- AppCompatActivity.MEDIA_PROJECTION_SERVICE
461
- ) as MediaProjectionManager
462
- val intent = mediaProjectionManager.createScreenCaptureIntent()
463
- currentActivity.startActivityForResult(intent, SCREENSHARE_REQUEST)
464
- }
465
- }
466
-
467
- suspend fun startForegroundService(config: ForegroundServiceConfig) {
468
- foregroundServiceManager.updateServiceWithConfig(config)
469
- foregroundServiceManager.start()
470
- }
471
-
472
- fun stopForegroundService() {
473
- foregroundServiceManager.stop()
474
- }
475
-
476
- suspend fun toggleScreenShare(screenShareOptions: ScreenShareOptions) {
477
- this.screenShareMetadata = screenShareOptions.screenShareMetadata
478
- this.screenShareQuality = screenShareOptions.quality
479
- this.screenShareSimulcastConfig =
480
- getSimulcastConfigFromOptions(screenShareOptions.simulcastConfig)
481
-
482
- if (!isScreenShareOn) {
483
- ensureConnected()
484
- startScreenShare()
485
- } else {
486
- stopScreenShare()
487
- }
488
- }
489
-
490
- fun getPeers(): List<Map<String, Any?>> =
491
- getAllPeers().map { endpoint ->
492
- mapOf(
493
- "id" to endpoint.id,
494
- "isLocal" to (endpoint.id == fishjamClient.getLocalEndpoint().id),
495
- "metadata" to endpoint.metadata,
496
- "tracks" to
497
- endpoint.tracks.values.mapNotNull { track ->
498
- when (track) {
499
- is RemoteVideoTrack ->
500
- mapOf(
501
- "id" to track.id(),
502
- "type" to "Video",
503
- "metadata" to track.metadata,
504
- "encoding" to track.encoding?.rid,
505
- "encodingReason" to track.encodingReason?.value,
506
- "aspectRatio" to track.dimensions?.aspectRatio
507
- )
508
-
509
- is RemoteAudioTrack ->
510
- mapOf(
511
- "id" to track.id(),
512
- "type" to "Audio",
513
- "metadata" to track.metadata,
514
- "vadStatus" to
515
- when (track.vadStatus) {
516
- Server.MediaEvent.VadNotification.Status.STATUS_SPEECH -> "speech"
517
- else -> "silence"
518
- }
519
- )
520
-
521
- is LocalVideoTrack ->
522
- mapOf(
523
- "id" to track.id(),
524
- "type" to "Video",
525
- "metadata" to track.metadata,
526
- "aspectRatio" to track.dimensions?.aspectRatio
527
- )
528
-
529
- is LocalScreenShareTrack ->
530
- mapOf(
531
- "id" to track.id(),
532
- "type" to "Video",
533
- "metadata" to track.metadata,
534
- "aspectRatio" to track.dimensions?.aspectRatio
535
- )
536
-
537
- is LocalAudioTrack ->
538
- mapOf(
539
- "id" to track.id(),
540
- "type" to "Audio",
541
- "metadata" to track.metadata
542
- )
543
-
544
- is VideoTrack -> // TODO(FCE-1418): Remove after refactoring LocalVideoTrack
545
- mapOf(
546
- "id" to track.id(),
547
- "type" to "Video",
548
- "metadata" to track.metadata,
549
- "aspectRatio" to track.dimensions?.aspectRatio
550
- )
551
-
552
- else -> {
553
- null
554
- }
555
- }
556
- }
557
- )
558
- }
559
-
560
- fun getCaptureDevices(): List<Map<String, Any>> {
561
- val devices = LocalVideoTrack.getCaptureDevices(appContext?.reactContext!!)
562
- return devices.map { device ->
563
- device.toLocalCamera()
564
- }
565
- }
566
-
567
- fun getCurrentCaptureDevice(): Map<String, Any>? = getLocalVideoTrack()?.getCaptureDevice()?.toLocalCamera()
568
-
569
- fun updatePeerMetadata(metadata: Metadata) {
570
- ensureConnected()
571
- fishjamClient.updatePeerMetadata(metadata)
572
- }
573
-
574
- private fun updateTrackMetadata(
575
- trackId: String,
576
- metadata: Metadata
577
- ) {
578
- fishjamClient.updateTrackMetadata(trackId, metadata)
579
- emitEndpoints()
580
- }
581
-
582
- fun updateLocalVideoTrackMetadata(metadata: Metadata) {
583
- ensureVideoTrack()
584
- getLocalVideoTrack()?.let {
585
- updateTrackMetadata(it.id(), metadata)
586
- }
587
- }
588
-
589
- private fun updateLocalAudioTrackMetadata(metadata: Metadata) {
590
- ensureAudioTrack()
591
- getLocalAudioTrack()?.let {
592
- updateTrackMetadata(it.id(), metadata)
593
- }
594
- }
595
-
596
- fun updateLocalScreenShareTrackMetadata(metadata: Metadata) {
597
- ensureScreenShareTrack()
598
- getLocalScreenShareTrack()?.let {
599
- updateTrackMetadata(it.id(), metadata)
600
- }
601
- }
602
-
603
- fun setOutputAudioDevice(audioDevice: String) {
604
- audioSwitchManager?.selectAudioOutput(AudioDeviceKind.fromTypeName(audioDevice))
605
- }
606
-
607
- fun startAudioSwitcher() {
608
- audioSwitchManager?.let {
609
- it.start(this::emitAudioDeviceEvent)
610
- emitAudioDeviceEvent(
611
- it.availableAudioDevices(),
612
- it.selectedAudioDevice()
613
- )
614
- }
615
- }
616
-
617
- fun stopAudioSwitcher() {
618
- audioSwitchManager?.stop()
619
- }
620
-
621
- private fun toggleTrackEncoding(
622
- encoding: String,
623
- trackId: String,
624
- simulcastConfig: SimulcastConfig
625
- ): SimulcastConfig {
626
- val trackEncoding = encoding.toTrackEncoding()
627
-
628
- val isTrackEncodingActive = simulcastConfig.activeEncodings.contains(trackEncoding)
629
-
630
- if (isTrackEncodingActive) {
631
- fishjamClient.disableTrackEncoding(trackId, trackEncoding)
632
- } else {
633
- fishjamClient.enableTrackEncoding(trackId, trackEncoding)
634
- }
635
-
636
- val updatedActiveEncodings =
637
- if (isTrackEncodingActive) {
638
- simulcastConfig.activeEncodings.filter { it != trackEncoding }
639
- } else {
640
- simulcastConfig.activeEncodings + trackEncoding
641
- }
642
-
643
- return SimulcastConfig(
644
- enabled = true,
645
- activeEncodings = updatedActiveEncodings
646
- )
647
- }
648
-
649
- fun toggleScreenShareTrackEncoding(encoding: String): Map<String, Any> {
650
- ensureScreenShareTrack()
651
- getLocalScreenShareTrack()?.let {
652
- screenShareSimulcastConfig =
653
- toggleTrackEncoding(encoding, it.id(), screenShareSimulcastConfig)
654
- }
655
- return getSimulcastConfigAsRNMap(screenShareSimulcastConfig)
656
- }
657
-
658
- fun setScreenShareTrackBandwidth(bandwidth: Int) {
659
- ensureScreenShareTrack()
660
- getLocalScreenShareTrack()?.let {
661
- fishjamClient.setTrackBandwidth(it.id(), TrackBandwidthLimit.BandwidthLimit(bandwidth))
662
- }
663
- }
664
-
665
- fun setScreenShareTrackEncodingBandwidth(
666
- encoding: String,
667
- bandwidth: Int
668
- ) {
669
- ensureScreenShareTrack()
670
- getLocalScreenShareTrack()?.let {
671
- fishjamClient.setEncodingBandwidth(
672
- it.id(),
673
- encoding,
674
- TrackBandwidthLimit.BandwidthLimit(bandwidth)
675
- )
676
- }
677
- }
678
-
679
- fun setTargetTrackEncoding(
680
- trackId: String,
681
- encoding: String
682
- ) {
683
- ensureConnected()
684
- fishjamClient.setTargetTrackEncoding(trackId, encoding.toTrackEncoding())
685
- }
686
-
687
- fun toggleVideoTrackEncoding(encoding: String): Map<String, Any?> {
688
- ensureVideoTrack()
689
- val trackId = getLocalVideoTrack()?.id() ?: return emptyMap()
690
- videoSimulcastConfig = toggleTrackEncoding(encoding, trackId, videoSimulcastConfig)
691
-
692
- val event = EmitableEvent.simulcastConfigUpdate(videoSimulcastConfig)
693
- emitEvent(event)
694
-
695
- return event.data
696
- }
697
-
698
- fun setVideoTrackEncodingBandwidth(
699
- encoding: String,
700
- bandwidth: Int
701
- ) {
702
- ensureVideoTrack()
703
- getLocalVideoTrack()?.let {
704
- fishjamClient.setEncodingBandwidth(
705
- it.id(),
706
- encoding,
707
- TrackBandwidthLimit.BandwidthLimit(bandwidth)
708
- )
709
- }
710
- }
711
-
712
- fun setVideoTrackBandwidth(bandwidth: Int) {
713
- ensureVideoTrack()
714
- getLocalVideoTrack()?.let {
715
- fishjamClient.setTrackBandwidth(it.id(), TrackBandwidthLimit.BandwidthLimit(bandwidth))
716
- }
717
- }
718
-
719
- fun changeWebRTCLoggingSeverity(severity: String) {
720
- when (severity) {
721
- "verbose" -> fishjamClient.changeWebRTCLoggingSeverity(Logging.Severity.LS_VERBOSE)
722
-
723
- "info" -> fishjamClient.changeWebRTCLoggingSeverity(Logging.Severity.LS_INFO)
724
-
725
- "error" -> fishjamClient.changeWebRTCLoggingSeverity(Logging.Severity.LS_ERROR)
726
-
727
- "warning" -> fishjamClient.changeWebRTCLoggingSeverity(Logging.Severity.LS_WARNING)
728
-
729
- "none" -> fishjamClient.changeWebRTCLoggingSeverity(Logging.Severity.LS_NONE)
730
-
731
- else -> {
732
- throw CodedException("Severity with name=$severity not found")
733
- }
734
- }
735
- }
736
-
737
- private fun rtcOutboundStatsToRNMap(stats: RTCOutboundStats): Map<String, Any?> {
738
- val innerMap = mutableMapOf<String, Double>()
739
- innerMap["bandwidth"] = stats.qualityLimitationDurations?.bandwidth ?: 0.0
740
- innerMap["cpu"] = stats.qualityLimitationDurations?.cpu ?: 0.0
741
- innerMap["none"] = stats.qualityLimitationDurations?.none ?: 0.0
742
- innerMap["other"] = stats.qualityLimitationDurations?.other ?: 0.0
743
-
744
- val res = mutableMapOf<String, Any?>()
745
- res["kind"] = stats.kind
746
- res["rid"] = stats.rid
747
- res["bytesSent"] = stats.bytesSent?.toInt() ?: 0
748
- res["targetBitrate"] = stats.targetBitrate ?: 0.0
749
- res["packetsSent"] = stats.packetsSent?.toInt() ?: 0
750
- res["framesEncoded"] = stats.framesEncoded?.toInt() ?: 0
751
- res["framesPerSecond"] = stats.framesPerSecond ?: 0.0
752
- res["frameWidth"] = stats.frameWidth?.toInt() ?: 0
753
- res["frameHeight"] = stats.frameHeight?.toInt() ?: 0
754
- res["qualityLimitationDurations"] = innerMap
755
-
756
- return res
757
- }
758
-
759
- private fun rtcInboundStatsToRNMap(stats: RTCInboundStats): Map<String, Any?> {
760
- val res = mutableMapOf<String, Any?>()
761
- res["kind"] = stats.kind
762
- res["jitter"] = stats.jitter ?: 0.0
763
- res["packetsLost"] = stats.packetsLost ?: 0
764
- res["packetsReceived"] = stats.packetsReceived?.toInt() ?: 0
765
- res["bytesReceived"] = stats.bytesReceived?.toInt() ?: 0
766
- res["framesReceived"] = stats.framesReceived ?: 0
767
- res["frameWidth"] = stats.frameWidth?.toInt() ?: 0
768
- res["frameHeight"] = stats.frameHeight?.toInt() ?: 0
769
- res["framesPerSecond"] = stats.framesPerSecond ?: 0.0
770
- res["framesDropped"] = stats.framesDropped?.toInt() ?: 0
771
-
772
- return res
773
- }
774
-
775
- suspend fun getStatistics(): Map<String, Map<String, Any?>> {
776
- val newMap = mutableMapOf<String, Map<String, Any?>>()
777
- val stats = fishjamClient.getStats()
778
- stats.forEach { entry ->
779
- newMap[entry.key] =
780
- if (entry.value is RTCInboundStats) {
781
- rtcInboundStatsToRNMap(
782
- entry.value as RTCInboundStats
783
- )
784
- } else {
785
- rtcOutboundStatsToRNMap(entry.value as RTCOutboundStats)
786
- }
787
- }
788
- return newMap
789
- }
790
-
791
- private suspend fun startScreenShare() {
792
- val videoParameters = getScreenShareVideoParameters()
793
- if (mediaProjectionIntent == null) {
794
- throw MissingScreenSharePermission()
795
- }
796
-
797
- foregroundServiceManager.updateService { screenSharingEnabled = true }
798
- foregroundServiceManager.start()
799
-
800
- fishjamClient.createScreenShareTrack(
801
- mediaProjectionIntent!!,
802
- videoParameters,
803
- screenShareMetadata
804
- )
805
- mediaProjectionIntent = null
806
-
807
- setScreenShareTrackState(true)
808
- emitEndpoints()
809
- }
810
-
811
- private fun getScreenShareVideoParameters(): VideoParameters {
812
- val videoParameters =
813
- when (screenShareQuality) {
814
- "VGA" -> VideoParameters.presetScreenShareVGA
815
- "HD5" -> VideoParameters.presetScreenShareHD5
816
- "HD15" -> VideoParameters.presetScreenShareHD15
817
- "FHD15" -> VideoParameters.presetScreenShareFHD15
818
- "FHD30" -> VideoParameters.presetScreenShareFHD30
819
- else -> VideoParameters.presetScreenShareHD15
820
- }
821
- val dimensions = videoParameters.dimensions.flip()
822
- return videoParameters.copy(
823
- dimensions = dimensions,
824
- simulcastConfig = screenShareSimulcastConfig,
825
- maxBitrate = videoParameters.maxBitrate
826
- )
827
- }
828
-
829
- private fun setScreenShareTrackState(isEnabled: Boolean) {
830
- isScreenShareOn = isEnabled
831
- emitEvent(EmitableEvent.isScreenShareOn(isEnabled))
832
- }
833
-
834
- private fun stopScreenShare() {
835
- ensureScreenShareTrack()
836
- coroutineScope.launch {
837
- foregroundServiceManager.updateService { screenSharingEnabled = false }
838
- foregroundServiceManager.start()
839
- val screenShareTrack =
840
- fishjamClient.getLocalEndpoint().tracks.values.first { track ->
841
- track is LocalScreenShareTrack
842
- } as? LocalScreenShareTrack
843
- if (screenShareTrack != null) {
844
- fishjamClient.removeTrack(screenShareTrack.id())
845
- }
846
- setScreenShareTrackState(false)
847
- emitEndpoints()
848
- }
849
- }
850
-
851
- private fun emitEvent(event: EmitableEvent) {
852
- CoroutineScope(Dispatchers.Main).launch {
853
- RNFishjamClient.sendEvent(event)
854
- }
855
- }
856
-
857
- private fun emitEndpoints() {
858
- emitEvent(EmitableEvent.peersUpdate(getPeers()))
859
- }
860
-
861
- private fun emitAudioDeviceEvent(
862
- audioDevices: List<AudioDevice>,
863
- selectedDevice: AudioDevice?
864
- ) {
865
- emitEvent(EmitableEvent.audioDeviceUpdate(audioDevices, selectedDevice))
866
- }
867
-
868
- private fun getSimulcastConfigAsRNMap(simulcastConfig: SimulcastConfig): Map<String, Any> =
869
- mapOf(
870
- "enabled" to simulcastConfig.enabled,
871
- "activeEncodings" to
872
- simulcastConfig.activeEncodings.map {
873
- it.rid
874
- }
875
- )
876
-
877
- override fun onJoined(
878
- peerID: String,
879
- peersInRoom: MutableMap<String, Endpoint>
880
- ) {
881
- CoroutineScope(Dispatchers.Main).launch {
882
- isConnected = true
883
- connectPromise?.resolve(null)
884
- connectPromise = null
885
- emitEndpoints()
886
- peerStatus = PeerStatus.Connected
887
- }
888
- }
889
-
890
- override fun onJoinError(metadata: Any) {
891
- CoroutineScope(Dispatchers.Main).launch {
892
- connectPromise?.reject(JoinError(metadata))
893
- connectPromise = null
894
- }
895
- }
896
-
897
- private fun addOrUpdateTrack(track: Track) {
898
- emitEndpoints()
899
- trackUpdateListenersManager.notifyListeners()
900
- }
901
-
902
- override fun onTrackReady(track: Track) {
903
- CoroutineScope(Dispatchers.Main).launch {
904
- addOrUpdateTrack(track)
905
- }
906
- }
907
-
908
- override fun onTrackAdded(track: Track) {
909
- CoroutineScope(Dispatchers.Main).launch {
910
- trackUpdateListenersManager.notifyListeners()
911
- }
912
- }
913
-
914
- override fun onTrackRemoved(track: Track) {
915
- CoroutineScope(Dispatchers.Main).launch {
916
- emitEndpoints()
917
- trackUpdateListenersManager.notifyListeners()
918
- }
919
- }
920
-
921
- override fun onTrackUpdated(track: Track) {
922
- CoroutineScope(Dispatchers.Main).launch {
923
- emitEndpoints()
924
- trackUpdateListenersManager.notifyListeners()
925
- }
926
- }
927
-
928
- override fun onPeerJoined(peer: Peer) {
929
- CoroutineScope(Dispatchers.Main).launch {
930
- emitEndpoints()
931
- trackUpdateListenersManager.notifyListeners()
932
- }
933
- }
934
-
935
- override fun onPeerLeft(peer: Peer) {
936
- CoroutineScope(Dispatchers.Main).launch {
937
- emitEndpoints()
938
- trackUpdateListenersManager.notifyListeners()
939
- }
940
- }
941
-
942
- override fun onPeerUpdated(peer: Peer) {}
943
-
944
- override fun onBandwidthEstimationChanged(estimation: Long) {
945
- emitEvent(EmitableEvent.bandwidthEstimation(estimation))
946
- }
947
-
948
- override fun onDisconnected() {
949
- peerStatus = PeerStatus.Idle
950
- }
951
-
952
- override fun onSocketClose(
953
- code: Int,
954
- reason: String
955
- ) {
956
- CoroutineScope(Dispatchers.Main).launch {
957
- connectPromise?.reject(SocketClosedError(code, reason))
958
- connectPromise = null
959
- peerStatus = PeerStatus.Idle
960
- }
961
- }
962
-
963
- override fun onSocketError(t: Throwable) {
964
- CoroutineScope(Dispatchers.Main).launch {
965
- connectPromise?.reject(SocketError(t.message ?: t.toString()))
966
- connectPromise = null
967
- peerStatus = PeerStatus.Error
968
- }
969
- }
970
-
971
- override fun onReconnected() {
972
- reconnectionStatus = ReconnectionStatus.Reconnecting
973
- }
974
-
975
- override fun onReconnectionStarted() {
976
- reconnectionStatus = ReconnectionStatus.Idle
977
- }
978
-
979
- override fun onReconnectionRetriesLimitReached() {
980
- reconnectionStatus = ReconnectionStatus.Error
981
- }
982
-
983
- override fun onCaptureDeviceChanged(captureDevice: CaptureDevice?) {
984
- emitEvent(
985
- EmitableEvent.currentCameraChanged(
986
- captureDevice?.toLocalCamera(),
987
- isCameraOn,
988
- isCameraInitialized
989
- )
990
- )
991
- }
992
-
993
- override fun onIncompatibleTracksDetected() {
994
- // TODO: FCE-1215 Add proper url after docs are updated
995
- emitEvent(
996
- EmitableEvent.warning(
997
- "Incompatible track detected. This usually means your device is missing codecs negotiated for the room. Visit https://docs.fishjam.io/category/react-native-integration for information."
998
- )
999
- )
1000
- }
1001
- }