@fishjam-cloud/react-native-client 0.23.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 (262) 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 +2 -2
  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 -3
  28. package/plugin/build/withFishjam.d.ts +31 -2
  29. package/plugin/build/withFishjam.js +32 -6
  30. package/plugin/build/withFishjamAndroid.d.ts +2 -2
  31. package/plugin/build/withFishjamAndroid.js +60 -13
  32. package/plugin/build/withFishjamIos.d.ts +3 -8
  33. package/plugin/build/withFishjamIos.js +54 -69
  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 -53
  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 -20
  134. package/build/hooks/useAppScreenShare.d.ts.map +0 -1
  135. package/build/hooks/useAppScreenShare.js +0 -54
  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 -95
  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 -37
  185. package/build/hooks/useScreenShare.d.ts.map +0 -1
  186. package/build/hooks/useScreenShare.js +0 -52
  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/useLivestreamStreamer.d.ts +0 -65
  205. package/build/livestream/hooks/useLivestreamStreamer.d.ts.map +0 -1
  206. package/build/livestream/hooks/useLivestreamStreamer.js +0 -72
  207. package/build/livestream/hooks/useLivestreamStreamer.js.map +0 -1
  208. package/build/livestream/hooks/useLivestreamViewer.d.ts +0 -36
  209. package/build/livestream/hooks/useLivestreamViewer.d.ts.map +0 -1
  210. package/build/livestream/hooks/useLivestreamViewer.js +0 -73
  211. package/build/livestream/hooks/useLivestreamViewer.js.map +0 -1
  212. package/build/livestream/index.d.ts +0 -11
  213. package/build/livestream/index.d.ts.map +0 -1
  214. package/build/livestream/index.js +0 -6
  215. package/build/livestream/index.js.map +0 -1
  216. package/build/protos/fishjam/peer_notifications.d.ts +0 -63
  217. package/build/protos/fishjam/peer_notifications.d.ts.map +0 -1
  218. package/build/protos/fishjam/peer_notifications.js +0 -235
  219. package/build/protos/fishjam/peer_notifications.js.map +0 -1
  220. package/build/types.d.ts +0 -34
  221. package/build/types.d.ts.map +0 -1
  222. package/build/types.js +0 -2
  223. package/build/types.js.map +0 -1
  224. package/build/utils/config.d.ts +0 -6
  225. package/build/utils/config.d.ts.map +0 -1
  226. package/build/utils/config.js +0 -10
  227. package/build/utils/config.js.map +0 -1
  228. package/build/utils/errorListener.d.ts +0 -2
  229. package/build/utils/errorListener.d.ts.map +0 -1
  230. package/build/utils/errorListener.js +0 -15
  231. package/build/utils/errorListener.js.map +0 -1
  232. package/build/utils/eventPayloadValidator.d.ts +0 -3
  233. package/build/utils/eventPayloadValidator.d.ts.map +0 -1
  234. package/build/utils/eventPayloadValidator.js +0 -86
  235. package/build/utils/eventPayloadValidator.js.map +0 -1
  236. package/build/utils/getFishjamUrl.d.ts +0 -2
  237. package/build/utils/getFishjamUrl.d.ts.map +0 -1
  238. package/build/utils/getFishjamUrl.js +0 -10
  239. package/build/utils/getFishjamUrl.js.map +0 -1
  240. package/debug/package.json +0 -4
  241. package/expo-module.config.json +0 -19
  242. package/ios/CameraPermissionsRequester.swift +0 -117
  243. package/ios/Events.swift +0 -152
  244. package/ios/PictureInPictureManager.swift +0 -215
  245. package/ios/PipContainerView.swift +0 -56
  246. package/ios/PipContainerViewModule.swift +0 -48
  247. package/ios/RNFishjamClient.podspec +0 -30
  248. package/ios/RNFishjamClient.swift +0 -995
  249. package/ios/RNFishjamClientModule.swift +0 -289
  250. package/ios/RNFishjamProxy.swift +0 -12
  251. package/ios/Utils/PermissionUtils.swift +0 -16
  252. package/ios/Utils.swift +0 -23
  253. package/ios/VideoPreviewView.swift +0 -54
  254. package/ios/VideoPreviewViewModule.swift +0 -21
  255. package/ios/VideoRendererView.swift +0 -98
  256. package/ios/VideoRendererViewModule.swift +0 -23
  257. package/ios/extensions/AVCaptureDevice.swift +0 -20
  258. package/ios/managers/LocalCameraTracksChangedListenersManager.swift +0 -23
  259. package/ios/managers/TracksUpdateListenersManager.swift +0 -21
  260. package/livestream/package.json +0 -4
  261. package/plugin/broadcastExtensionFiles/FishjamBroadcastSampleHandler.swift +0 -50
  262. /package/plugin/broadcastExtensionFiles/{FishjamScreenBroadcastExtension.entitlements → ScreenBroadcastExtension.entitlements} +0 -0
@@ -1,61 +0,0 @@
1
- package io.fishjam.reactnative
2
-
3
- import android.content.Context
4
- import android.os.Handler
5
- import android.os.Looper
6
- import com.twilio.audioswitch.AudioDevice
7
- import com.twilio.audioswitch.AudioDeviceChangeListener
8
- import com.twilio.audioswitch.AudioSwitch
9
-
10
- class AudioSwitchManager(
11
- private val context: Context
12
- ) {
13
- private var preferredDeviceList =
14
- listOf(
15
- AudioDevice.BluetoothHeadset::class.java,
16
- AudioDevice.WiredHeadset::class.java,
17
- AudioDevice.Speakerphone::class.java,
18
- AudioDevice.Earpiece::class.java
19
- )
20
-
21
- // AudioSwitch is not threadsafe, so all calls should be done on the main thread.
22
- private val handler: Handler = Handler(Looper.getMainLooper())
23
-
24
- private var audioSwitch: AudioSwitch =
25
- AudioSwitch(context, loggingEnabled = true, preferredDeviceList = preferredDeviceList)
26
-
27
- fun start(listener: AudioDeviceChangeListener) {
28
- handler.removeCallbacksAndMessages(null)
29
- handler.postAtFrontOfQueue {
30
- audioSwitch.start(listener)
31
- audioSwitch.activate()
32
- }
33
- }
34
-
35
- fun stop() {
36
- handler.removeCallbacksAndMessages(null)
37
- handler.postAtFrontOfQueue {
38
- audioSwitch.stop()
39
- }
40
- }
41
-
42
- fun selectedAudioDevice(): AudioDevice? = audioSwitch.selectedAudioDevice
43
-
44
- fun availableAudioDevices(): List<AudioDevice> = audioSwitch.availableAudioDevices
45
-
46
- fun selectAudioOutput(audioDeviceClass: Class<out AudioDevice?>) {
47
- handler.post {
48
- availableAudioDevices()
49
- .find { it.javaClass == audioDeviceClass }
50
- ?.let {
51
- audioSwitch.selectDevice(it)
52
- }
53
- }
54
- }
55
-
56
- fun selectAudioOutput(kind: AudioDeviceKind?) {
57
- if (kind != null) {
58
- selectAudioOutput(kind.audioDeviceClass)
59
- }
60
- }
61
- }
@@ -1,126 +0,0 @@
1
- package io.fishjam.reactnative
2
-
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")
15
- }
16
-
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
- TrackAspectRatioUpdated
33
- }
34
-
35
- val name: String
36
- get() = event.name
37
-
38
- val data: Map<String, Any?>
39
- get() = mapOf(event.name to eventContent)
40
-
41
- companion object {
42
- fun isMicrophoneOn(enabled: Boolean) = EmitableEvent(EventName.IsMicrophoneOn, enabled)
43
-
44
- fun isScreenShareOn(enabled: Boolean) = EmitableEvent(EventName.IsScreenShareOn, enabled)
45
-
46
- fun bandwidthEstimation(estimation: Long) = EmitableEvent(EventName.BandwidthEstimation, estimation.toFloat())
47
-
48
- fun warning(message: String) = EmitableEvent(EventName.Warning, message)
49
-
50
- fun peerStatusChanged(peerStatus: PeerStatus) = EmitableEvent(EventName.PeerStatusChanged, peerStatus.status)
51
-
52
- fun reconnectionStatusChanged(reconnectionStatus: ReconnectionStatus) =
53
- EmitableEvent(EventName.ReconnectionStatusChanged, reconnectionStatus.status)
54
-
55
- fun currentCameraChanged(
56
- localCamera: LocalCamera?,
57
- isCameraOn: Boolean,
58
- isCameraInitialized: Boolean
59
- ) = EmitableEvent(
60
- EventName.CurrentCameraChanged,
61
- mapOf(
62
- "currentCamera" to localCamera,
63
- "isCameraOn" to isCameraOn,
64
- "isCameraInitialized" to isCameraInitialized
65
- )
66
- )
67
-
68
- fun simulcastConfigUpdate(simulcastConfig: SimulcastConfig) =
69
- EmitableEvent(
70
- EventName.SimulcastConfigUpdate,
71
- mapOf(
72
- "enabled" to simulcastConfig.enabled,
73
- "activeEncodings" to simulcastConfig.activeEncodings.map { it.rid }
74
- )
75
- )
76
-
77
- fun peersUpdate(peersData: List<Map<String, Any?>>) = EmitableEvent(EventName.PeersUpdate, peersData)
78
-
79
- fun audioDeviceUpdate(
80
- audioDevices: List<AudioDevice>,
81
- selectedDevice: AudioDevice?
82
- ): EmitableEvent {
83
- val audioDeviceAsMap = { audioDevice: AudioDevice ->
84
- mapOf(
85
- "name" to audioDevice.name,
86
- "type" to AudioDeviceKind.fromAudioDevice(audioDevice)?.typeName
87
- )
88
- }
89
-
90
- return EmitableEvent(
91
- EventName.AudioDeviceUpdate,
92
- mapOf(
93
- "selectedDevice" to (
94
- if (selectedDevice != null) {
95
- audioDeviceAsMap(
96
- selectedDevice
97
- )
98
- } else {
99
- null
100
- }
101
- ),
102
- "availableDevices" to
103
- audioDevices.map { audioDevice ->
104
- audioDeviceAsMap(
105
- audioDevice
106
- )
107
- }
108
- )
109
- )
110
- }
111
-
112
- fun trackAspectRatioUpdated(
113
- trackId: String,
114
- aspectRatio: Double?
115
- ) = EmitableEvent(
116
- EventName.TrackAspectRatioUpdated,
117
- mapOf(
118
- "trackId" to trackId,
119
- "aspectRatio" to aspectRatio
120
- )
121
- )
122
-
123
- val allEvents: Array<String>
124
- get() = EventName.entries.map { it.name }.toTypedArray()
125
- }
126
- }
@@ -1,31 +0,0 @@
1
- package io.fishjam.reactnative
2
-
3
- import com.fishjamcloud.client.models.AuthError
4
- import expo.modules.kotlin.exception.CodedException
5
-
6
- class JoinError(
7
- metadata: Any
8
- ) : CodedException(message = "Join error: $metadata")
9
-
10
- class ConnectionError(
11
- reason: AuthError
12
- ) : CodedException(message = "Connection error: ${reason.error}")
13
-
14
- class MissingScreenSharePermission : CodedException(message = "No permission to start screen share.")
15
-
16
- class ClientNotConnectedError : CodedException(message = "Client not connected to server yet. Make sure to call connect() first!")
17
-
18
- class NoLocalVideoTrackError : CodedException(message = "No local video track. Make sure to call connect() first!")
19
-
20
- class NoLocalAudioTrackError : CodedException(message = "No local audio track. Make sure to call connect() first!")
21
-
22
- class NoScreenShareTrackError : CodedException(message = "No local screen share track. Make sure to toggle screen share on first!")
23
-
24
- class SocketClosedError(
25
- code: Int,
26
- reason: String
27
- ) : CodedException(message = "Socket was closed with code = $code and reason = $reason")
28
-
29
- class SocketError(
30
- message: String
31
- ) : CodedException(message = "Socket error: $message")
@@ -1,282 +0,0 @@
1
- package io.fishjam.reactnative
2
-
3
- import android.app.PictureInPictureParams
4
- import android.content.Context
5
- import android.os.Build
6
- import android.util.Log
7
- import android.view.View
8
- import android.view.ViewGroup
9
- import androidx.annotation.RequiresApi
10
- import androidx.fragment.app.FragmentActivity
11
- import expo.modules.kotlin.AppContext
12
- import expo.modules.kotlin.views.ExpoView
13
- import io.fishjam.reactnative.helpers.PictureInPictureHelperFragment
14
- import io.fishjam.reactnative.managers.TrackUpdateListener
15
- import java.lang.ref.WeakReference
16
-
17
- data class RemoteTrackInfo(
18
- val videoTrack: com.fishjamcloud.client.media.VideoTrack?,
19
- val displayName: String?,
20
- val videoTrackActive: Boolean
21
- )
22
-
23
- class PipContainerView(
24
- context: Context,
25
- appContext: AppContext
26
- ) : ExpoView(context, appContext), TrackUpdateListener {
27
-
28
- companion object {
29
- private const val TAG = "PipContainerView"
30
- }
31
-
32
- private val activityRef: WeakReference<FragmentActivity?> = WeakReference(
33
- appContext.currentActivity as? FragmentActivity
34
- )
35
-
36
- private val decorView = activityRef.get()?.window?.decorView
37
- private val rootView = decorView?.findViewById<ViewGroup>(android.R.id.content)
38
- private val rootViewChildrenOriginalVisibility: ArrayList<Int> = arrayListOf()
39
-
40
- private var pictureInPictureHelperTag: String? = null
41
- private var pipViews: PipViewContainer? = null
42
- private var isPipActive = false
43
-
44
- private val trackSelector = PipTrackSelector()
45
- private val viewFactory by lazy { PipViewFactory(context, appContext) }
46
-
47
- @RequiresApi(Build.VERSION_CODES.O)
48
- private val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
49
-
50
- var startAutomatically: Boolean = true
51
- set(value) {
52
- field = value
53
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
54
- updateAutoEnterEnabled()
55
- }
56
- }
57
-
58
- var stopAutomatically: Boolean = true
59
-
60
- var primaryPlaceholderText: String = "No camera"
61
- set(value) {
62
- field = value
63
- pipViews?.primaryPlaceholder?.text = value
64
- }
65
-
66
- var secondaryPlaceholderText: String = "No active speaker"
67
- set(value) {
68
- field = value
69
- pipViews?.secondaryPlaceholder?.text = value
70
- }
71
-
72
- private var remoteTrackInfo: RemoteTrackInfo? = null
73
-
74
- @RequiresApi(Build.VERSION_CODES.O)
75
- private fun updatePictureInPictureParams() {
76
- val activity = activityRef.get()
77
- if (activity == null) {
78
- Log.w(TAG, "Cannot update PiP params: activity reference is null")
79
- return
80
- }
81
-
82
- try {
83
- activity.setPictureInPictureParams(pictureInPictureParamsBuilder.build())
84
- } catch (e: IllegalStateException) {
85
- Log.e(TAG, "Failed to update PiP params", e)
86
- emitPipNotSupportedWarning()
87
- }
88
- }
89
-
90
- private fun emitPipNotSupportedWarning() {
91
- RNFishjamClient.sendEvent(
92
- EmitableEvent.warning(
93
- "Picture-in-Picture is not supported. Enable it in app.json."
94
- )
95
- )
96
- }
97
-
98
- @RequiresApi(Build.VERSION_CODES.S)
99
- private fun updateAutoEnterEnabled() {
100
- pictureInPictureParamsBuilder.setAutoEnterEnabled(startAutomatically)
101
- updatePictureInPictureParams()
102
- }
103
-
104
- private fun updatePipViews() {
105
- val views = pipViews ?: run {
106
- Log.w(TAG, "Cannot update PiP views: pipViews is null")
107
- return
108
- }
109
-
110
- val localCameraTrack = trackSelector.findLocalCameraTrack()
111
- updatePrimaryView(views, localCameraTrack)
112
-
113
- remoteTrackInfo = trackSelector.findSecondaryRemoteTrack(remoteTrackInfo)
114
- updateSecondaryView(views, remoteTrackInfo)
115
- }
116
-
117
- private fun updatePrimaryView(
118
- views: PipViewContainer,
119
- localCameraTrack: com.fishjamcloud.client.media.VideoTrack?
120
- ) {
121
- if (localCameraTrack != null && localCameraTrack.isEnabled()) {
122
- views.primaryVideoView.init(localCameraTrack.id())
123
- views.primaryVideoView.visibility = View.VISIBLE
124
- views.primaryPlaceholder.visibility = View.GONE
125
- } else {
126
- views.primaryVideoView.visibility = View.GONE
127
- views.primaryPlaceholder.visibility = View.VISIBLE
128
- }
129
- }
130
-
131
- private fun updateSecondaryView(
132
- views: PipViewContainer,
133
- trackInfo: RemoteTrackInfo?
134
- ) {
135
- trackInfo?.let { info ->
136
- if (info.videoTrackActive && info.videoTrack != null) {
137
- views.secondaryVideoView.init(info.videoTrack.id())
138
- views.secondaryVideoView.visibility = View.VISIBLE
139
- views.secondaryPlaceholder.visibility = View.GONE
140
-
141
- info.displayName?.let { displayName ->
142
- views.secondaryNameOverlay.text = displayName
143
- views.secondaryNameOverlay.visibility = View.VISIBLE
144
- } ?: run {
145
- views.secondaryNameOverlay.visibility = View.GONE
146
- }
147
- } else {
148
- views.secondaryVideoView.visibility = View.GONE
149
- views.secondaryPlaceholder.text = info.displayName
150
- views.secondaryPlaceholder.visibility = View.VISIBLE
151
- views.secondaryNameOverlay.visibility = View.GONE
152
- }
153
- } ?: run {
154
- views.secondaryVideoView.visibility = View.GONE
155
- views.secondaryPlaceholder.text = secondaryPlaceholderText
156
- views.secondaryPlaceholder.visibility = View.VISIBLE
157
- views.secondaryNameOverlay.visibility = View.GONE
158
- }
159
- views.secondaryContainer.visibility = View.VISIBLE
160
- }
161
-
162
- @RequiresApi(Build.VERSION_CODES.O)
163
- fun startPictureInPicture() {
164
- val activity = activityRef.get()
165
- if (activity == null) {
166
- Log.w(TAG, "Cannot start PiP: activity reference is null")
167
- return
168
- }
169
-
170
- try {
171
- activity.enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
172
- } catch (e: IllegalStateException) {
173
- Log.e(TAG, "Failed to enter PiP mode", e)
174
- emitPipNotSupportedWarning()
175
- }
176
- }
177
-
178
- fun stopPictureInPicture() {
179
- Log.d(TAG, "stopPictureInPicture called, but no-op on Android")
180
- }
181
-
182
- override fun onAttachedToWindow() {
183
- super.onAttachedToWindow()
184
-
185
- activityRef.get()?.let { activity ->
186
- val fragment = PictureInPictureHelperFragment(this)
187
- pictureInPictureHelperTag = fragment.id
188
- activity.supportFragmentManager.beginTransaction()
189
- .add(fragment, fragment.id)
190
- .commitAllowingStateLoss()
191
- } ?: Log.w(TAG, "Cannot attach PiP helper: activity reference is null")
192
-
193
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
194
- updateAutoEnterEnabled()
195
- }
196
-
197
- RNFishjamClient.trackUpdateListenersManager.add(this)
198
- }
199
-
200
- override fun onDetachedFromWindow() {
201
- super.onDetachedFromWindow()
202
-
203
- activityRef.get()?.let { activity ->
204
- pictureInPictureHelperTag?.let { tag ->
205
- activity.supportFragmentManager.findFragmentByTag(tag)?.let { fragment ->
206
- activity.supportFragmentManager.beginTransaction()
207
- .remove(fragment)
208
- .commitAllowingStateLoss()
209
- }
210
- }
211
- }
212
-
213
- startAutomatically = false
214
- RNFishjamClient.trackUpdateListenersManager.remove(this)
215
- }
216
-
217
- override fun onTracksUpdate() {
218
- if (isPipActive) {
219
- updatePipViews()
220
- }
221
- }
222
-
223
- fun layoutForPiPEnter() {
224
- val root = rootView
225
- if (root == null) {
226
- Log.w(TAG, "Cannot enter PiP layout: rootView is null")
227
- return
228
- }
229
-
230
- isPipActive = true
231
-
232
- hideAllRootViewChildren(root)
233
- pipViews = viewFactory.createPipViews(primaryPlaceholderText, secondaryPlaceholderText)
234
- pipViews?.let { views ->
235
- root.addView(views.splitScreenContainer)
236
- }
237
-
238
- updatePipViews()
239
- }
240
-
241
- fun layoutForPiPExit() {
242
- val root = rootView
243
- if (root == null) {
244
- Log.w(TAG, "Cannot exit PiP layout: rootView is null")
245
- return
246
- }
247
-
248
- isPipActive = false
249
-
250
- pipViews?.let { views ->
251
- root.removeView(views.splitScreenContainer)
252
- cleanUpViews(views)
253
- }
254
- pipViews = null
255
-
256
- restoreRootViewChildren(root)
257
- }
258
-
259
- private fun cleanUpViews(views: PipViewContainer) {
260
- views.primaryVideoView.dispose()
261
- views.secondaryVideoView.dispose()
262
- }
263
-
264
- private fun hideAllRootViewChildren(rootView: ViewGroup) {
265
- rootViewChildrenOriginalVisibility.clear()
266
- (0 until rootView.childCount).forEach { i ->
267
- val child = rootView.getChildAt(i)
268
- rootViewChildrenOriginalVisibility.add(child.visibility)
269
- child.visibility = View.GONE
270
- }
271
- }
272
-
273
- private fun restoreRootViewChildren(rootView: ViewGroup) {
274
- rootViewChildrenOriginalVisibility.forEachIndexed { index, originalVisibility ->
275
- if (index < rootView.childCount) {
276
- rootView.getChildAt(index).visibility = originalVisibility
277
- }
278
- }
279
- rootViewChildrenOriginalVisibility.clear()
280
- }
281
- }
282
-
@@ -1,41 +0,0 @@
1
- package io.fishjam.reactnative
2
-
3
- import expo.modules.kotlin.modules.Module
4
- import expo.modules.kotlin.modules.ModuleDefinition
5
-
6
- class PipContainerViewModule : Module() {
7
- override fun definition() =
8
- ModuleDefinition {
9
- Name("PipContainerViewModule")
10
-
11
- View(PipContainerView::class) {
12
- Prop("startAutomatically") { view: PipContainerView, value: Boolean ->
13
- view.startAutomatically = value
14
- }
15
-
16
- Prop("stopAutomatically") { view: PipContainerView, value: Boolean ->
17
- view.stopAutomatically = value
18
- }
19
-
20
- // iOS-only property, no-op on Android
21
- Prop("allowsCameraInBackground") { _: PipContainerView, _: Boolean -> }
22
-
23
- Prop("primaryPlaceholderText") { view: PipContainerView, value: String ->
24
- view.primaryPlaceholderText = value
25
- }
26
-
27
- Prop("secondaryPlaceholderText") { view: PipContainerView, value: String ->
28
- view.secondaryPlaceholderText = value
29
- }
30
-
31
- AsyncFunction("startPictureInPicture") { view: PipContainerView ->
32
- view.startPictureInPicture()
33
- }
34
-
35
- AsyncFunction("stopPictureInPicture") { view: PipContainerView ->
36
- view.stopPictureInPicture()
37
- }
38
- }
39
- }
40
- }
41
-
@@ -1,98 +0,0 @@
1
- package io.fishjam.reactnative
2
-
3
- import com.fishjamcloud.client.media.RemoteAudioTrack
4
- import com.fishjamcloud.client.media.Track
5
- import com.fishjamcloud.client.media.VideoTrack
6
- import com.fishjamcloud.client.models.Peer
7
- import fishjam.media_events.server.Server
8
-
9
- class PipTrackSelector {
10
- companion object {
11
- private const val METADATA_TYPE = "type"
12
- private const val METADATA_CAMERA = "camera"
13
- private const val METADATA_DISPLAY_NAME = "displayName"
14
- private const val METADATA_NAME = "name"
15
- }
16
-
17
- fun findLocalCameraTrack(): VideoTrack? {
18
- val peers = RNFishjamClient.getAllPeers()
19
- val localEndpointId = RNFishjamClient.fishjamClient.getLocalEndpoint().id
20
- val localPeer = peers.find { it.id == localEndpointId } ?: return null
21
-
22
- return localPeer.tracks.values
23
- .filterIsInstance<VideoTrack>()
24
- .firstOrNull { track ->
25
- (track.metadata as? Map<*, *>)?.get(METADATA_TYPE) == METADATA_CAMERA
26
- }
27
- }
28
-
29
- fun findSecondaryRemoteTrack(currentTrackInfo: RemoteTrackInfo?): RemoteTrackInfo? {
30
- val peers = RNFishjamClient.getAllPeers()
31
- val localEndpointId = RNFishjamClient.fishjamClient.getLocalEndpoint().id
32
- val remotePeers = peers.filter { it.id != localEndpointId }
33
-
34
- if (remotePeers.isEmpty()) {
35
- return null
36
- }
37
-
38
- remotePeers.firstOrNull { it.hasActiveVoiceActivity() }?.let { activeSpeaker ->
39
- return activeSpeaker.toRemoteTrackInfo()
40
- }
41
-
42
- currentTrackInfo?.let { currentInfo ->
43
- val existingPeer = remotePeers.firstOrNull() { peer -> peer.hasTrack(currentInfo.videoTrack) }
44
- if (existingPeer != null) {
45
- return existingPeer.toRemoteTrackInfo()
46
- }
47
- }
48
-
49
- remotePeers.firstOrNull { it.hasVideoTrack() }?.let { peerWithVideo ->
50
- return peerWithVideo.toRemoteTrackInfo()
51
- }
52
-
53
- return null
54
- }
55
- }
56
-
57
- private fun Peer.hasActiveVoiceActivity(): Boolean {
58
- return tracks.values
59
- .filterIsInstance<RemoteAudioTrack>()
60
- .any { it.vadStatus == Server.MediaEvent.VadNotification.Status.STATUS_SPEECH }
61
- }
62
-
63
- private fun Peer.hasTrack(videoTrack: VideoTrack?): Boolean {
64
- return videoTrack != null && tracks.values.contains(videoTrack)
65
- }
66
-
67
- private fun Peer.hasVideoTrack(): Boolean {
68
- return tracks.values.any { it is VideoTrack }
69
- }
70
-
71
- private fun Peer.getDisplayName(): String {
72
- val serverMetadata = metadata?.get("peer") as? Map<*, *>
73
- val displayName = serverMetadata?.get("displayName") as? String
74
- return displayName ?: id
75
- }
76
-
77
- private fun Track.getTrackActive(): Boolean {
78
-
79
- if (metadata["active"] as? Boolean == false) {
80
- return false
81
- }
82
-
83
- if (metadata["paused"] as? Boolean == true) {
84
- return false
85
- }
86
-
87
- return true
88
- }
89
-
90
- private fun Peer.toRemoteTrackInfo(): RemoteTrackInfo {
91
- val videoTrack = tracks.values.filterIsInstance<VideoTrack>().firstOrNull()
92
- return RemoteTrackInfo(
93
- videoTrack = videoTrack,
94
- displayName = getDisplayName(),
95
- videoTrackActive = videoTrack?.getTrackActive() ?: false
96
- )
97
- }
98
-