@fishjam-cloud/react-native-client 0.2.1 → 0.2.2

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 (24) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/AndroidManifest.xml +2 -0
  3. package/android/src/main/java/io/fishjam/reactnative/AudioDeviceKind.kt +34 -0
  4. package/android/src/main/java/io/fishjam/reactnative/AudioSwitchManager.kt +61 -0
  5. package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +14 -0
  6. package/android/src/main/java/io/fishjam/reactnative/Errors.kt +31 -0
  7. package/android/src/main/java/io/fishjam/reactnative/FishjamForegroundService.kt +90 -0
  8. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +870 -0
  9. package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +370 -0
  10. package/android/src/main/java/io/fishjam/reactnative/Utils.kt +11 -0
  11. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewView.kt +40 -0
  12. package/android/src/main/java/io/fishjam/reactnative/VideoPreviewViewModule.kt +17 -0
  13. package/android/src/main/java/io/fishjam/reactnative/VideoRendererView.kt +58 -0
  14. package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +25 -0
  15. package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +77 -0
  16. package/package.json +4 -4
  17. package/plugin/build/types.d.ts +9 -0
  18. package/plugin/build/types.js +2 -0
  19. package/plugin/build/withFishjam.d.ts +4 -0
  20. package/plugin/build/withFishjam.js +13 -0
  21. package/plugin/build/withFishjamAndroid.d.ts +3 -0
  22. package/plugin/build/withFishjamAndroid.js +32 -0
  23. package/plugin/build/withFishjamIos.d.ts +9 -0
  24. package/plugin/build/withFishjamIos.js +222 -0
@@ -0,0 +1,370 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import android.content.Intent
4
+ import android.os.Build
5
+ import expo.modules.kotlin.Promise
6
+ import expo.modules.kotlin.exception.CodedException
7
+ import expo.modules.kotlin.functions.Coroutine
8
+ import expo.modules.kotlin.modules.Module
9
+ import expo.modules.kotlin.modules.ModuleDefinition
10
+ import expo.modules.kotlin.records.Field
11
+ import expo.modules.kotlin.records.Record
12
+ import kotlinx.coroutines.CoroutineScope
13
+ import kotlinx.coroutines.Dispatchers
14
+ import kotlinx.coroutines.launch
15
+ import kotlinx.coroutines.sync.Mutex
16
+ import kotlinx.coroutines.sync.withLock
17
+ import kotlinx.coroutines.withContext
18
+
19
+ class SimulcastConfig : Record {
20
+ @Field
21
+ val enabled: Boolean = false
22
+
23
+ @Field
24
+ val activeEncodings: List<String> = emptyList()
25
+ }
26
+
27
+ class CameraConfig : Record {
28
+ @Field
29
+ val quality: String = "VGA169"
30
+
31
+ @Field
32
+ val flipVideo: Boolean = false
33
+
34
+ @Field
35
+ val videoTrackMetadata: Map<String, Any> = emptyMap()
36
+
37
+ @Field
38
+ val simulcastConfig: SimulcastConfig = SimulcastConfig()
39
+
40
+ // expo-modules on Android don't support Either type
41
+ @Field
42
+ val maxBandwidthMap: Map<String, Int> = emptyMap()
43
+
44
+ @Field
45
+ val maxBandwidthInt: Int = 0
46
+
47
+ @Field
48
+ val cameraEnabled: Boolean = true
49
+
50
+ @Field
51
+ val cameraId: String? = null
52
+ }
53
+
54
+ class ScreencastOptions : Record {
55
+ @Field
56
+ val quality: String = "HD15"
57
+
58
+ @Field
59
+ val screencastMetadata: Map<String, Any> = emptyMap()
60
+
61
+ @Field
62
+ val simulcastConfig: SimulcastConfig = SimulcastConfig()
63
+
64
+ @Field
65
+ val maxBandwidthMap: Map<String, Int> = emptyMap()
66
+
67
+ @Field
68
+ val maxBandwidthInt: Int = 0
69
+ }
70
+
71
+ class ReconnectConfig : Record {
72
+ @Field
73
+ val maxAttempts: Int = 5
74
+
75
+ @Field
76
+ val initialDelayMs: Long = 1000
77
+
78
+ @Field
79
+ val delayMs: Long = 1000
80
+ }
81
+
82
+ class ConnectConfig : Record {
83
+ @Field
84
+ val reconnectConfig: ReconnectConfig = ReconnectConfig()
85
+ }
86
+
87
+ class ForegroundServiceConfig : Record {
88
+ @Field
89
+ val channelId: String? = null
90
+
91
+ @Field
92
+ val channelName: String? = null
93
+
94
+ @Field
95
+ val notificationContent: String? = null
96
+
97
+ @Field
98
+ val notificationTitle: String? = null
99
+
100
+ @Field
101
+ val foregroundServiceTypes: IntArray = intArrayOf()
102
+ }
103
+
104
+ class RNFishjamClientModule : Module() {
105
+ override fun definition() =
106
+ ModuleDefinition {
107
+ Name("RNFishjamClient")
108
+
109
+ Events(
110
+ "IsCameraOn",
111
+ "IsMicrophoneOn",
112
+ "IsScreencastOn",
113
+ "SimulcastConfigUpdate",
114
+ "PeersUpdate",
115
+ "AudioDeviceUpdate",
116
+ "SendMediaEvent",
117
+ "BandwidthEstimation",
118
+ "ReconnectionRetriesLimitReached",
119
+ "ReconnectionStarted",
120
+ "Reconnected"
121
+ )
122
+
123
+ val rnFishjamClient =
124
+ RNFishjamClient { name: String, data: Map<String, Any?> ->
125
+ sendEvent(name, data)
126
+ }
127
+
128
+ val mutex = Mutex()
129
+
130
+ OnCreate {
131
+ rnFishjamClient.onModuleCreate(appContext)
132
+ }
133
+
134
+ OnDestroy {
135
+ rnFishjamClient.onModuleDestroy()
136
+ }
137
+
138
+ OnActivityDestroys {
139
+ rnFishjamClient.leaveRoom()
140
+ }
141
+
142
+ OnActivityResult { _, result ->
143
+ rnFishjamClient.onActivityResult(result.requestCode, result.resultCode, result.data)
144
+ }
145
+
146
+ AsyncFunction(
147
+ "joinRoom"
148
+ ) { url: String, participantToken: String, participantMetadata: Map<String, Any>, config: ConnectConfig, promise: Promise ->
149
+ CoroutineScope(Dispatchers.Main).launch {
150
+ rnFishjamClient.joinRoom(url, participantToken, participantMetadata, config, promise)
151
+ }
152
+ }
153
+
154
+ AsyncFunction("leaveRoom") Coroutine { ->
155
+ withContext(Dispatchers.Main) {
156
+ rnFishjamClient.leaveRoom()
157
+ }
158
+ }
159
+
160
+ AsyncFunction("startCamera") Coroutine { config: CameraConfig ->
161
+ withContext(Dispatchers.Main) {
162
+ rnFishjamClient.startCamera(config)
163
+ }
164
+ }
165
+
166
+ Property("isMicrophoneOn") {
167
+ return@Property rnFishjamClient.isMicrophoneOn
168
+ }
169
+
170
+ AsyncFunction("toggleMicrophone") Coroutine { ->
171
+ withContext(Dispatchers.Main) {
172
+ rnFishjamClient.toggleMicrophone()
173
+ }
174
+ }
175
+
176
+ Property("isCameraOn") {
177
+ return@Property rnFishjamClient.isCameraOn
178
+ }
179
+
180
+ AsyncFunction("toggleCamera") Coroutine { ->
181
+ withContext(Dispatchers.Main) {
182
+ rnFishjamClient.toggleCamera()
183
+ }
184
+ }
185
+
186
+ AsyncFunction("flipCamera") Coroutine { ->
187
+ mutex.withLock {
188
+ withContext(Dispatchers.Main) {
189
+ rnFishjamClient.flipCamera()
190
+ }
191
+ }
192
+ }
193
+
194
+ AsyncFunction("switchCamera") Coroutine { cameraId: String ->
195
+ mutex.withLock {
196
+ withContext(Dispatchers.Main) {
197
+ rnFishjamClient.switchCamera(cameraId)
198
+ }
199
+ }
200
+ }
201
+
202
+ AsyncFunction("handleScreencastPermission") { promise: Promise ->
203
+ CoroutineScope(Dispatchers.Main).launch {
204
+ rnFishjamClient.handleScreencastPermission(promise)
205
+ }
206
+ }
207
+
208
+ AsyncFunction("toggleScreencast") Coroutine { screencastOptions: ScreencastOptions ->
209
+ withContext(Dispatchers.Main) {
210
+ rnFishjamClient.toggleScreencast(screencastOptions)
211
+ }
212
+ }
213
+
214
+ Property("cameras") {
215
+ return@Property rnFishjamClient.getCaptureDevices()
216
+ }
217
+
218
+ Property("isScreencastOn") {
219
+ return@Property rnFishjamClient.isScreencastOn
220
+ }
221
+
222
+ AsyncFunction("getPeers") Coroutine { ->
223
+ withContext(Dispatchers.Main) {
224
+ rnFishjamClient.getPeers()
225
+ }
226
+ }
227
+
228
+ AsyncFunction("updatePeerMetadata") Coroutine { metadata: Map<String, Any> ->
229
+ withContext(Dispatchers.Main) {
230
+ rnFishjamClient.updatePeerMetadata(metadata)
231
+ }
232
+ }
233
+
234
+ AsyncFunction("updateVideoTrackMetadata") Coroutine { metadata: Map<String, Any> ->
235
+ withContext(Dispatchers.Main) {
236
+ rnFishjamClient.updateLocalVideoTrackMetadata(metadata)
237
+ }
238
+ }
239
+
240
+ AsyncFunction("updateAudioTrackMetadata") Coroutine { metadata: Map<String, Any> ->
241
+ withContext(Dispatchers.Main) {
242
+ rnFishjamClient.updateLocalAudioTrackMetadata(metadata)
243
+ }
244
+ }
245
+
246
+ AsyncFunction("updateScreencastTrackMetadata") Coroutine { metadata: Map<String, Any> ->
247
+ withContext(Dispatchers.Main) {
248
+ rnFishjamClient.updateLocalScreencastTrackMetadata(metadata)
249
+ }
250
+ }
251
+
252
+ AsyncFunction("setOutputAudioDevice") { audioDevice: String ->
253
+ rnFishjamClient.setOutputAudioDevice(audioDevice)
254
+ }
255
+
256
+ AsyncFunction("startAudioSwitcher") {
257
+ rnFishjamClient.startAudioSwitcher()
258
+ }
259
+
260
+ AsyncFunction("stopAudioSwitcher") {
261
+ rnFishjamClient.stopAudioSwitcher()
262
+ }
263
+
264
+ AsyncFunction("toggleScreencastTrackEncoding") Coroutine { encoding: String ->
265
+ withContext(Dispatchers.Main) {
266
+ rnFishjamClient.toggleScreencastTrackEncoding(encoding)
267
+ }
268
+ }
269
+
270
+ AsyncFunction("setScreencastTrackBandwidth") Coroutine { bandwidth: Int ->
271
+ withContext(Dispatchers.Main) {
272
+ rnFishjamClient.setScreencastTrackBandwidth(bandwidth)
273
+ }
274
+ }
275
+
276
+ AsyncFunction("setScreencastTrackEncodingBandwidth") Coroutine { encoding: String, bandwidth: Int ->
277
+ withContext(Dispatchers.Main) {
278
+ rnFishjamClient.setScreencastTrackEncodingBandwidth(encoding, bandwidth)
279
+ }
280
+ }
281
+
282
+ AsyncFunction("setTargetTrackEncoding") Coroutine { trackId: String, encoding: String ->
283
+ withContext(Dispatchers.Main) {
284
+ rnFishjamClient.setTargetTrackEncoding(trackId, encoding)
285
+ }
286
+ }
287
+
288
+ AsyncFunction("toggleVideoTrackEncoding") Coroutine { encoding: String ->
289
+ withContext(Dispatchers.Main) {
290
+ rnFishjamClient.toggleVideoTrackEncoding(encoding)
291
+ }
292
+ }
293
+
294
+ AsyncFunction("setVideoTrackEncodingBandwidth") Coroutine { encoding: String, bandwidth: Int ->
295
+ withContext(Dispatchers.Main) {
296
+ rnFishjamClient.setVideoTrackEncodingBandwidth(encoding, bandwidth)
297
+ }
298
+ }
299
+
300
+ AsyncFunction("setVideoTrackBandwidth") Coroutine { bandwidth: Int ->
301
+ withContext(Dispatchers.Main) {
302
+ rnFishjamClient.setVideoTrackBandwidth(bandwidth)
303
+ }
304
+ }
305
+
306
+ AsyncFunction("changeWebRTCLoggingSeverity") Coroutine { severity: String ->
307
+ CoroutineScope(Dispatchers.Main).launch {
308
+ rnFishjamClient.changeWebRTCLoggingSeverity(severity)
309
+ }
310
+ }
311
+
312
+ AsyncFunction("getStatistics") { rnFishjamClient.getStatistics() }
313
+
314
+ Function("startForegroundService") { config: ForegroundServiceConfig ->
315
+ if (appContext.reactContext == null) {
316
+ throw CodedException(message = "reactContext not found")
317
+ }
318
+
319
+ val channelId =
320
+ config.channelId
321
+ ?: throw CodedException(message = "Missing `channelId` for startForegroundService")
322
+ val channelName =
323
+ config.channelName
324
+ ?: throw CodedException(message = "Missing `channelName` for startForegroundService")
325
+ val notificationContent =
326
+ config.notificationContent
327
+ ?: throw CodedException(message = "Missing `notificationContent` for startForegroundService")
328
+ val notificationTitle =
329
+ config.notificationTitle
330
+ ?: throw CodedException(message = "Missing `notificationTitle` for startForegroundService")
331
+ val foregroundServiceTypes = config.foregroundServiceTypes
332
+
333
+ if (foregroundServiceTypes.isEmpty()) {
334
+ throw CodedException(message = "`foregroundServiceTypes` cannot be empty")
335
+ }
336
+
337
+ val serviceIntent =
338
+ Intent(
339
+ appContext.reactContext,
340
+ FishjamForegroundService::class.java
341
+ )
342
+
343
+ serviceIntent.putExtra("channelId", channelId)
344
+ serviceIntent.putExtra("channelName", channelName)
345
+ serviceIntent.putExtra("notificationTitle", notificationContent)
346
+ serviceIntent.putExtra("notificationContent", notificationTitle)
347
+ serviceIntent.putExtra("foregroundServiceTypes", foregroundServiceTypes)
348
+
349
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
350
+ appContext.reactContext!!.startForegroundService(serviceIntent)
351
+ } else {
352
+ appContext.reactContext!!.startService(serviceIntent)
353
+ }
354
+ }
355
+
356
+ Function("stopForegroundService") {
357
+ if (appContext.reactContext == null) {
358
+ throw CodedException(message = "reactContext not found")
359
+ }
360
+
361
+ val serviceIntent: Intent =
362
+ Intent(
363
+ appContext.reactContext,
364
+ FishjamForegroundService::class.java
365
+ )
366
+
367
+ appContext.reactContext!!.stopService(serviceIntent)
368
+ }
369
+ }
370
+ }
@@ -0,0 +1,11 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import com.fishjamcloud.client.models.TrackEncoding
4
+
5
+ internal fun String.toTrackEncoding(): TrackEncoding =
6
+ when (this) {
7
+ "l" -> TrackEncoding.L
8
+ "m" -> TrackEncoding.M
9
+ "h" -> TrackEncoding.H
10
+ else -> throw IllegalArgumentException("Invalid encoding specified: $this")
11
+ }
@@ -0,0 +1,40 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import android.content.Context
4
+ import com.fishjamcloud.client.media.LocalVideoTrack
5
+ import com.fishjamcloud.client.media.VideoTrack
6
+ import expo.modules.kotlin.AppContext
7
+
8
+ class VideoPreviewView(
9
+ context: Context,
10
+ appContext: AppContext
11
+ ) : VideoView(context, appContext) {
12
+ private var localVideoTrack: LocalVideoTrack? = null
13
+
14
+ private fun initialize() {
15
+ localVideoTrack =
16
+ RNFishjamClient.fishjamClient.getLocalEndpoint().tracks.values.firstOrNull { track ->
17
+ track is LocalVideoTrack
18
+ } as? LocalVideoTrack?
19
+
20
+ videoView.let { localVideoTrack?.addRenderer(it) }
21
+ super.setupTrack()
22
+ }
23
+
24
+ override fun dispose() {
25
+ videoView.let { localVideoTrack?.removeRenderer(it) }
26
+ super.dispose()
27
+ }
28
+
29
+ override fun onDetachedFromWindow() {
30
+ super.onDetachedFromWindow()
31
+ dispose()
32
+ }
33
+
34
+ override fun onAttachedToWindow() {
35
+ super.onAttachedToWindow()
36
+ initialize()
37
+ }
38
+
39
+ override fun getVideoTrack(): VideoTrack? = localVideoTrack
40
+ }
@@ -0,0 +1,17 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+
6
+ class VideoPreviewViewModule : Module() {
7
+ override fun definition() =
8
+ ModuleDefinition {
9
+ Name("VideoPreviewViewModule")
10
+
11
+ View(VideoPreviewView::class) {
12
+ Prop("videoLayout") { view: VideoPreviewView, videoLayout: String ->
13
+ view.setVideoLayout(videoLayout)
14
+ }
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,58 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import android.content.Context
4
+ import com.fishjamcloud.client.media.VideoTrack
5
+ import expo.modules.kotlin.AppContext
6
+ import kotlinx.coroutines.CoroutineScope
7
+ import kotlinx.coroutines.Dispatchers
8
+ import kotlinx.coroutines.launch
9
+
10
+ class VideoRendererView(
11
+ context: Context,
12
+ appContext: AppContext
13
+ ) : VideoView(context, appContext),
14
+ RNFishjamClient.OnTrackUpdateListener {
15
+ private var activeVideoTrack: VideoTrack? = null
16
+ private var trackId: String? = null
17
+
18
+ init {
19
+ RNFishjamClient.onTracksUpdateListeners.add(this)
20
+ }
21
+
22
+ private fun setupTrack(videoTrack: VideoTrack) {
23
+ if (activeVideoTrack == videoTrack) return
24
+
25
+ activeVideoTrack?.removeRenderer(videoView)
26
+ activeVideoTrack = videoTrack
27
+
28
+ videoTrack.addRenderer(videoView)
29
+
30
+ super.setupTrack()
31
+ }
32
+
33
+ private fun update() {
34
+ CoroutineScope(Dispatchers.Main).launch {
35
+ val peers = RNFishjamClient.getAllPeers()
36
+ val endpoint = peers.firstOrNull { it.tracks[trackId] != null } ?: return@launch
37
+ val videoTrack = endpoint.tracks[trackId] as? VideoTrack ?: return@launch
38
+ setupTrack(videoTrack)
39
+ }
40
+ }
41
+
42
+ fun init(trackId: String) {
43
+ this.trackId = trackId
44
+ update()
45
+ }
46
+
47
+ override fun dispose() {
48
+ activeVideoTrack?.removeRenderer(videoView)
49
+ RNFishjamClient.onTracksUpdateListeners.remove(this)
50
+ super.dispose()
51
+ }
52
+
53
+ override fun onTracksUpdate() {
54
+ update()
55
+ }
56
+
57
+ override fun getVideoTrack(): VideoTrack? = activeVideoTrack
58
+ }
@@ -0,0 +1,25 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+
6
+ class VideoRendererViewModule : Module() {
7
+ override fun definition() =
8
+ ModuleDefinition {
9
+ Name("VideoRendererViewModule")
10
+
11
+ View(VideoRendererView::class) {
12
+ OnViewDestroys { view: VideoRendererView ->
13
+ view.dispose()
14
+ }
15
+
16
+ Prop("trackId") { view: VideoRendererView, trackId: String ->
17
+ view.init(trackId)
18
+ }
19
+
20
+ Prop("videoLayout") { view: VideoRendererView, videoLayout: String ->
21
+ view.setVideoLayout(videoLayout)
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,77 @@
1
+ package io.fishjam.reactnative
2
+
3
+ import android.animation.ValueAnimator
4
+ import android.content.Context
5
+ import android.graphics.Color
6
+ import android.graphics.drawable.ColorDrawable
7
+ import android.view.animation.LinearInterpolator
8
+ import com.fishjamcloud.client.media.LocalVideoTrack
9
+ import com.fishjamcloud.client.media.VideoTrack
10
+ import expo.modules.kotlin.AppContext
11
+ import expo.modules.kotlin.views.ExpoView
12
+ import kotlinx.coroutines.CoroutineScope
13
+ import kotlinx.coroutines.Dispatchers
14
+ import kotlinx.coroutines.delay
15
+ import org.webrtc.RendererCommon
16
+
17
+ abstract class VideoView(
18
+ context: Context,
19
+ appContext: AppContext
20
+ ) : ExpoView(context, appContext),
21
+ RNFishjamClient.OnLocalTrackSwitchListener {
22
+ protected val videoView =
23
+ RNFishjamClient.fishjamClient.createVideoViewRenderer().also {
24
+ addView(it)
25
+ }
26
+
27
+ private val fadeAnimation: ValueAnimator =
28
+ ValueAnimator.ofArgb(Color.TRANSPARENT, Color.BLACK).apply {
29
+ duration = 200
30
+ interpolator = LinearInterpolator()
31
+ addUpdateListener {
32
+ val colorValue = it.animatedValue as Int
33
+ foreground = ColorDrawable(colorValue)
34
+ }
35
+ }
36
+
37
+ val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main)
38
+
39
+ init {
40
+ RNFishjamClient.onLocalTrackSwitchListener.add(this)
41
+ }
42
+
43
+ fun setVideoLayout(videoLayout: String) {
44
+ val scalingType =
45
+ when (videoLayout) {
46
+ "FILL" -> RendererCommon.ScalingType.SCALE_ASPECT_FILL
47
+ "FIT" -> RendererCommon.ScalingType.SCALE_ASPECT_FIT
48
+ else -> RendererCommon.ScalingType.SCALE_ASPECT_FILL
49
+ }
50
+ videoView.setScalingType(scalingType)
51
+ videoView.setEnableHardwareScaler(true)
52
+ }
53
+
54
+ open fun dispose() {
55
+ videoView.release()
56
+ }
57
+
58
+ protected abstract fun getVideoTrack(): VideoTrack?
59
+
60
+ override suspend fun onLocalTrackWillSwitch() {
61
+ if (getVideoTrack() is LocalVideoTrack) {
62
+ fadeAnimation.start()
63
+ }
64
+ }
65
+
66
+ override suspend fun onLocalTrackSwitched() {
67
+ if (getVideoTrack() is LocalVideoTrack) {
68
+ videoView.setMirror((getVideoTrack() as? LocalVideoTrack)?.isFrontCamera() ?: false)
69
+ delay(500)
70
+ fadeAnimation.reverse()
71
+ }
72
+ }
73
+
74
+ fun setupTrack() {
75
+ videoView.setMirror((getVideoTrack() as? LocalVideoTrack)?.isFrontCamera() ?: false)
76
+ }
77
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fishjam-cloud/react-native-client",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A React Native client for Fishjam Cloud",
5
5
  "author": "Fishjam Cloud Team",
6
6
  "license": "Apache-2.0",
@@ -78,12 +78,12 @@
78
78
  "testEnvironment": "jsdom"
79
79
  },
80
80
  "files": [
81
- "build/",
81
+ "build/**",
82
82
  "android/build.gradle",
83
- "android/src/",
83
+ "android/src/**",
84
84
  "ios/*.swift",
85
85
  "ios/RNFishjamClient.podspec",
86
- "plugin/build/",
86
+ "plugin/build/**",
87
87
  "app.plugin.js",
88
88
  "expo-module.config.json",
89
89
  "README.md",
@@ -0,0 +1,9 @@
1
+ export type FishjamPluginOptions = {
2
+ android: {
3
+ enableForegroundService: boolean;
4
+ };
5
+ ios: {
6
+ iphoneDeploymentTarget?: string;
7
+ enableScreensharing: boolean;
8
+ };
9
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ import { FishjamPluginOptions } from './types';
3
+ declare const withFishjam: ConfigPlugin<FishjamPluginOptions>;
4
+ export default withFishjam;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const withFishjamAndroid_1 = require("./withFishjamAndroid");
7
+ const withFishjamIos_1 = __importDefault(require("./withFishjamIos"));
8
+ const withFishjam = (config, options) => {
9
+ (0, withFishjamAndroid_1.withFishjamAndroid)(config, options);
10
+ (0, withFishjamIos_1.default)(config, options);
11
+ return config;
12
+ };
13
+ exports.default = withFishjam;
@@ -0,0 +1,3 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ import { FishjamPluginOptions } from './types';
3
+ export declare const withFishjamAndroid: ConfigPlugin<FishjamPluginOptions>;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withFishjamAndroid = void 0;
4
+ const config_plugins_1 = require("@expo/config-plugins");
5
+ const Manifest_1 = require("@expo/config-plugins/build/android/Manifest");
6
+ const withFishjamForegroundService = (config) => {
7
+ return (0, config_plugins_1.withAndroidManifest)(config, async (config) => {
8
+ const mainApplication = (0, Manifest_1.getMainApplicationOrThrow)(config.modResults);
9
+ mainApplication.service = mainApplication.service || [];
10
+ const newService = {
11
+ $: {
12
+ 'android:name': 'io.fishjam.reactnative.FishjamForegroundService',
13
+ 'android:foregroundServiceType': 'camera|microphone|mediaProjection',
14
+ },
15
+ };
16
+ const existingServiceIndex = mainApplication.service.findIndex((service) => service.$['android:name'] === newService.$['android:name']);
17
+ if (existingServiceIndex !== -1) {
18
+ mainApplication.service[existingServiceIndex] = newService;
19
+ }
20
+ else {
21
+ mainApplication.service.push(newService);
22
+ }
23
+ return config;
24
+ });
25
+ };
26
+ const withFishjamAndroid = (config, { android: { enableForegroundService } }) => {
27
+ if (enableForegroundService) {
28
+ config = withFishjamForegroundService(config);
29
+ }
30
+ return config;
31
+ };
32
+ exports.withFishjamAndroid = withFishjamAndroid;