@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.
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +104 -20
- package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +83 -99
- package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +21 -30
- package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +6 -2
- package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +41 -3
- package/android/src/main/java/io/fishjam/reactnative/extensions/CaptureDevice.kt +17 -0
- package/android/src/main/java/io/fishjam/reactnative/foregroundService/FishjamForegroundService.kt +10 -4
- package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceManager.kt +41 -70
- package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceState.kt +46 -0
- package/android/src/main/java/io/fishjam/reactnative/managers/ListenerManager.kt +22 -0
- package/android/src/main/java/io/fishjam/reactnative/managers/LocalCameraTracksChangedListenersManager.kt +2 -15
- package/android/src/main/java/io/fishjam/reactnative/managers/LocalTracksSwitchListenersManager.kt +1 -11
- package/android/src/main/java/io/fishjam/reactnative/managers/TracksUpdateListenersManager.kt +1 -15
- package/build/RNFishjamClientModule.d.ts +28 -12
- package/build/RNFishjamClientModule.d.ts.map +1 -1
- package/build/RNFishjamClientModule.js +19 -4
- package/build/RNFishjamClientModule.js.map +1 -1
- package/build/common/client.d.ts +0 -4
- package/build/common/client.d.ts.map +1 -1
- package/build/common/client.js +0 -4
- package/build/common/client.js.map +1 -1
- package/build/common/metadata.d.ts +1 -1
- package/build/common/metadata.js +1 -1
- package/build/common/metadata.js.map +1 -1
- package/build/common/webRTC.d.ts +2 -1
- package/build/common/webRTC.d.ts.map +1 -1
- package/build/common/webRTC.js.map +1 -1
- package/build/components/FishjamRoom/GridTrackItem.d.ts +11 -0
- package/build/components/FishjamRoom/GridTrackItem.d.ts.map +1 -0
- package/build/components/FishjamRoom/GridTrackItem.js +56 -0
- package/build/components/FishjamRoom/GridTrackItem.js.map +1 -0
- package/build/components/FishjamRoom/VideosGrid.d.ts +3 -0
- package/build/components/FishjamRoom/VideosGrid.d.ts.map +1 -0
- package/build/components/FishjamRoom/VideosGrid.js +20 -0
- package/build/components/FishjamRoom/VideosGrid.js.map +1 -0
- package/build/components/FishjamRoom/index.d.ts +6 -0
- package/build/components/FishjamRoom/index.d.ts.map +1 -0
- package/build/components/FishjamRoom/index.js +29 -0
- package/build/components/FishjamRoom/index.js.map +1 -0
- package/build/components/FishjamRoom/parsePeersToTracks.d.ts +4 -0
- package/build/components/FishjamRoom/parsePeersToTracks.d.ts.map +1 -0
- package/build/components/FishjamRoom/parsePeersToTracks.js +34 -0
- package/build/components/FishjamRoom/parsePeersToTracks.js.map +1 -0
- package/build/components/VideoRendererView.d.ts +6 -1
- package/build/components/VideoRendererView.d.ts.map +1 -1
- package/build/components/VideoRendererView.js.map +1 -1
- package/build/debug/stats/useRTCStatistics.d.ts.map +1 -1
- package/build/debug/stats/useRTCStatistics.js +13 -13
- package/build/debug/stats/useRTCStatistics.js.map +1 -1
- package/build/hooks/internal/useFishjamEvent.d.ts +3 -0
- package/build/hooks/internal/useFishjamEvent.d.ts.map +1 -0
- package/build/hooks/internal/useFishjamEvent.js +11 -0
- package/build/hooks/internal/useFishjamEvent.js.map +1 -0
- package/build/hooks/internal/useFishjamEventState.d.ts +3 -0
- package/build/hooks/internal/useFishjamEventState.d.ts.map +1 -0
- package/build/hooks/internal/useFishjamEventState.js +18 -0
- package/build/hooks/internal/useFishjamEventState.js.map +1 -0
- package/build/hooks/useAppScreenShare.d.ts.map +1 -1
- package/build/hooks/useAppScreenShare.js +6 -8
- package/build/hooks/useAppScreenShare.js.map +1 -1
- package/build/hooks/useAudioSettings.d.ts.map +1 -1
- package/build/hooks/useAudioSettings.js +8 -11
- package/build/hooks/useAudioSettings.js.map +1 -1
- package/build/hooks/useBandwidthEstimation.d.ts.map +1 -1
- package/build/hooks/useBandwidthEstimation.js +3 -4
- package/build/hooks/useBandwidthEstimation.js.map +1 -1
- package/build/hooks/useCamera.d.ts +6 -2
- package/build/hooks/useCamera.d.ts.map +1 -1
- package/build/hooks/useCamera.js +19 -23
- package/build/hooks/useCamera.js.map +1 -1
- package/build/hooks/useConnection.d.ts +42 -0
- package/build/hooks/useConnection.d.ts.map +1 -0
- package/build/hooks/useConnection.js +33 -0
- package/build/hooks/useConnection.js.map +1 -0
- package/build/hooks/useForegroundService.d.ts +12 -20
- package/build/hooks/useForegroundService.d.ts.map +1 -1
- package/build/hooks/useForegroundService.js +14 -4
- package/build/hooks/useForegroundService.js.map +1 -1
- package/build/hooks/useMicrophone.d.ts.map +1 -1
- package/build/hooks/useMicrophone.js +5 -11
- package/build/hooks/useMicrophone.js.map +1 -1
- package/build/hooks/usePeerStatus.d.ts +2 -3
- package/build/hooks/usePeerStatus.d.ts.map +1 -1
- package/build/hooks/usePeerStatus.js +4 -10
- package/build/hooks/usePeerStatus.js.map +1 -1
- package/build/hooks/usePeers.d.ts +50 -11
- package/build/hooks/usePeers.d.ts.map +1 -1
- package/build/hooks/usePeers.js +42 -18
- package/build/hooks/usePeers.js.map +1 -1
- package/build/hooks/useReconnection.d.ts +1 -1
- package/build/hooks/useReconnection.d.ts.map +1 -1
- package/build/hooks/useReconnection.js +4 -10
- package/build/hooks/useReconnection.js.map +1 -1
- package/build/hooks/useScreenShare.d.ts.map +1 -1
- package/build/hooks/useScreenShare.js +11 -16
- package/build/hooks/useScreenShare.js.map +1 -1
- package/build/hooks/useUpdatePeerMetadata.d.ts +15 -0
- package/build/hooks/useUpdatePeerMetadata.d.ts.map +1 -0
- package/build/hooks/useUpdatePeerMetadata.js +21 -0
- package/build/hooks/useUpdatePeerMetadata.js.map +1 -0
- package/build/index.d.ts +24 -16
- package/build/index.d.ts.map +1 -1
- package/build/index.js +18 -6
- package/build/index.js.map +1 -1
- package/build/types.d.ts +1 -1
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/build/utils/errorListener.d.ts.map +1 -1
- package/build/utils/errorListener.js +3 -4
- package/build/utils/errorListener.js.map +1 -1
- package/ios/Events.swift +94 -19
- package/ios/RNFishjamClient.podspec +1 -1
- package/ios/RNFishjamClient.swift +84 -114
- package/ios/RNFishjamClientModule.swift +14 -10
- package/ios/Utils.swift +0 -20
- package/ios/VideoPreviewView.swift +13 -13
- package/ios/VideoRendererView.swift +28 -25
- package/ios/VideoRendererViewModule.swift +8 -4
- package/ios/extensions/AVCaptureDevice.swift +20 -0
- package/package.json +11 -14
- package/plugin/build/withFishjamAndroid.js +18 -20
- package/plugin/build/withFishjamIos.js +99 -103
- package/build/hooks/useFishjamEvent.d.ts +0 -18
- package/build/hooks/useFishjamEvent.d.ts.map +0 -1
- package/build/hooks/useFishjamEvent.js +0 -27
- package/build/hooks/useFishjamEvent.js.map +0 -1
package/android/build.gradle
CHANGED
|
@@ -1,28 +1,112 @@
|
|
|
1
1
|
package io.fishjam.reactnative
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import com.fishjamcloud.client.ReconnectionStatus
|
|
4
|
+
import com.fishjamcloud.client.models.SimulcastConfig
|
|
5
|
+
import com.twilio.audioswitch.AudioDevice
|
|
6
|
+
import io.fishjam.reactnative.extensions.LocalCamera
|
|
7
|
+
|
|
8
|
+
enum class PeerStatus(
|
|
9
|
+
val status: String
|
|
10
|
+
) {
|
|
11
|
+
Connecting("connecting"),
|
|
12
|
+
Connected("connected"),
|
|
13
|
+
Idle("idle"),
|
|
14
|
+
Error("error")
|
|
9
15
|
}
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
class EmitableEvent private constructor(
|
|
18
|
+
private val event: EventName,
|
|
19
|
+
private val eventContent: Any? = null
|
|
20
|
+
) {
|
|
21
|
+
enum class EventName {
|
|
22
|
+
IsMicrophoneOn,
|
|
23
|
+
IsScreenShareOn,
|
|
24
|
+
SimulcastConfigUpdate,
|
|
25
|
+
PeersUpdate,
|
|
26
|
+
AudioDeviceUpdate,
|
|
27
|
+
BandwidthEstimation,
|
|
28
|
+
Warning,
|
|
29
|
+
PeerStatusChanged,
|
|
30
|
+
ReconnectionStatusChanged,
|
|
31
|
+
CurrentCameraChanged
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
val name: String
|
|
35
|
+
get() = event.name
|
|
36
|
+
|
|
37
|
+
val data: Map<String, Any?>
|
|
38
|
+
get() = mapOf(event.name to eventContent)
|
|
24
39
|
|
|
25
40
|
companion object {
|
|
26
|
-
|
|
41
|
+
fun isMicrophoneOn(enabled: Boolean) = EmitableEvent(EventName.IsMicrophoneOn, enabled)
|
|
42
|
+
|
|
43
|
+
fun isScreenShareOn(enabled: Boolean) = EmitableEvent(EventName.IsScreenShareOn, enabled)
|
|
44
|
+
|
|
45
|
+
fun bandwidthEstimation(estimation: Long) = EmitableEvent(EventName.BandwidthEstimation, estimation.toFloat())
|
|
46
|
+
|
|
47
|
+
fun warning(message: String) = EmitableEvent(EventName.Warning, message)
|
|
48
|
+
|
|
49
|
+
fun peerStatusChanged(peerStatus: PeerStatus) = EmitableEvent(EventName.PeerStatusChanged, peerStatus.status)
|
|
50
|
+
|
|
51
|
+
fun reconnectionStatusChanged(reconnectionStatus: ReconnectionStatus) =
|
|
52
|
+
EmitableEvent(EventName.ReconnectionStatusChanged, reconnectionStatus.status)
|
|
53
|
+
|
|
54
|
+
fun currentCameraChanged(
|
|
55
|
+
localCamera: LocalCamera?,
|
|
56
|
+
isCameraOn: Boolean
|
|
57
|
+
) = EmitableEvent(
|
|
58
|
+
EventName.CurrentCameraChanged,
|
|
59
|
+
mapOf(
|
|
60
|
+
"currentCamera" to localCamera,
|
|
61
|
+
"isCameraOn" to isCameraOn
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
fun simulcastConfigUpdate(simulcastConfig: SimulcastConfig) =
|
|
66
|
+
EmitableEvent(
|
|
67
|
+
EventName.SimulcastConfigUpdate,
|
|
68
|
+
mapOf(
|
|
69
|
+
"enabled" to simulcastConfig.enabled,
|
|
70
|
+
"activeEncodings" to simulcastConfig.activeEncodings.map { it.rid }
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
fun peersUpdate(peersData: List<Map<String, Any?>>) = EmitableEvent(EventName.PeersUpdate, peersData)
|
|
75
|
+
|
|
76
|
+
fun audioDeviceUpdate(
|
|
77
|
+
audioDevices: List<AudioDevice>,
|
|
78
|
+
selectedDevice: AudioDevice?
|
|
79
|
+
): EmitableEvent {
|
|
80
|
+
val audioDeviceAsMap = { audioDevice: AudioDevice ->
|
|
81
|
+
mapOf(
|
|
82
|
+
"name" to audioDevice.name,
|
|
83
|
+
"type" to AudioDeviceKind.fromAudioDevice(audioDevice)?.typeName
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return EmitableEvent(
|
|
88
|
+
EventName.AudioDeviceUpdate,
|
|
89
|
+
mapOf(
|
|
90
|
+
"selectedDevice" to (
|
|
91
|
+
if (selectedDevice != null) {
|
|
92
|
+
audioDeviceAsMap(
|
|
93
|
+
selectedDevice
|
|
94
|
+
)
|
|
95
|
+
} else {
|
|
96
|
+
null
|
|
97
|
+
}
|
|
98
|
+
),
|
|
99
|
+
"availableDevices" to
|
|
100
|
+
audioDevices.map { audioDevice ->
|
|
101
|
+
audioDeviceAsMap(
|
|
102
|
+
audioDevice
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
val allEvents: Array<String>
|
|
110
|
+
get() = EventName.entries.map { it.name }.toTypedArray()
|
|
27
111
|
}
|
|
28
112
|
}
|
|
@@ -7,6 +7,9 @@ import android.media.projection.MediaProjectionManager
|
|
|
7
7
|
import androidx.appcompat.app.AppCompatActivity
|
|
8
8
|
import com.fishjamcloud.client.FishjamClient
|
|
9
9
|
import com.fishjamcloud.client.FishjamClientListener
|
|
10
|
+
import com.fishjamcloud.client.ReconnectionStatus
|
|
11
|
+
import com.fishjamcloud.client.media.CaptureDevice
|
|
12
|
+
import com.fishjamcloud.client.media.CaptureDeviceChangedListener
|
|
10
13
|
import com.fishjamcloud.client.media.LocalAudioTrack
|
|
11
14
|
import com.fishjamcloud.client.media.LocalScreenShareTrack
|
|
12
15
|
import com.fishjamcloud.client.media.LocalVideoTrack
|
|
@@ -27,6 +30,8 @@ import com.twilio.audioswitch.AudioDevice
|
|
|
27
30
|
import expo.modules.kotlin.AppContext
|
|
28
31
|
import expo.modules.kotlin.Promise
|
|
29
32
|
import expo.modules.kotlin.exception.CodedException
|
|
33
|
+
import fishjam.media_events.server.Server
|
|
34
|
+
import io.fishjam.reactnative.extensions.toLocalCamera
|
|
30
35
|
import io.fishjam.reactnative.foregroundService.ForegroundServiceManager
|
|
31
36
|
import io.fishjam.reactnative.managers.LocalCameraTracksChangedListenersManager
|
|
32
37
|
import io.fishjam.reactnative.managers.LocalTracksSwitchListenersManager
|
|
@@ -40,7 +45,8 @@ import org.webrtc.Logging
|
|
|
40
45
|
|
|
41
46
|
class RNFishjamClient(
|
|
42
47
|
val sendEvent: (name: String, data: Map<String, Any?>) -> Unit
|
|
43
|
-
) : FishjamClientListener
|
|
48
|
+
) : FishjamClientListener,
|
|
49
|
+
CaptureDeviceChangedListener {
|
|
44
50
|
private val SCREENSHARE_REQUEST = 1
|
|
45
51
|
|
|
46
52
|
var isMicrophoneOn = false
|
|
@@ -68,14 +74,21 @@ class RNFishjamClient(
|
|
|
68
74
|
|
|
69
75
|
var appContext: AppContext? = null
|
|
70
76
|
|
|
71
|
-
var peerStatus = PeerStatus.
|
|
77
|
+
var peerStatus = PeerStatus.Idle
|
|
72
78
|
private set(value) {
|
|
73
79
|
field = value
|
|
74
|
-
|
|
75
|
-
emitEvent(event, mapOf(event.name to value))
|
|
80
|
+
emitEvent(EmitableEvent.peerStatusChanged(value))
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
|
|
83
|
+
var reconnectionStatus = ReconnectionStatus.Idle
|
|
84
|
+
private set(value) {
|
|
85
|
+
field = value
|
|
86
|
+
emitEvent(EmitableEvent.reconnectionStatusChanged(value))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private val foregroundServiceManager by lazy {
|
|
90
|
+
ForegroundServiceManager(appContext ?: throw CodedException("appContext not found"))
|
|
91
|
+
}
|
|
79
92
|
|
|
80
93
|
companion object {
|
|
81
94
|
val trackUpdateListenersManager = TracksUpdateListenersManager()
|
|
@@ -236,7 +249,7 @@ class RNFishjamClient(
|
|
|
236
249
|
CoroutineScope(Dispatchers.Main).launch {
|
|
237
250
|
connectPromise?.reject(ConnectionError(reason))
|
|
238
251
|
connectPromise = null
|
|
239
|
-
peerStatus = PeerStatus.
|
|
252
|
+
peerStatus = PeerStatus.Error
|
|
240
253
|
}
|
|
241
254
|
}
|
|
242
255
|
|
|
@@ -247,14 +260,14 @@ class RNFishjamClient(
|
|
|
247
260
|
config: ConnectConfig,
|
|
248
261
|
promise: Promise
|
|
249
262
|
) {
|
|
250
|
-
peerStatus = PeerStatus.
|
|
263
|
+
peerStatus = PeerStatus.Connecting
|
|
251
264
|
connectPromise = promise
|
|
252
265
|
localUserMetadata = mapOf("server" to emptyMap(), "peer" to peerMetadata)
|
|
253
266
|
fishjamClient.connect(
|
|
254
267
|
com.fishjamcloud.client.ConnectConfig(
|
|
255
268
|
url,
|
|
256
269
|
peerToken,
|
|
257
|
-
|
|
270
|
+
peerMetadata,
|
|
258
271
|
ReconnectConfig(
|
|
259
272
|
config.reconnectConfig.maxAttempts,
|
|
260
273
|
config.reconnectConfig.initialDelayMs,
|
|
@@ -278,20 +291,22 @@ class RNFishjamClient(
|
|
|
278
291
|
}
|
|
279
292
|
}
|
|
280
293
|
|
|
281
|
-
suspend fun startCamera(config: CameraConfig) {
|
|
294
|
+
suspend fun startCamera(config: CameraConfig): Boolean {
|
|
282
295
|
if (isCameraInitialized) {
|
|
283
|
-
|
|
284
|
-
return
|
|
296
|
+
emitEvent(EmitableEvent.warning("Camera already started. You may only call startCamera once before leaveRoom is called."))
|
|
297
|
+
return true
|
|
285
298
|
}
|
|
286
299
|
if (!PermissionUtils.requestCameraPermission(appContext)) {
|
|
287
|
-
|
|
288
|
-
return
|
|
300
|
+
emitEvent(EmitableEvent.warning("Camera permission not granted."))
|
|
301
|
+
return false
|
|
289
302
|
}
|
|
290
303
|
|
|
291
304
|
val cameraTrack = createCameraTrack(config)
|
|
305
|
+
cameraTrack.captureDeviceChangedListener = this
|
|
292
306
|
setCameraTrackState(cameraTrack, config.cameraEnabled)
|
|
293
307
|
emitEndpoints()
|
|
294
308
|
isCameraInitialized = true
|
|
309
|
+
return true
|
|
295
310
|
}
|
|
296
311
|
|
|
297
312
|
private suspend fun createCameraTrack(config: CameraConfig): LocalVideoTrack {
|
|
@@ -310,8 +325,7 @@ class RNFishjamClient(
|
|
|
310
325
|
) {
|
|
311
326
|
cameraTrack.setEnabled(isEnabled)
|
|
312
327
|
isCameraOn = isEnabled
|
|
313
|
-
|
|
314
|
-
emitEvent(event, mapOf(event.name to isEnabled))
|
|
328
|
+
emitEvent(EmitableEvent.currentCameraChanged(cameraTrack.getCaptureDevice()?.toLocalCamera(), isEnabled))
|
|
315
329
|
localCameraTracksChangedListenersManager.notifyListeners()
|
|
316
330
|
}
|
|
317
331
|
|
|
@@ -337,7 +351,7 @@ class RNFishjamClient(
|
|
|
337
351
|
|
|
338
352
|
private suspend fun startMicrophone() {
|
|
339
353
|
if (!PermissionUtils.requestMicrophonePermission(appContext)) {
|
|
340
|
-
|
|
354
|
+
emitEvent(EmitableEvent.warning("Microphone permission not granted."))
|
|
341
355
|
return
|
|
342
356
|
}
|
|
343
357
|
|
|
@@ -352,8 +366,7 @@ class RNFishjamClient(
|
|
|
352
366
|
) {
|
|
353
367
|
microphoneTrack.setEnabled(isEnabled)
|
|
354
368
|
isMicrophoneOn = isEnabled
|
|
355
|
-
|
|
356
|
-
emitEvent(event, mapOf(event.name to isEnabled))
|
|
369
|
+
emitEvent(EmitableEvent.isMicrophoneOn(isEnabled))
|
|
357
370
|
}
|
|
358
371
|
|
|
359
372
|
suspend fun toggleMicrophone(): Boolean {
|
|
@@ -362,6 +375,15 @@ class RNFishjamClient(
|
|
|
362
375
|
} else {
|
|
363
376
|
getLocalAudioTrack()?.let { setMicrophoneTrackState(it, !isMicrophoneOn) }
|
|
364
377
|
}
|
|
378
|
+
|
|
379
|
+
updateLocalAudioTrackMetadata(
|
|
380
|
+
mapOf(
|
|
381
|
+
"active" to isMicrophoneOn,
|
|
382
|
+
"paused" to !isMicrophoneOn, // TODO: FCE-711,
|
|
383
|
+
"type" to "microphone"
|
|
384
|
+
)
|
|
385
|
+
)
|
|
386
|
+
|
|
365
387
|
return isMicrophoneOn
|
|
366
388
|
}
|
|
367
389
|
|
|
@@ -380,22 +402,13 @@ class RNFishjamClient(
|
|
|
380
402
|
}
|
|
381
403
|
}
|
|
382
404
|
|
|
383
|
-
fun
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
suspend fun startForegroundService(config: ForegroundServicePermissionsConfig) {
|
|
390
|
-
if (foregroundServiceManager == null) {
|
|
391
|
-
throw CodedException("Foreground service not configured.")
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
foregroundServiceManager?.startForegroundService(config)
|
|
405
|
+
suspend fun startForegroundService(config: ForegroundServiceConfig) {
|
|
406
|
+
foregroundServiceManager.updateServiceWithConfig(config)
|
|
407
|
+
foregroundServiceManager.start()
|
|
395
408
|
}
|
|
396
409
|
|
|
397
410
|
fun stopForegroundService() {
|
|
398
|
-
foregroundServiceManager
|
|
411
|
+
foregroundServiceManager.stop()
|
|
399
412
|
}
|
|
400
413
|
|
|
401
414
|
suspend fun toggleScreenShare(screenShareOptions: ScreenShareOptions) {
|
|
@@ -408,6 +421,7 @@ class RNFishjamClient(
|
|
|
408
421
|
screenShareOptions.maxBandwidthMap,
|
|
409
422
|
screenShareOptions.maxBandwidthInt
|
|
410
423
|
)
|
|
424
|
+
|
|
411
425
|
if (!isScreenShareOn) {
|
|
412
426
|
ensureConnected()
|
|
413
427
|
startScreenShare()
|
|
@@ -421,7 +435,6 @@ class RNFishjamClient(
|
|
|
421
435
|
mapOf(
|
|
422
436
|
"id" to endpoint.id,
|
|
423
437
|
"isLocal" to (endpoint.id == fishjamClient.getLocalEndpoint().id),
|
|
424
|
-
"type" to endpoint.type,
|
|
425
438
|
"metadata" to endpoint.metadata,
|
|
426
439
|
"tracks" to
|
|
427
440
|
endpoint.tracks.values.mapNotNull { track ->
|
|
@@ -440,7 +453,11 @@ class RNFishjamClient(
|
|
|
440
453
|
"id" to track.id(),
|
|
441
454
|
"type" to "Audio",
|
|
442
455
|
"metadata" to track.metadata,
|
|
443
|
-
"vadStatus" to
|
|
456
|
+
"vadStatus" to
|
|
457
|
+
when (track.vadStatus) {
|
|
458
|
+
Server.MediaEvent.VadNotification.Status.STATUS_SPEECH -> "speech"
|
|
459
|
+
else -> "silence"
|
|
460
|
+
}
|
|
444
461
|
)
|
|
445
462
|
|
|
446
463
|
is LocalVideoTrack ->
|
|
@@ -475,19 +492,12 @@ class RNFishjamClient(
|
|
|
475
492
|
fun getCaptureDevices(): List<Map<String, Any>> {
|
|
476
493
|
val devices = LocalVideoTrack.getCaptureDevices(appContext?.reactContext!!)
|
|
477
494
|
return devices.map { device ->
|
|
478
|
-
|
|
479
|
-
"id" to device.deviceName,
|
|
480
|
-
"name" to device.deviceName,
|
|
481
|
-
"facingDirection" to
|
|
482
|
-
when (true) {
|
|
483
|
-
device.isFrontFacing -> "front"
|
|
484
|
-
device.isBackFacing -> "back"
|
|
485
|
-
else -> "unspecified"
|
|
486
|
-
}
|
|
487
|
-
)
|
|
495
|
+
device.toLocalCamera()
|
|
488
496
|
}
|
|
489
497
|
}
|
|
490
498
|
|
|
499
|
+
fun getCurrentCaptureDevice(): Map<String, Any>? = getLocalVideoTrack()?.getCaptureDevice()?.toLocalCamera()
|
|
500
|
+
|
|
491
501
|
fun updatePeerMetadata(metadata: Metadata) {
|
|
492
502
|
ensureConnected()
|
|
493
503
|
fishjamClient.updatePeerMetadata(metadata)
|
|
@@ -508,7 +518,7 @@ class RNFishjamClient(
|
|
|
508
518
|
}
|
|
509
519
|
}
|
|
510
520
|
|
|
511
|
-
fun updateLocalAudioTrackMetadata(metadata: Metadata) {
|
|
521
|
+
private fun updateLocalAudioTrackMetadata(metadata: Metadata) {
|
|
512
522
|
ensureAudioTrack()
|
|
513
523
|
getLocalAudioTrack()?.let {
|
|
514
524
|
updateTrackMetadata(it.id(), metadata)
|
|
@@ -606,13 +616,15 @@ class RNFishjamClient(
|
|
|
606
616
|
fishjamClient.setTargetTrackEncoding(trackId, encoding.toTrackEncoding())
|
|
607
617
|
}
|
|
608
618
|
|
|
609
|
-
fun toggleVideoTrackEncoding(encoding: String): Map<String, Any
|
|
619
|
+
fun toggleVideoTrackEncoding(encoding: String): Map<String, Any?> {
|
|
610
620
|
ensureVideoTrack()
|
|
611
621
|
val trackId = getLocalVideoTrack()?.id() ?: return emptyMap()
|
|
612
622
|
videoSimulcastConfig = toggleTrackEncoding(encoding, trackId, videoSimulcastConfig)
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
623
|
+
|
|
624
|
+
val event = EmitableEvent.simulcastConfigUpdate(videoSimulcastConfig)
|
|
625
|
+
emitEvent(event)
|
|
626
|
+
|
|
627
|
+
return event.data
|
|
616
628
|
}
|
|
617
629
|
|
|
618
630
|
fun setVideoTrackEncodingBandwidth(
|
|
@@ -712,6 +724,10 @@ class RNFishjamClient(
|
|
|
712
724
|
if (mediaProjectionIntent == null) {
|
|
713
725
|
throw MissingScreenSharePermission()
|
|
714
726
|
}
|
|
727
|
+
|
|
728
|
+
foregroundServiceManager.updateService { screenSharingEnabled = true }
|
|
729
|
+
foregroundServiceManager.start()
|
|
730
|
+
|
|
715
731
|
fishjamClient.createScreenShareTrack(
|
|
716
732
|
mediaProjectionIntent!!,
|
|
717
733
|
videoParameters,
|
|
@@ -743,13 +759,14 @@ class RNFishjamClient(
|
|
|
743
759
|
|
|
744
760
|
private fun setScreenShareTrackState(isEnabled: Boolean) {
|
|
745
761
|
isScreenShareOn = isEnabled
|
|
746
|
-
|
|
747
|
-
emitEvent(event, mapOf(event.name to isEnabled))
|
|
762
|
+
emitEvent(EmitableEvent.isScreenShareOn(isEnabled))
|
|
748
763
|
}
|
|
749
764
|
|
|
750
765
|
private fun stopScreenShare() {
|
|
751
766
|
ensureScreenShareTrack()
|
|
752
767
|
coroutineScope.launch {
|
|
768
|
+
foregroundServiceManager.updateService { screenSharingEnabled = false }
|
|
769
|
+
foregroundServiceManager.start()
|
|
753
770
|
val screenShareTrack =
|
|
754
771
|
fishjamClient.getLocalEndpoint().tracks.values.first { track ->
|
|
755
772
|
track is LocalScreenShareTrack
|
|
@@ -762,58 +779,21 @@ class RNFishjamClient(
|
|
|
762
779
|
}
|
|
763
780
|
}
|
|
764
781
|
|
|
765
|
-
private fun emitEvent(
|
|
766
|
-
event: EmitableEvents,
|
|
767
|
-
data: Map<String, Any?> = mapOf()
|
|
768
|
-
) {
|
|
782
|
+
private fun emitEvent(event: EmitableEvent) {
|
|
769
783
|
CoroutineScope(Dispatchers.Main).launch {
|
|
770
|
-
sendEvent(event.name, data)
|
|
784
|
+
sendEvent(event.name, event.data)
|
|
771
785
|
}
|
|
772
786
|
}
|
|
773
787
|
|
|
774
|
-
fun emitWarning(warning: String) {
|
|
775
|
-
emitEvent(EmitableEvents.Warning, mapOf("message" to warning))
|
|
776
|
-
}
|
|
777
|
-
|
|
778
788
|
private fun emitEndpoints() {
|
|
779
|
-
|
|
780
|
-
emitEvent(event, mapOf(event.name to getPeers()))
|
|
789
|
+
emitEvent(EmitableEvent.peersUpdate(getPeers()))
|
|
781
790
|
}
|
|
782
791
|
|
|
783
|
-
private fun audioDeviceAsRNMap(audioDevice: AudioDevice): Map<String, String?> =
|
|
784
|
-
mapOf(
|
|
785
|
-
"name" to audioDevice.name,
|
|
786
|
-
"type" to AudioDeviceKind.fromAudioDevice(audioDevice)?.typeName
|
|
787
|
-
)
|
|
788
|
-
|
|
789
792
|
private fun emitAudioDeviceEvent(
|
|
790
793
|
audioDevices: List<AudioDevice>,
|
|
791
794
|
selectedDevice: AudioDevice?
|
|
792
795
|
) {
|
|
793
|
-
|
|
794
|
-
emitEvent(
|
|
795
|
-
event,
|
|
796
|
-
mapOf(
|
|
797
|
-
event.name to
|
|
798
|
-
mapOf(
|
|
799
|
-
"selectedDevice" to (
|
|
800
|
-
if (selectedDevice != null) {
|
|
801
|
-
audioDeviceAsRNMap(
|
|
802
|
-
selectedDevice
|
|
803
|
-
)
|
|
804
|
-
} else {
|
|
805
|
-
null
|
|
806
|
-
}
|
|
807
|
-
),
|
|
808
|
-
"availableDevices" to
|
|
809
|
-
audioDevices.map { audioDevice ->
|
|
810
|
-
audioDeviceAsRNMap(
|
|
811
|
-
audioDevice
|
|
812
|
-
)
|
|
813
|
-
}
|
|
814
|
-
)
|
|
815
|
-
)
|
|
816
|
-
)
|
|
796
|
+
emitEvent(EmitableEvent.audioDeviceUpdate(audioDevices, selectedDevice))
|
|
817
797
|
}
|
|
818
798
|
|
|
819
799
|
private fun getSimulcastConfigAsRNMap(simulcastConfig: SimulcastConfig): Map<String, Any> =
|
|
@@ -834,7 +814,7 @@ class RNFishjamClient(
|
|
|
834
814
|
connectPromise?.resolve(null)
|
|
835
815
|
connectPromise = null
|
|
836
816
|
emitEndpoints()
|
|
837
|
-
peerStatus = PeerStatus.
|
|
817
|
+
peerStatus = PeerStatus.Connected
|
|
838
818
|
}
|
|
839
819
|
}
|
|
840
820
|
|
|
@@ -885,12 +865,11 @@ class RNFishjamClient(
|
|
|
885
865
|
override fun onPeerUpdated(peer: Peer) {}
|
|
886
866
|
|
|
887
867
|
override fun onBandwidthEstimationChanged(estimation: Long) {
|
|
888
|
-
|
|
889
|
-
emitEvent(event, mapOf(event.name to estimation.toFloat()))
|
|
868
|
+
emitEvent(EmitableEvent.bandwidthEstimation(estimation))
|
|
890
869
|
}
|
|
891
870
|
|
|
892
871
|
override fun onDisconnected() {
|
|
893
|
-
peerStatus = PeerStatus.
|
|
872
|
+
peerStatus = PeerStatus.Idle
|
|
894
873
|
}
|
|
895
874
|
|
|
896
875
|
override fun onSocketClose(
|
|
@@ -900,7 +879,7 @@ class RNFishjamClient(
|
|
|
900
879
|
CoroutineScope(Dispatchers.Main).launch {
|
|
901
880
|
connectPromise?.reject(SocketClosedError(code, reason))
|
|
902
881
|
connectPromise = null
|
|
903
|
-
peerStatus = PeerStatus.
|
|
882
|
+
peerStatus = PeerStatus.Idle
|
|
904
883
|
}
|
|
905
884
|
}
|
|
906
885
|
|
|
@@ -908,18 +887,23 @@ class RNFishjamClient(
|
|
|
908
887
|
CoroutineScope(Dispatchers.Main).launch {
|
|
909
888
|
connectPromise?.reject(SocketError(t.message ?: t.toString()))
|
|
910
889
|
connectPromise = null
|
|
890
|
+
peerStatus = PeerStatus.Error
|
|
911
891
|
}
|
|
912
892
|
}
|
|
913
893
|
|
|
914
894
|
override fun onReconnected() {
|
|
915
|
-
|
|
895
|
+
reconnectionStatus = ReconnectionStatus.Reconnecting
|
|
916
896
|
}
|
|
917
897
|
|
|
918
898
|
override fun onReconnectionStarted() {
|
|
919
|
-
|
|
899
|
+
reconnectionStatus = ReconnectionStatus.Idle
|
|
920
900
|
}
|
|
921
901
|
|
|
922
902
|
override fun onReconnectionRetriesLimitReached() {
|
|
923
|
-
|
|
903
|
+
reconnectionStatus = ReconnectionStatus.Error
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
override fun onCaptureDeviceChanged(captureDevice: CaptureDevice?) {
|
|
907
|
+
emitEvent(EmitableEvent.currentCameraChanged(captureDevice?.toLocalCamera(), isCameraOn))
|
|
924
908
|
}
|
|
925
909
|
}
|
|
@@ -81,7 +81,7 @@ class ConnectConfig : Record {
|
|
|
81
81
|
val reconnectConfig: ReconnectConfig = ReconnectConfig()
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
class
|
|
84
|
+
class ForegroundServiceConfig : Record {
|
|
85
85
|
@Field
|
|
86
86
|
val channelId: String? = null
|
|
87
87
|
|
|
@@ -93,17 +93,12 @@ class ForegroundServiceNotificationConfig : Record {
|
|
|
93
93
|
|
|
94
94
|
@Field
|
|
95
95
|
val notificationTitle: String? = null
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
class ForegroundServicePermissionsConfig : Record {
|
|
99
|
-
@Field
|
|
100
|
-
val enableCamera: Boolean = false
|
|
101
96
|
|
|
102
97
|
@Field
|
|
103
|
-
val
|
|
98
|
+
val enableCamera: Boolean? = null
|
|
104
99
|
|
|
105
100
|
@Field
|
|
106
|
-
val
|
|
101
|
+
val enableMicrophone: Boolean? = null
|
|
107
102
|
}
|
|
108
103
|
|
|
109
104
|
class RNFishjamClientModule : Module() {
|
|
@@ -118,7 +113,7 @@ class RNFishjamClientModule : Module() {
|
|
|
118
113
|
|
|
119
114
|
Name("RNFishjamClient")
|
|
120
115
|
|
|
121
|
-
Events(
|
|
116
|
+
Events(EmitableEvent.allEvents)
|
|
122
117
|
|
|
123
118
|
OnCreate {
|
|
124
119
|
rnFishjamClient.onModuleCreate(appContext)
|
|
@@ -148,12 +143,24 @@ class RNFishjamClientModule : Module() {
|
|
|
148
143
|
return@Property rnFishjamClient.getCaptureDevices()
|
|
149
144
|
}
|
|
150
145
|
|
|
146
|
+
Property("currentCamera") {
|
|
147
|
+
return@Property rnFishjamClient.getCurrentCaptureDevice()
|
|
148
|
+
}
|
|
149
|
+
|
|
151
150
|
Property("isScreenShareOn") {
|
|
152
151
|
return@Property rnFishjamClient.isScreenShareOn
|
|
153
152
|
}
|
|
154
153
|
|
|
155
154
|
Property("peerStatus") {
|
|
156
|
-
return@Property rnFishjamClient.peerStatus
|
|
155
|
+
return@Property rnFishjamClient.peerStatus.status
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
Property("reconnectionStatus") {
|
|
159
|
+
return@Property rnFishjamClient.reconnectionStatus.status
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Function("getPeers") {
|
|
163
|
+
return@Function rnFishjamClient.getPeers()
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
AsyncFunction(
|
|
@@ -171,8 +178,8 @@ class RNFishjamClientModule : Module() {
|
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
AsyncFunction("startCamera") Coroutine { config: CameraConfig ->
|
|
174
|
-
withContext(Dispatchers.Main) {
|
|
175
|
-
rnFishjamClient.startCamera(config)
|
|
181
|
+
return@Coroutine withContext(Dispatchers.Main) {
|
|
182
|
+
return@withContext rnFishjamClient.startCamera(config)
|
|
176
183
|
}
|
|
177
184
|
}
|
|
178
185
|
|
|
@@ -216,12 +223,6 @@ class RNFishjamClientModule : Module() {
|
|
|
216
223
|
}
|
|
217
224
|
}
|
|
218
225
|
|
|
219
|
-
AsyncFunction("getPeers") Coroutine { ->
|
|
220
|
-
withContext(Dispatchers.Main) {
|
|
221
|
-
rnFishjamClient.getPeers()
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
226
|
AsyncFunction("updatePeerMetadata") Coroutine { metadata: Map<String, Any> ->
|
|
226
227
|
withContext(Dispatchers.Main) {
|
|
227
228
|
rnFishjamClient.updatePeerMetadata(metadata)
|
|
@@ -234,12 +235,6 @@ class RNFishjamClientModule : Module() {
|
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
237
|
|
|
237
|
-
AsyncFunction("updateAudioTrackMetadata") Coroutine { metadata: Map<String, Any> ->
|
|
238
|
-
withContext(Dispatchers.Main) {
|
|
239
|
-
rnFishjamClient.updateLocalAudioTrackMetadata(metadata)
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
238
|
AsyncFunction("updateScreenShareTrackMetadata") Coroutine { metadata: Map<String, Any> ->
|
|
244
239
|
withContext(Dispatchers.Main) {
|
|
245
240
|
rnFishjamClient.updateLocalScreenShareTrackMetadata(metadata)
|
|
@@ -301,18 +296,14 @@ class RNFishjamClientModule : Module() {
|
|
|
301
296
|
}
|
|
302
297
|
|
|
303
298
|
AsyncFunction("changeWebRTCLoggingSeverity") Coroutine { severity: String ->
|
|
304
|
-
|
|
299
|
+
withContext(Dispatchers.Main) {
|
|
305
300
|
rnFishjamClient.changeWebRTCLoggingSeverity(severity)
|
|
306
301
|
}
|
|
307
302
|
}
|
|
308
303
|
|
|
309
304
|
AsyncFunction("getStatistics") { rnFishjamClient.getStatistics() }
|
|
310
305
|
|
|
311
|
-
|
|
312
|
-
return@Function rnFishjamClient.configureForegroundService(config)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
AsyncFunction("startForegroundService") Coroutine { config: ForegroundServicePermissionsConfig ->
|
|
306
|
+
AsyncFunction("startForegroundService") Coroutine { config: ForegroundServiceConfig ->
|
|
316
307
|
rnFishjamClient.startForegroundService(config)
|
|
317
308
|
}
|
|
318
309
|
|
|
@@ -15,13 +15,17 @@ class VideoRendererViewModule : Module() {
|
|
|
15
15
|
RNFishjamClient.localTracksSwitchListenerManager.remove(view)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
Prop("trackId") { view
|
|
18
|
+
Prop("trackId") { view, trackId: String ->
|
|
19
19
|
view.init(trackId)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
Prop("videoLayout") { view
|
|
22
|
+
Prop("videoLayout") { view, videoLayout: String ->
|
|
23
23
|
view.setVideoLayout(videoLayout)
|
|
24
24
|
}
|
|
25
|
+
|
|
26
|
+
Prop("skipRenderOutsideVisibleArea") { view, skipRenderOutsideVisibleArea: Boolean ->
|
|
27
|
+
view.checkVisibilityDelayMillis = if (skipRenderOutsideVisibleArea) 1000 else null
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
31
|
}
|