@fishjam-cloud/react-native-client 0.4.1 → 0.5.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 +99 -14
- package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +63 -92
- package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +12 -23
- 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 +6 -7
- package/build/RNFishjamClientModule.d.ts.map +1 -1
- package/build/RNFishjamClientModule.js.map +1 -1
- package/build/common/client.d.ts +2 -1
- package/build/common/client.d.ts.map +1 -1
- package/build/common/client.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 +36 -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/hooks/useAppScreenShare.js +1 -1
- package/build/hooks/useAppScreenShare.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 +14 -17
- package/build/hooks/useCamera.js.map +1 -1
- package/build/hooks/useFishjamEvent.d.ts +1 -1
- package/build/hooks/useFishjamEvent.js +1 -1
- package/build/hooks/useFishjamEvent.js.map +1 -1
- package/build/hooks/useFishjamEventState.d.ts +3 -0
- package/build/hooks/useFishjamEventState.d.ts.map +1 -0
- package/build/hooks/useFishjamEventState.js +16 -0
- package/build/hooks/useFishjamEventState.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 -10
- package/build/hooks/useMicrophone.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 +41 -6
- package/build/hooks/usePeers.js.map +1 -1
- package/build/hooks/useScreenShare.d.ts.map +1 -1
- package/build/hooks/useScreenShare.js +5 -6
- package/build/hooks/useScreenShare.js.map +1 -1
- package/build/index.d.ts +3 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- 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.js +2 -2
- package/build/utils/errorListener.js.map +1 -1
- package/ios/Events.swift +97 -19
- package/ios/RNFishjamClient.podspec +1 -1
- package/ios/RNFishjamClient.swift +74 -109
- package/ios/RNFishjamClientModule.swift +6 -6
- 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 +8 -10
|
@@ -26,22 +26,23 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
26
26
|
|
|
27
27
|
var cameraId: String? = nil
|
|
28
28
|
|
|
29
|
-
var audioSessionMode: AVAudioSession.Mode =
|
|
29
|
+
var audioSessionMode: AVAudioSession.Mode = .videoChat
|
|
30
30
|
var errorMessage: String?
|
|
31
31
|
|
|
32
|
+
var currentCamera: LocalCamera? { getLocalCameraTrack()?.currentCaptureDevice?.toLocalCamera() }
|
|
33
|
+
|
|
32
34
|
private(set) var peerStatus: PeerStatus = .idle {
|
|
33
35
|
didSet {
|
|
34
|
-
|
|
35
|
-
emit(event: event, data: [event.name: peerStatus.rawValue])
|
|
36
|
+
emit(event: .peerStatusChanged(peerStatus: peerStatus))
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
let sendEvent: (_ eventName: String, _ data: [String: Any]) -> Void
|
|
40
|
+
let sendEvent: (_ eventName: String, _ data: [String: Any?]) -> Void
|
|
40
41
|
|
|
41
42
|
static var tracksUpdateListenersManager = TracksUpdateListenersManager()
|
|
42
43
|
static var localCameraTracksChangedListenersManager = LocalCameraTracksChangedListenersManager()
|
|
43
44
|
|
|
44
|
-
init(sendEvent: @escaping (_ eventName: String, _ data: [String: Any]) -> Void) {
|
|
45
|
+
init(sendEvent: @escaping (_ eventName: String, _ data: [String: Any?]) -> Void) {
|
|
45
46
|
self.sendEvent = sendEvent
|
|
46
47
|
NotificationCenter.default.addObserver(
|
|
47
48
|
self,
|
|
@@ -214,7 +215,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
214
215
|
|
|
215
216
|
RNFishjamClient.fishjamClient?.connect(
|
|
216
217
|
config: FishjamCloudClient.ConnectConfig(
|
|
217
|
-
websocketUrl: url, token: peerToken, peerMetadata:
|
|
218
|
+
websocketUrl: url, token: peerToken, peerMetadata: peerMetadata.toMetadata(),
|
|
218
219
|
reconnectConfig: reconnectConfig
|
|
219
220
|
))
|
|
220
221
|
|
|
@@ -239,23 +240,36 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
239
240
|
}
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
func startCamera(config: CameraConfig) async throws {
|
|
243
|
-
|
|
243
|
+
func startCamera(config: CameraConfig) async throws -> Bool {
|
|
244
|
+
#if targetEnvironment(simulator)
|
|
245
|
+
emit(
|
|
246
|
+
event: .warning(
|
|
247
|
+
message: "Camera is not supported on simulator."))
|
|
248
|
+
return false
|
|
249
|
+
#else
|
|
250
|
+
try ensureCreated()
|
|
244
251
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
252
|
+
guard !isCameraInitialized else {
|
|
253
|
+
emit(
|
|
254
|
+
event: .warning(
|
|
255
|
+
message:
|
|
256
|
+
"Camera already started. You may only call startCamera once before leaveRoom is called."))
|
|
249
257
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return
|
|
253
|
-
}
|
|
258
|
+
return true
|
|
259
|
+
}
|
|
254
260
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
261
|
+
guard await PermissionUtils.requestCameraPermission() else {
|
|
262
|
+
emit(event: .warning(message: "Camera permission not granted."))
|
|
263
|
+
return false
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
let cameraTrack = try createCameraTrack(config: config)
|
|
267
|
+
cameraTrack.captureDeviceChangedListener = self
|
|
268
|
+
setCameraTrackState(cameraTrack, enabled: config.cameraEnabled)
|
|
269
|
+
emitEndpoints()
|
|
270
|
+
isCameraInitialized = true
|
|
271
|
+
return true
|
|
272
|
+
#endif
|
|
259
273
|
}
|
|
260
274
|
|
|
261
275
|
private func createCameraTrack(config: CameraConfig) throws -> LocalCameraTrack {
|
|
@@ -272,9 +286,9 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
272
286
|
private func setCameraTrackState(_ cameraTrack: LocalCameraTrack, enabled: Bool) {
|
|
273
287
|
cameraTrack.enabled = enabled
|
|
274
288
|
isCameraOn = enabled
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
289
|
+
emit(
|
|
290
|
+
event: .currentCameraChanged(
|
|
291
|
+
localCamera: cameraTrack.currentCaptureDevice?.toLocalCamera(), isCameraOn: enabled))
|
|
278
292
|
RNFishjamClient.localCameraTracksChangedListenersManager.notifyListeners()
|
|
279
293
|
}
|
|
280
294
|
|
|
@@ -301,12 +315,19 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
301
315
|
} else {
|
|
302
316
|
try await startMicrophone()
|
|
303
317
|
}
|
|
318
|
+
|
|
319
|
+
try updateLocalAudioTrackMetadata(metadata: [
|
|
320
|
+
"active": isMicrophoneOn,
|
|
321
|
+
"paused": !isMicrophoneOn, //TODO: FCE-711
|
|
322
|
+
"type": "microphone",
|
|
323
|
+
])
|
|
324
|
+
|
|
304
325
|
return isMicrophoneOn
|
|
305
326
|
}
|
|
306
327
|
|
|
307
328
|
func startMicrophone() async throws {
|
|
308
329
|
guard await PermissionUtils.requestMicrophonePermission() else {
|
|
309
|
-
emit(warning: "Microphone permission not granted.")
|
|
330
|
+
emit(event: .warning(message: "Microphone permission not granted."))
|
|
310
331
|
return
|
|
311
332
|
}
|
|
312
333
|
let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(metadata: Metadata())
|
|
@@ -318,9 +339,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
318
339
|
private func setMicrophoneTrackState(_ microphoneTrack: LocalAudioTrack, enabled: Bool) {
|
|
319
340
|
microphoneTrack.enabled = enabled
|
|
320
341
|
isMicrophoneOn = enabled
|
|
321
|
-
|
|
322
|
-
let isMicrophoneOnMap = [event.name: enabled]
|
|
323
|
-
emit(event: event, data: isMicrophoneOnMap)
|
|
342
|
+
emit(event: .isMicrophoneOn(enabled: enabled))
|
|
324
343
|
}
|
|
325
344
|
|
|
326
345
|
func setAudioSessionMode() {
|
|
@@ -345,7 +364,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
345
364
|
try ensureCreated()
|
|
346
365
|
try ensureConnected()
|
|
347
366
|
guard isAppScreenShareOn == false else {
|
|
348
|
-
emit(warning: "Screensharing screen not available during screensharing app.")
|
|
367
|
+
emit(event: .warning(message: "Screensharing screen not available during screensharing app."))
|
|
349
368
|
return
|
|
350
369
|
}
|
|
351
370
|
guard let screenShareExtensionBundleId = Bundle.main.infoDictionary?["ScreenShareExtensionBundleId"] as? String
|
|
@@ -383,7 +402,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
383
402
|
metadata: screenShareMetadata,
|
|
384
403
|
canStart: {
|
|
385
404
|
if self.isAppScreenShareOn {
|
|
386
|
-
self.emit(warning: "Screensharing screen not available during screensharing app.")
|
|
405
|
+
self.emit(event: .warning(message: "Screensharing screen not available during screensharing app."))
|
|
387
406
|
}
|
|
388
407
|
return !self.isAppScreenShareOn
|
|
389
408
|
},
|
|
@@ -418,9 +437,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
418
437
|
|
|
419
438
|
private func setScreenShareTrackState(enabled: Bool) throws {
|
|
420
439
|
isScreenShareOn = enabled
|
|
421
|
-
|
|
422
|
-
let isScreenShareEnabled = [event.name: enabled]
|
|
423
|
-
emit(event: event, data: isScreenShareEnabled)
|
|
440
|
+
emit(event: .isScreenShareOn(enabled: enabled))
|
|
424
441
|
}
|
|
425
442
|
|
|
426
443
|
func startScreenAppShare(screenShareOptions: ScreenShareOptions) throws {
|
|
@@ -449,7 +466,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
449
466
|
|
|
450
467
|
func toggleAppScreenShare(screenShareOptions: ScreenShareOptions) throws {
|
|
451
468
|
guard isScreenShareOn == false else {
|
|
452
|
-
emit(warning: "App screensharing not available during screensharing.")
|
|
469
|
+
emit(event: .warning(message: "App screensharing not available during screensharing."))
|
|
453
470
|
return
|
|
454
471
|
}
|
|
455
472
|
if getLocalScreenAppTrack() != nil {
|
|
@@ -462,9 +479,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
462
479
|
private func setScreenAppTrackState(_ track: LocalAppScreenShareTrack, enabled: Bool) {
|
|
463
480
|
track.enabled = enabled
|
|
464
481
|
isAppScreenShareOn = enabled
|
|
465
|
-
|
|
466
|
-
let eventMap = [event.name: enabled]
|
|
467
|
-
emit(event: event, data: eventMap)
|
|
482
|
+
emit(event: .isAppScreenShareOn(enabled: enabled))
|
|
468
483
|
}
|
|
469
484
|
|
|
470
485
|
//returns local endpoint and remote endpoints
|
|
@@ -480,7 +495,6 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
480
495
|
[
|
|
481
496
|
"id": endpoint.id,
|
|
482
497
|
"isLocal": endpoint.id == RNFishjamClient.fishjamClient!.getLocalEndpoint().id,
|
|
483
|
-
"type": endpoint.type,
|
|
484
498
|
"metadata": endpoint.metadata.toDict(),
|
|
485
499
|
"tracks": endpoint.tracks.values.compactMap { track -> [String: Any?]? in
|
|
486
500
|
switch track {
|
|
@@ -539,19 +553,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
539
553
|
|
|
540
554
|
func getCaptureDevices() -> [[String: Any]] {
|
|
541
555
|
let devices = LocalCameraTrack.getCaptureDevices()
|
|
542
|
-
return devices.map {
|
|
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
|
-
}
|
|
556
|
+
return devices.map { $0.toLocalCamera() }
|
|
555
557
|
}
|
|
556
558
|
|
|
557
559
|
func updatePeerMetadata(metadata: [String: Any]) throws {
|
|
@@ -571,7 +573,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
571
573
|
}
|
|
572
574
|
}
|
|
573
575
|
|
|
574
|
-
func updateLocalAudioTrackMetadata(metadata: [String: Any]) throws {
|
|
576
|
+
private func updateLocalAudioTrackMetadata(metadata: [String: Any]) throws {
|
|
575
577
|
try ensureAudioTrack()
|
|
576
578
|
if let track = getLocalAudioTrack() {
|
|
577
579
|
updateTrackMetadata(trackId: track.id, metadata: metadata)
|
|
@@ -604,13 +606,14 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
604
606
|
return SimulcastConfig(enabled: true, activeEncodings: updatedEncodings)
|
|
605
607
|
}
|
|
606
608
|
|
|
607
|
-
func toggleScreenShareTrackEncoding(encoding: String) throws -> [String: Any] {
|
|
609
|
+
func toggleScreenShareTrackEncoding(encoding: String) throws -> [String: Any?] {
|
|
608
610
|
try ensureScreenBroadcastTrack()
|
|
609
611
|
if let track = getLocalScreenBroadcastTrack() {
|
|
610
612
|
screenShareSimulcastConfig = try toggleTrackEncoding(
|
|
611
613
|
encoding: encoding, trackId: track.id, simulcastConfig: screenShareSimulcastConfig)
|
|
612
614
|
}
|
|
613
|
-
|
|
615
|
+
|
|
616
|
+
return EmitableEvent.simulcastConfigUpdate(simulcastConfig: screenShareSimulcastConfig).data
|
|
614
617
|
}
|
|
615
618
|
|
|
616
619
|
func setScreenShareTrackBandwidth(bandwidth: Int) throws {
|
|
@@ -634,7 +637,7 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
634
637
|
RNFishjamClient.fishjamClient?.setTargetTrackEncoding(trackId: trackId, encoding: trackEncoding)
|
|
635
638
|
}
|
|
636
639
|
|
|
637
|
-
func toggleVideoTrackEncoding(encoding: String) throws -> [String: Any] {
|
|
640
|
+
func toggleVideoTrackEncoding(encoding: String) throws -> [String: Any?] {
|
|
638
641
|
try ensureCameraTrack()
|
|
639
642
|
try ensureConnected()
|
|
640
643
|
|
|
@@ -642,11 +645,10 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
642
645
|
videoSimulcastConfig = try toggleTrackEncoding(
|
|
643
646
|
encoding: encoding, trackId: track.id, simulcastConfig: videoSimulcastConfig)
|
|
644
647
|
|
|
645
|
-
let event =
|
|
646
|
-
|
|
647
|
-
emit(event: event, data: simulcastConfigAsRNMap)
|
|
648
|
+
let event = EmitableEvent.simulcastConfigUpdate(simulcastConfig: videoSimulcastConfig)
|
|
649
|
+
emit(event: event)
|
|
648
650
|
|
|
649
|
-
return
|
|
651
|
+
return event.data
|
|
650
652
|
}
|
|
651
653
|
|
|
652
654
|
func setVideoTrackEncodingBandwidth(encoding: String, bandwidth: Int) throws {
|
|
@@ -759,20 +761,14 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
759
761
|
)
|
|
760
762
|
}
|
|
761
763
|
|
|
762
|
-
func emit(event:
|
|
764
|
+
func emit(event: EmitableEvent) {
|
|
763
765
|
DispatchQueue.main.async { [weak self] in
|
|
764
|
-
self?.sendEvent(event.name, data)
|
|
766
|
+
self?.sendEvent(event.event.name, event.data)
|
|
765
767
|
}
|
|
766
768
|
}
|
|
767
769
|
|
|
768
|
-
func emit(warning: String) {
|
|
769
|
-
emit(event: .Warning, data: ["message": warning])
|
|
770
|
-
}
|
|
771
|
-
|
|
772
770
|
func emitEndpoints() {
|
|
773
|
-
|
|
774
|
-
let EndpointsUpdateMap = [event.name: (try? getPeers()) ?? []]
|
|
775
|
-
emit(event: event, data: EndpointsUpdateMap)
|
|
771
|
+
emit(event: .peersUpdate(peersData: (try? getPeers()) ?? []))
|
|
776
772
|
}
|
|
777
773
|
|
|
778
774
|
func onJoined(peerID: String, peersInRoom: [String: Endpoint]) {
|
|
@@ -856,13 +852,6 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
856
852
|
peerStatus = .idle
|
|
857
853
|
}
|
|
858
854
|
|
|
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
855
|
func selectAudioSessionMode(sessionMode: String) throws {
|
|
867
856
|
switch sessionMode {
|
|
868
857
|
case "videoChat":
|
|
@@ -895,53 +884,29 @@ class RNFishjamClient: FishjamClientListener {
|
|
|
895
884
|
}
|
|
896
885
|
|
|
897
886
|
@objc func onRouteChangeNotification() {
|
|
898
|
-
|
|
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]])
|
|
887
|
+
emit(event: .audioDeviceUpdate(currentRoute: AVAudioSession.sharedInstance().currentRoute))
|
|
928
888
|
}
|
|
929
889
|
|
|
930
890
|
func onBandwidthEstimationChanged(estimation: Int) {
|
|
931
|
-
|
|
932
|
-
emit(event: event, data: [event.name: estimation])
|
|
891
|
+
emit(event: .bandwidthEstimation(estimation: estimation))
|
|
933
892
|
}
|
|
934
893
|
|
|
935
894
|
func onReconnectionStarted() {
|
|
936
|
-
emit(event: .
|
|
895
|
+
emit(event: .reconnectionStarted)
|
|
937
896
|
}
|
|
938
897
|
|
|
939
898
|
func onReconnected() {
|
|
940
|
-
emit(event: .
|
|
899
|
+
emit(event: .reconnected)
|
|
941
900
|
}
|
|
942
901
|
|
|
943
902
|
func onReconnectionRetriesLimitReached() {
|
|
944
|
-
emit(event: .
|
|
903
|
+
emit(event: .reconnectionRetriesLimitReached)
|
|
945
904
|
}
|
|
946
905
|
|
|
947
906
|
}
|
|
907
|
+
|
|
908
|
+
extension RNFishjamClient: CameraCapturerDeviceChangedListener {
|
|
909
|
+
func onCaptureDeviceChanged(_ device: AVCaptureDevice?) {
|
|
910
|
+
emit(event: .currentCameraChanged(localCamera: device?.toLocalCamera(), isCameraOn: isCameraOn))
|
|
911
|
+
}
|
|
912
|
+
}
|
|
@@ -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,7 +84,7 @@ public class RNFishjamClientModule: Module {
|
|
|
84
84
|
|
|
85
85
|
Name("RNFishjamClient")
|
|
86
86
|
|
|
87
|
-
Events(
|
|
87
|
+
Events(EmitableEvent.allEvents)
|
|
88
88
|
|
|
89
89
|
Property("peerStatus") {
|
|
90
90
|
return rnFishjamClient.peerStatus.rawValue
|
|
@@ -102,6 +102,10 @@ public class RNFishjamClientModule: Module {
|
|
|
102
102
|
return rnFishjamClient.getCaptureDevices()
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
Property("currentCamera") {
|
|
106
|
+
return rnFishjamClient.currentCamera
|
|
107
|
+
}
|
|
108
|
+
|
|
105
109
|
Property("isScreenShareOn") {
|
|
106
110
|
return rnFishjamClient.isScreenShareOn
|
|
107
111
|
}
|
|
@@ -164,10 +168,6 @@ public class RNFishjamClientModule: Module {
|
|
|
164
168
|
try rnFishjamClient.updateLocalVideoTrackMetadata(metadata: metadata)
|
|
165
169
|
}
|
|
166
170
|
|
|
167
|
-
AsyncFunction("updateAudioTrackMetadata") { (metadata: [String: Any]) in
|
|
168
|
-
try rnFishjamClient.updateLocalAudioTrackMetadata(metadata: metadata)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
171
|
AsyncFunction("updateScreenShareTrackMetadata") { (metadata: [String: Any]) in
|
|
172
172
|
try rnFishjamClient.updateLocalScreenShareTrackMetadata(metadata: metadata)
|
|
173
173
|
}
|
|
@@ -2,15 +2,14 @@ import ExpoModulesCore
|
|
|
2
2
|
import FishjamCloudClient
|
|
3
3
|
|
|
4
4
|
class VideoPreviewView: ExpoView, LocalCameraTrackChangedListener {
|
|
5
|
-
var videoView: VideoView
|
|
6
|
-
private var localVideoTrack: LocalCameraTrack?
|
|
5
|
+
var videoView: VideoView!
|
|
6
|
+
private var localVideoTrack: LocalCameraTrack?
|
|
7
7
|
|
|
8
8
|
required init(appContext: AppContext? = nil) {
|
|
9
9
|
super.init(appContext: appContext)
|
|
10
10
|
videoView = VideoView()
|
|
11
|
-
videoView
|
|
12
|
-
videoView
|
|
13
|
-
addSubview(videoView!)
|
|
11
|
+
videoView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
12
|
+
videoView.clipsToBounds = true
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
private func trySetLocalCameraTrack() {
|
|
@@ -29,16 +28,18 @@ class VideoPreviewView: ExpoView, LocalCameraTrackChangedListener {
|
|
|
29
28
|
track is LocalCameraTrack
|
|
30
29
|
})?.value as? LocalCameraTrack
|
|
31
30
|
self.localVideoTrack?.start()
|
|
32
|
-
self.videoView
|
|
31
|
+
self.videoView.track = self.localVideoTrack
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
override func willMove(toSuperview newSuperview: UIView?) {
|
|
37
36
|
super.willMove(toSuperview: newSuperview)
|
|
38
37
|
if newSuperview == nil {
|
|
38
|
+
videoView.removeFromSuperview()
|
|
39
39
|
RNFishjamClient.localCameraTracksChangedListenersManager.remove(self)
|
|
40
40
|
localVideoTrack?.stop()
|
|
41
41
|
} else {
|
|
42
|
+
addSubview(videoView)
|
|
42
43
|
RNFishjamClient.localCameraTracksChangedListenersManager.add(self)
|
|
43
44
|
trySetLocalCameraTrack()
|
|
44
45
|
}
|
|
@@ -48,26 +49,25 @@ class VideoPreviewView: ExpoView, LocalCameraTrackChangedListener {
|
|
|
48
49
|
didSet {
|
|
49
50
|
switch videoLayout {
|
|
50
51
|
case "FIT":
|
|
51
|
-
|
|
52
|
+
videoView.layout = .fit
|
|
52
53
|
case "FILL":
|
|
53
|
-
|
|
54
|
+
videoView.layout = .fill
|
|
54
55
|
default:
|
|
55
|
-
|
|
56
|
+
videoView.layout = .fill
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
var mirrorVideo: Bool = false {
|
|
61
62
|
didSet {
|
|
62
|
-
|
|
63
|
+
videoView.mirror = mirrorVideo
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
var captureDeviceId: String? = nil {
|
|
67
68
|
didSet {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
69
|
+
guard let captureDeviceId else { return }
|
|
70
|
+
localVideoTrack?.switchCamera(deviceId: captureDeviceId)
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -3,42 +3,39 @@ import ExpoModulesCore
|
|
|
3
3
|
import FishjamCloudClient
|
|
4
4
|
|
|
5
5
|
class VideoRendererView: ExpoView, TrackUpdateListener {
|
|
6
|
-
var videoView: VideoView
|
|
7
|
-
var cancellableEndpoints: Cancellable?
|
|
6
|
+
var videoView: VideoView!
|
|
7
|
+
var cancellableEndpoints: Cancellable?
|
|
8
8
|
|
|
9
9
|
required init(appContext: AppContext? = nil) {
|
|
10
10
|
super.init(appContext: appContext)
|
|
11
|
-
RNFishjamClient.tracksUpdateListenersManager.add(self)
|
|
12
11
|
videoView = VideoView()
|
|
13
|
-
videoView
|
|
14
|
-
videoView
|
|
15
|
-
addSubview(videoView!)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
deinit {
|
|
19
|
-
RNFishjamClient.tracksUpdateListenersManager.remove(self)
|
|
12
|
+
videoView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
13
|
+
videoView.clipsToBounds = true
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
override func willMove(toSuperview newSuperview: UIView?) {
|
|
23
17
|
super.willMove(toSuperview: newSuperview)
|
|
24
18
|
|
|
25
|
-
if newSuperview
|
|
19
|
+
if newSuperview == nil {
|
|
20
|
+
videoView.removeFromSuperview()
|
|
21
|
+
RNFishjamClient.tracksUpdateListenersManager.remove(self)
|
|
22
|
+
} else {
|
|
23
|
+
addSubview(videoView)
|
|
24
|
+
RNFishjamClient.tracksUpdateListenersManager.add(self)
|
|
26
25
|
updateVideoTrack()
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
func updateVideoTrack() {
|
|
31
|
-
DispatchQueue.main.async {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
self.videoView?.track = track
|
|
39
|
-
return
|
|
40
|
-
}
|
|
30
|
+
DispatchQueue.main.async { [weak self] in
|
|
31
|
+
guard let self, self.superview != nil else { return }
|
|
32
|
+
for endpoint in RNFishjamClient.getLocalAndRemoteEndpoints() {
|
|
33
|
+
guard let track = endpoint.tracks[self.trackId] as? VideoTrack else { continue }
|
|
34
|
+
if let track = track as? LocalCameraTrack {
|
|
35
|
+
self.mirrorVideo = track.isFrontCamera
|
|
41
36
|
}
|
|
37
|
+
self.videoView.track = track
|
|
38
|
+
return
|
|
42
39
|
}
|
|
43
40
|
}
|
|
44
41
|
}
|
|
@@ -57,11 +54,11 @@ class VideoRendererView: ExpoView, TrackUpdateListener {
|
|
|
57
54
|
didSet {
|
|
58
55
|
switch videoLayout {
|
|
59
56
|
case "FIT":
|
|
60
|
-
|
|
57
|
+
videoView.layout = .fit
|
|
61
58
|
case "FILL":
|
|
62
|
-
|
|
59
|
+
videoView.layout = .fill
|
|
63
60
|
default:
|
|
64
|
-
|
|
61
|
+
videoView.layout = .fill
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
}
|
|
@@ -69,7 +66,13 @@ class VideoRendererView: ExpoView, TrackUpdateListener {
|
|
|
69
66
|
|
|
70
67
|
var mirrorVideo: Bool = false {
|
|
71
68
|
didSet {
|
|
72
|
-
|
|
69
|
+
videoView.mirror = mirrorVideo
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var checkVisibilityTimeInterval: TimeInterval? {
|
|
74
|
+
didSet {
|
|
75
|
+
videoView.checkVisibilityTimeInterval = checkVisibilityTimeInterval
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
}
|
|
@@ -5,12 +5,16 @@ public class VideoRendererViewModule: Module {
|
|
|
5
5
|
Name("VideoRendererViewModule")
|
|
6
6
|
|
|
7
7
|
View(VideoRendererView.self) {
|
|
8
|
-
Prop("trackId") { (view
|
|
9
|
-
view.trackId =
|
|
8
|
+
Prop("trackId") { (view, trackId) in
|
|
9
|
+
view.trackId = trackId
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
Prop("videoLayout") { (view
|
|
13
|
-
view.videoLayout =
|
|
12
|
+
Prop("videoLayout") { (view, videoLayout) in
|
|
13
|
+
view.videoLayout = videoLayout
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Prop("skipRenderOutsideVisibleArea") { (view, skipRenderOutsideVisibleArea) in
|
|
17
|
+
view.checkVisibilityTimeInterval = skipRenderOutsideVisibleArea ? 1 : nil
|
|
14
18
|
}
|
|
15
19
|
}
|
|
16
20
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import AVKit
|
|
2
|
+
import FishjamCloudClient
|
|
3
|
+
|
|
4
|
+
public typealias LocalCamera = [String: Any]
|
|
5
|
+
|
|
6
|
+
extension AVCaptureDevice {
|
|
7
|
+
func toLocalCamera() -> LocalCamera {
|
|
8
|
+
let facingDirection =
|
|
9
|
+
switch position {
|
|
10
|
+
case .front: "front"
|
|
11
|
+
case .back: "back"
|
|
12
|
+
default: "unspecified"
|
|
13
|
+
}
|
|
14
|
+
return [
|
|
15
|
+
"id": uniqueID,
|
|
16
|
+
"name": localizedName,
|
|
17
|
+
"facingDirection": facingDirection,
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fishjam-cloud/react-native-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A React Native client for Fishjam Cloud",
|
|
5
5
|
"author": "Fishjam Cloud Team",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -44,30 +44,28 @@
|
|
|
44
44
|
"protobufjs": "^7.4.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@testing-library/
|
|
48
|
-
"@
|
|
47
|
+
"@testing-library/dom": "^10.4.0",
|
|
48
|
+
"@testing-library/react": "^16.0.1",
|
|
49
|
+
"@types/lodash": "^4.17.13",
|
|
49
50
|
"@types/phoenix": "^1.6.5",
|
|
50
51
|
"@types/promise-fs": "^2.1.2",
|
|
51
|
-
"@types/react": "^18.3.
|
|
52
|
-
"expo": "^51.0.32",
|
|
52
|
+
"@types/react": "^18.3.12",
|
|
53
53
|
"expo-module-scripts": "^3.5.2",
|
|
54
|
-
"expo-modules-core": "^1.12.24",
|
|
55
54
|
"husky": "^9.1.6",
|
|
56
55
|
"jest": "^29.6.1",
|
|
57
56
|
"jest-environment-jsdom": "^29.6.1",
|
|
58
57
|
"jest-expo": "^51.0.4",
|
|
59
58
|
"jest-websocket-mock": "^2.4.0",
|
|
60
59
|
"pod-install": "^0.2.0",
|
|
61
|
-
"react": "^18.2.0",
|
|
62
60
|
"react-dom": "^18.3.1",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"typedoc": "^0.26.8",
|
|
61
|
+
"ts-proto": "^2.2.5",
|
|
62
|
+
"typedoc": "^0.26.11",
|
|
66
63
|
"typedoc-plugin-mark-react-functional-components": "^0.2.2",
|
|
67
64
|
"typescript": "^5.6.3"
|
|
68
65
|
},
|
|
69
66
|
"peerDependencies": {
|
|
70
67
|
"expo": "*",
|
|
68
|
+
"expo-modules-core": "*",
|
|
71
69
|
"react": "*",
|
|
72
70
|
"react-native": "*"
|
|
73
71
|
},
|