@capgo/capacitor-stream-call 0.0.2 → 0.0.3

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.
@@ -6,7 +6,6 @@ import android.app.Application
6
6
  import android.app.KeyguardManager
7
7
  import android.content.Context
8
8
  import android.graphics.Color
9
- import android.os.Build
10
9
  import android.os.Bundle
11
10
  import android.os.Handler
12
11
  import android.os.Looper
@@ -25,7 +24,6 @@ import io.getstream.android.push.firebase.FirebasePushDeviceGenerator
25
24
  import io.getstream.android.push.permissions.ActivityLifecycleCallbacks
26
25
  import io.getstream.video.android.core.Call
27
26
  import io.getstream.video.android.core.GEO
28
- import io.getstream.video.android.core.RingingState
29
27
  import io.getstream.video.android.core.StreamVideo
30
28
  import io.getstream.video.android.core.StreamVideoBuilder
31
29
  import io.getstream.video.android.core.model.RejectReason
@@ -36,7 +34,9 @@ import io.getstream.video.android.core.sounds.toSounds
36
34
  import io.getstream.video.android.model.StreamCallId
37
35
  import io.getstream.video.android.model.User
38
36
  import io.getstream.video.android.model.streamCallId
37
+ import kotlinx.coroutines.DelicateCoroutinesApi
39
38
  import kotlinx.coroutines.launch
39
+ import org.openapitools.client.models.CallAcceptedEvent
40
40
  import org.openapitools.client.models.CallEndedEvent
41
41
  import org.openapitools.client.models.CallMissedEvent
42
42
  import org.openapitools.client.models.CallRejectedEvent
@@ -86,7 +86,7 @@ public class StreamCallPlugin : Plugin() {
86
86
  ringtonePlayer = RingtonePlayer(
87
87
  this.activity.application,
88
88
  cancelIncomingCallService = {
89
- var streamVideoClient = this.streamVideoClient
89
+ val streamVideoClient = this.streamVideoClient
90
90
  if (streamVideoClient == null) {
91
91
  android.util.Log.d("StreamCallPlugin", "StreamVideo SDK client is null, no incoming call notification can be constructed")
92
92
  return@RingtonePlayer
@@ -116,7 +116,7 @@ public class StreamCallPlugin : Plugin() {
116
116
  val defaultConfig = defaultMethod.invoke(defaultInstance)
117
117
 
118
118
  val app = this.activity.application
119
- val cId = streamVideoClient?.state?.ringingCall?.value?.cid?.let { StreamCallId.fromCallCid(it) }
119
+ val cId = streamVideoClient.state.ringingCall.value?.cid?.let { StreamCallId.fromCallCid(it) }
120
120
  if (app == null || cId == null || defaultConfig == null) {
121
121
  android.util.Log.e("StreamCallPlugin", "Some required parameters are null - app: ${app == null}, cId: ${cId == null}, defaultConfig: ${defaultConfig == null}")
122
122
  }
@@ -136,6 +136,7 @@ public class StreamCallPlugin : Plugin() {
136
136
  activity?.intent?.let { handleOnNewIntent(it) }
137
137
  }
138
138
 
139
+ @OptIn(DelicateCoroutinesApi::class)
139
140
  override fun handleOnNewIntent(intent: android.content.Intent) {
140
141
  super.handleOnNewIntent(intent)
141
142
 
@@ -197,21 +198,26 @@ public class StreamCallPlugin : Plugin() {
197
198
  android.util.Log.d("StreamCallPlugin", "New Intent - Extras: $extras")
198
199
  }
199
200
 
201
+ @OptIn(DelicateCoroutinesApi::class)
200
202
  private fun declineCall(call: Call) {
201
203
  kotlinx.coroutines.GlobalScope.launch {
202
- call.reject(RejectReason.Decline)
203
-
204
- // Stop ringtone
205
- ringtonePlayer?.stopRinging()
206
-
207
- // Notify that call has ended
208
- val data = JSObject().apply {
209
- put("callId", call.id)
210
- put("state", "rejected")
204
+ try {
205
+ call.leave()
206
+
207
+ // Stop ringtone
208
+ ringtonePlayer?.stopRinging()
209
+
210
+ // Notify that call has ended
211
+ val data = JSObject().apply {
212
+ put("callId", call.id)
213
+ put("state", "rejected")
214
+ }
215
+ notifyListeners("callEvent", data)
216
+
217
+ hideIncomingCall()
218
+ } catch (e: Exception) {
219
+ android.util.Log.e("StreamCallPlugin", "Error declining call: ${e.message}")
211
220
  }
212
- notifyListeners("callEvent", data)
213
-
214
- hideIncomingCall()
215
221
  }
216
222
  }
217
223
 
@@ -366,6 +372,7 @@ public class StreamCallPlugin : Plugin() {
366
372
  }
367
373
  }
368
374
 
375
+ @OptIn(DelicateCoroutinesApi::class)
369
376
  public fun initializeStreamVideo(passedContext: Context? = null, passedApplication: Application? = null) {
370
377
  android.util.Log.v("StreamCallPlugin", "Attempting to initialize streamVideo")
371
378
  if (state == State.INITIALIZING) {
@@ -505,18 +512,14 @@ public class StreamCallPlugin : Plugin() {
505
512
  // Get the ActivityManager
506
513
  val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as android.app.ActivityManager
507
514
  // Remove the task
508
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
509
- val tasks = activityManager.appTasks
510
- tasks.forEach { task ->
511
- task.finishAndRemoveTask()
512
- }
515
+ val tasks = activityManager.appTasks
516
+ tasks.forEach { task ->
517
+ task.finishAndRemoveTask()
513
518
  }
514
519
  // Finish the activity
515
520
  act.finish()
516
521
  // Remove from recents
517
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
518
- act.finishAndRemoveTask()
519
- }
522
+ act.finishAndRemoveTask()
520
523
  // Give a small delay for cleanup
521
524
  Handler(Looper.getMainLooper()).postDelayed({
522
525
  // Kill the process
@@ -542,6 +545,7 @@ public class StreamCallPlugin : Plugin() {
542
545
  }
543
546
  }
544
547
 
548
+ @OptIn(DelicateCoroutinesApi::class)
545
549
  private fun registerEventHandlers() {
546
550
  // Subscribe to call events
547
551
  streamVideoClient?.let { client ->
@@ -559,6 +563,10 @@ public class StreamCallPlugin : Plugin() {
559
563
  )
560
564
  }
561
565
  overlayView?.isVisible = false
566
+ // Stop ringtone if it's still playing
567
+ ringtonePlayer?.stopRinging()
568
+ // Hide incoming call view if visible
569
+ incomingCallView?.isVisible = false
562
570
  }
563
571
  val data = JSObject().apply {
564
572
  put("callId", event.call.cid)
@@ -577,6 +585,10 @@ public class StreamCallPlugin : Plugin() {
577
585
  )
578
586
  }
579
587
  overlayView?.isVisible = false
588
+ // Stop ringtone if it's still playing
589
+ ringtonePlayer?.stopRinging()
590
+ // Hide incoming call view if visible
591
+ incomingCallView?.isVisible = false
580
592
  }
581
593
  val data = JSObject().apply {
582
594
  put("callId", event.call.cid)
@@ -707,9 +719,9 @@ public class StreamCallPlugin : Plugin() {
707
719
  })
708
720
  }
709
721
 
722
+ @OptIn(DelicateCoroutinesApi::class)
710
723
  private fun acceptCall(call: Call) {
711
724
  kotlinx.coroutines.GlobalScope.launch {
712
- android.util.Log.i("StreamCallPlugin", "Attempting to accept call ${call.id}")
713
725
  try {
714
726
  // Stop ringtone
715
727
  ringtonePlayer?.stopRinging()
@@ -720,8 +732,8 @@ public class StreamCallPlugin : Plugin() {
720
732
  incomingCallView?.isVisible = false
721
733
  }
722
734
 
723
- // Accept the call
724
- call.accept()
735
+ // Join the call without affecting others
736
+ call.join()
725
737
 
726
738
  // Notify that call has started
727
739
  val data = JSObject().apply {
@@ -755,6 +767,7 @@ public class StreamCallPlugin : Plugin() {
755
767
  }
756
768
  }
757
769
 
770
+ @OptIn(DelicateCoroutinesApi::class)
758
771
  @PluginMethod
759
772
  fun setMicrophoneEnabled(call: PluginCall) {
760
773
  val enabled = call.getBoolean("enabled") ?: run {
@@ -785,6 +798,37 @@ public class StreamCallPlugin : Plugin() {
785
798
  }
786
799
  }
787
800
 
801
+ @OptIn(DelicateCoroutinesApi::class)
802
+ @PluginMethod
803
+ fun isCameraEnabled(call: PluginCall) {
804
+ try {
805
+ val activeCall = streamVideoClient?.state?.activeCall
806
+ if (activeCall == null) {
807
+ call.reject("No active call")
808
+ return
809
+ }
810
+
811
+ kotlinx.coroutines.GlobalScope.launch {
812
+ try {
813
+ val enabled = activeCall.value?.camera?.isEnabled?.value
814
+ if (enabled == null) {
815
+ call.reject("Cannot figure out if camera is enabled or not")
816
+ return@launch
817
+ }
818
+ call.resolve(JSObject().apply {
819
+ put("enabled", enabled)
820
+ })
821
+ } catch (e: Exception) {
822
+ android.util.Log.e("StreamCallPlugin", "Error checking the camera status: ${e.message}")
823
+ call.reject("Failed to check if camera is enabled: ${e.message}")
824
+ }
825
+ }
826
+ } catch (e: Exception) {
827
+ call.reject("StreamVideo not initialized")
828
+ }
829
+ }
830
+
831
+ @OptIn(DelicateCoroutinesApi::class)
788
832
  @PluginMethod
789
833
  fun setCameraEnabled(call: PluginCall) {
790
834
  val enabled = call.getBoolean("enabled") ?: run {
@@ -815,7 +859,7 @@ public class StreamCallPlugin : Plugin() {
815
859
  }
816
860
  }
817
861
 
818
- suspend fun endCallRaw(call: Call) {
862
+ private suspend fun endCallRaw(call: Call) {
819
863
  val callId = call.id
820
864
  android.util.Log.d("StreamCallPlugin", "Attempting to end call $callId")
821
865
  call.leave()
@@ -844,7 +888,7 @@ public class StreamCallPlugin : Plugin() {
844
888
  }
845
889
  }
846
890
 
847
- var savedCapacitorActivity = savedActivity
891
+ val savedCapacitorActivity = savedActivity
848
892
  if (savedCapacitorActivity != null) {
849
893
 
850
894
  if (savedActivityPaused) {
@@ -880,9 +924,10 @@ public class StreamCallPlugin : Plugin() {
880
924
  notifyListeners("callEvent", data)
881
925
  }
882
926
 
927
+ @OptIn(DelicateCoroutinesApi::class)
883
928
  private fun transEndCallRaw(call: Call) {
884
929
  val callId = call.id
885
- var savedCapacitorActivity = savedActivity
930
+ val savedCapacitorActivity = savedActivity
886
931
  if (savedCapacitorActivity == null) {
887
932
  android.util.Log.d("StreamCallPlugin", "Cannot perform transEndCallRaw for call $callId. savedCapacitorActivity is null")
888
933
  return
@@ -911,6 +956,7 @@ public class StreamCallPlugin : Plugin() {
911
956
  }
912
957
  }
913
958
 
959
+ @OptIn(DelicateCoroutinesApi::class)
914
960
  @PluginMethod
915
961
  fun endCall(call: PluginCall) {
916
962
  try {
@@ -937,11 +983,12 @@ public class StreamCallPlugin : Plugin() {
937
983
  }
938
984
  }
939
985
 
986
+ @OptIn(DelicateCoroutinesApi::class)
940
987
  @PluginMethod
941
988
  fun call(call: PluginCall) {
942
- val userId = call.getString("userId")
943
- if (userId == null) {
944
- call.reject("Missing required parameter: userId")
989
+ val userIds = call.getArray("userIds")?.toList<String>()
990
+ if (userIds.isNullOrEmpty()) {
991
+ call.reject("Missing required parameter: userIds (array of user IDs)")
945
992
  return
946
993
  }
947
994
 
@@ -964,7 +1011,7 @@ public class StreamCallPlugin : Plugin() {
964
1011
  android.util.Log.d("StreamCallPlugin", "Creating call:")
965
1012
  android.util.Log.d("StreamCallPlugin", "- Call ID: $callId")
966
1013
  android.util.Log.d("StreamCallPlugin", "- Call Type: $callType")
967
- android.util.Log.d("StreamCallPlugin", "- User ID: $userId")
1014
+ android.util.Log.d("StreamCallPlugin", "- Users: $userIds")
968
1015
  android.util.Log.d("StreamCallPlugin", "- Should Ring: $shouldRing")
969
1016
 
970
1017
  // Create and join call in a coroutine
@@ -973,18 +1020,66 @@ public class StreamCallPlugin : Plugin() {
973
1020
  // Create the call object
974
1021
  val streamCall = streamVideoClient?.call(type = callType, id = callId)
975
1022
 
976
- android.util.Log.d("StreamCallPlugin", "Creating call with member...")
977
- // Create the call with the member
1023
+ // Track participants responses
1024
+ val participantResponses = mutableMapOf<String, String>()
1025
+ val totalParticipants = userIds.size
1026
+
1027
+ // Subscribe to call events for this specific call
1028
+ streamCall?.subscribe { event ->
1029
+ when (event) {
1030
+ is CallRejectedEvent -> {
1031
+ val userId = event.user.id
1032
+ android.util.Log.d("StreamCallPlugin", "Call was rejected by user: $userId")
1033
+ participantResponses[userId] = "rejected"
1034
+
1035
+ val data = JSObject().apply {
1036
+ put("callId", callId)
1037
+ put("state", "rejected")
1038
+ put("userId", userId)
1039
+ }
1040
+ notifyListeners("callEvent", data)
1041
+
1042
+ // Check if all participants have rejected or missed
1043
+ checkAllParticipantsResponded(participantResponses, totalParticipants, streamCall)
1044
+ }
1045
+ is CallMissedEvent -> {
1046
+ val userId = event.user.id
1047
+ android.util.Log.d("StreamCallPlugin", "Call was missed by user: $userId")
1048
+ participantResponses[userId] = "missed"
1049
+
1050
+ val data = JSObject().apply {
1051
+ put("callId", callId)
1052
+ put("state", "missed")
1053
+ put("userId", userId)
1054
+ }
1055
+ notifyListeners("callEvent", data)
1056
+
1057
+ // Check if all participants have rejected or missed
1058
+ checkAllParticipantsResponded(participantResponses, totalParticipants, streamCall)
1059
+ }
1060
+ is CallAcceptedEvent -> {
1061
+ val userId = event.user.id
1062
+ android.util.Log.d("StreamCallPlugin", "Call was accepted by user: $userId")
1063
+ participantResponses[userId] = "accepted"
1064
+
1065
+ val data = JSObject().apply {
1066
+ put("callId", callId)
1067
+ put("state", "accepted")
1068
+ put("userId", userId)
1069
+ }
1070
+ notifyListeners("callEvent", data)
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ android.util.Log.d("StreamCallPlugin", "Creating call with members...")
1076
+ // Create the call with all members
978
1077
  streamCall?.create(
979
- memberIds = listOf(userId, selfUserId),
1078
+ memberIds = userIds + selfUserId,
980
1079
  custom = emptyMap(),
981
1080
  ring = shouldRing
982
1081
  )
983
1082
 
984
- // streamCall?.let {
985
- // this@StreamCallPlugin.streamVideoClient?.state?.setActiveCall(it)
986
- // }
987
-
988
1083
  android.util.Log.d("StreamCallPlugin", "Setting overlay visible for outgoing call $callId")
989
1084
  // Show overlay view
990
1085
  activity?.runOnUiThread {
@@ -1011,4 +1106,42 @@ public class StreamCallPlugin : Plugin() {
1011
1106
  call.reject("Failed to make call: ${e.message}")
1012
1107
  }
1013
1108
  }
1109
+
1110
+ @OptIn(DelicateCoroutinesApi::class)
1111
+ private fun checkAllParticipantsResponded(
1112
+ participantResponses: Map<String, String>,
1113
+ totalParticipants: Int,
1114
+ streamCall: Call
1115
+ ) {
1116
+ kotlinx.coroutines.GlobalScope.launch {
1117
+ try {
1118
+ val allResponded = participantResponses.size == totalParticipants
1119
+ val allRejectedOrMissed = participantResponses.values.all { it == "rejected" || it == "missed" }
1120
+
1121
+ if (allResponded && allRejectedOrMissed) {
1122
+ android.util.Log.d("StreamCallPlugin", "All participants have rejected or missed the call")
1123
+ streamCall.leave()
1124
+ activity?.runOnUiThread {
1125
+ overlayView?.setContent {
1126
+ CallOverlayView(
1127
+ context = context,
1128
+ streamVideo = streamVideoClient,
1129
+ call = null
1130
+ )
1131
+ }
1132
+ overlayView?.isVisible = false
1133
+ }
1134
+
1135
+ val data = JSObject().apply {
1136
+ put("callId", streamCall.id)
1137
+ put("state", "ended")
1138
+ put("reason", "all_rejected_or_missed")
1139
+ }
1140
+ notifyListeners("callEvent", data)
1141
+ }
1142
+ } catch (e: Exception) {
1143
+ android.util.Log.e("StreamCallPlugin", "Error checking participant responses: ${e.message}")
1144
+ }
1145
+ }
1146
+ }
1014
1147
  }
package/dist/docs.json CHANGED
@@ -281,6 +281,18 @@
281
281
  "SuccessResponse"
282
282
  ],
283
283
  "slug": "rejectcall"
284
+ },
285
+ {
286
+ "name": "isCameraEnabled",
287
+ "signature": "() => Promise<CameraEnabledResponse>",
288
+ "parameters": [],
289
+ "returns": "Promise<CameraEnabledResponse>",
290
+ "tags": [],
291
+ "docs": "",
292
+ "complexTypes": [
293
+ "CameraEnabledResponse"
294
+ ],
295
+ "slug": "iscameraenabled"
284
296
  }
285
297
  ],
286
298
  "properties": []
@@ -351,18 +363,6 @@
351
363
  {
352
364
  "text": "{string} [magicDivId] - DOM element ID where video will be rendered",
353
365
  "name": "property"
354
- },
355
- {
356
- "text": "{Object} [refreshToken] - Token refresh configuration",
357
- "name": "property"
358
- },
359
- {
360
- "text": "{string} refreshToken.url - Endpoint URL for token refresh",
361
- "name": "property"
362
- },
363
- {
364
- "text": "{Record<string, string>} [refreshToken.headers] - Custom headers for refresh request",
365
- "name": "property"
366
366
  }
367
367
  ],
368
368
  "methods": [],
@@ -408,15 +408,6 @@
408
408
  "docs": "ID of the HTML element where the video will be rendered",
409
409
  "complexTypes": [],
410
410
  "type": "string | undefined"
411
- },
412
- {
413
- "name": "refreshToken",
414
- "tags": [],
415
- "docs": "Configuration for token refresh",
416
- "complexTypes": [
417
- "Record"
418
- ],
419
- "type": "{ url: string; headers?: Record<string, string> | undefined; } | undefined"
420
411
  }
421
412
  ]
422
413
  },
@@ -449,11 +440,11 @@
449
440
  "methods": [],
450
441
  "properties": [
451
442
  {
452
- "name": "userId",
443
+ "name": "userIds",
453
444
  "tags": [],
454
445
  "docs": "User ID of the person to call",
455
446
  "complexTypes": [],
456
- "type": "string"
447
+ "type": "string[]"
457
448
  },
458
449
  {
459
450
  "name": "type",
@@ -508,26 +499,34 @@
508
499
  "docs": "Current state of the call",
509
500
  "complexTypes": [],
510
501
  "type": "string"
502
+ },
503
+ {
504
+ "name": "userId",
505
+ "tags": [],
506
+ "docs": "User ID of the participant in the call who triggered the event",
507
+ "complexTypes": [],
508
+ "type": "string | undefined"
511
509
  }
512
510
  ]
513
- }
514
- ],
515
- "enums": [],
516
- "typeAliases": [
511
+ },
517
512
  {
518
- "name": "Record",
519
- "slug": "record",
520
- "docs": "Construct a type with a set of properties K of type T",
521
- "types": [
522
- {
523
- "text": "{\r\n [P in K]: T;\r\n}",
524
- "complexTypes": [
525
- "K",
526
- "T"
527
- ]
513
+ "name": "CameraEnabledResponse",
514
+ "slug": "cameraenabledresponse",
515
+ "docs": "",
516
+ "tags": [],
517
+ "methods": [],
518
+ "properties": [
519
+ {
520
+ "name": "enabled",
521
+ "tags": [],
522
+ "docs": "",
523
+ "complexTypes": [],
524
+ "type": "boolean"
528
525
  }
529
526
  ]
530
527
  }
531
528
  ],
529
+ "enums": [],
530
+ "typeAliases": [],
532
531
  "pluginConfigs": []
533
532
  }
@@ -7,9 +7,6 @@
7
7
  * @property {string} [imageURL] - Avatar URL for the current user
8
8
  * @property {string} apiKey - Stream Video API key for your application
9
9
  * @property {string} [magicDivId] - DOM element ID where video will be rendered
10
- * @property {Object} [refreshToken] - Token refresh configuration
11
- * @property {string} refreshToken.url - Endpoint URL for token refresh
12
- * @property {Record<string, string>} [refreshToken.headers] - Custom headers for refresh request
13
10
  */
14
11
  export interface LoginOptions {
15
12
  /** Stream Video API token */
@@ -24,13 +21,6 @@ export interface LoginOptions {
24
21
  apiKey: string;
25
22
  /** ID of the HTML element where the video will be rendered */
26
23
  magicDivId?: string;
27
- /** Configuration for token refresh */
28
- refreshToken?: {
29
- /** URL to call for refreshing the token */
30
- url: string;
31
- /** Optional headers to include in the refresh request */
32
- headers?: Record<string, string>;
33
- };
34
24
  }
35
25
  /**
36
26
  * @interface CallOptions
@@ -41,7 +31,7 @@ export interface LoginOptions {
41
31
  */
42
32
  export interface CallOptions {
43
33
  /** User ID of the person to call */
44
- userId: string;
34
+ userIds: string[];
45
35
  /** Type of call, defaults to 'default' */
46
36
  type?: string;
47
37
  /** Whether to ring the other user, defaults to true */
@@ -67,6 +57,11 @@ export interface CallEvent {
67
57
  callId: string;
68
58
  /** Current state of the call */
69
59
  state: string;
60
+ /** User ID of the participant in the call who triggered the event */
61
+ userId?: string;
62
+ }
63
+ export interface CameraEnabledResponse {
64
+ enabled: boolean;
70
65
  }
71
66
  /**
72
67
  * @interface StreamCallPlugin
@@ -166,4 +161,5 @@ export interface StreamCallPlugin {
166
161
  * await StreamCall.rejectCall();
167
162
  */
168
163
  rejectCall(): Promise<SuccessResponse>;
164
+ isCameraEnabled(): Promise<CameraEnabledResponse>;
169
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * @interface LoginOptions\n * @description Configuration options for logging into the Stream Video service\n * @property {string} token - Stream Video API token for authentication\n * @property {string} userId - Unique identifier for the current user\n * @property {string} name - Display name for the current user\n * @property {string} [imageURL] - Avatar URL for the current user\n * @property {string} apiKey - Stream Video API key for your application\n * @property {string} [magicDivId] - DOM element ID where video will be rendered\n * @property {Object} [refreshToken] - Token refresh configuration\n * @property {string} refreshToken.url - Endpoint URL for token refresh\n * @property {Record<string, string>} [refreshToken.headers] - Custom headers for refresh request\n */\nexport interface LoginOptions {\n /** Stream Video API token */\n token: string;\n /** User ID for the current user */\n userId: string;\n /** Display name for the current user */\n name: string;\n /** Optional avatar URL for the current user */\n imageURL?: string;\n /** Stream Video API key */\n apiKey: string;\n /** ID of the HTML element where the video will be rendered */\n magicDivId?: string;\n /** Configuration for token refresh */\n refreshToken?: {\n /** URL to call for refreshing the token */\n url: string;\n /** Optional headers to include in the refresh request */\n headers?: Record<string, string>;\n };\n}\n\n/**\n * @interface CallOptions\n * @description Options for initiating a video call\n * @property {string} userId - ID of the user to call\n * @property {string} [type=default] - Type of call\n * @property {boolean} [ring=true] - Whether to send ring notification\n */\nexport interface CallOptions {\n /** User ID of the person to call */\n userId: string;\n /** Type of call, defaults to 'default' */\n type?: string;\n /** Whether to ring the other user, defaults to true */\n ring?: boolean;\n}\n\n/**\n * @interface SuccessResponse\n * @description Standard response indicating operation success/failure\n * @property {boolean} success - Whether the operation succeeded\n */\nexport interface SuccessResponse {\n /** Whether the operation was successful */\n success: boolean;\n}\n\n/**\n * @interface CallEvent\n * @description Event emitted when call state changes\n * @property {string} callId - Unique identifier of the call\n * @property {string} state - Current state of the call (joined, left, ringing, etc)\n */\nexport interface CallEvent {\n /** ID of the call */\n callId: string;\n /** Current state of the call */\n state: string;\n}\n\n/**\n * @interface StreamCallPlugin\n * @description Capacitor plugin for Stream Video calling functionality\n */\nexport interface StreamCallPlugin {\n /**\n * Login to Stream Video service\n * @param {LoginOptions} options - Login configuration\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.login({\n * token: 'your-token',\n * userId: 'user-123',\n * name: 'John Doe',\n * apiKey: 'your-api-key'\n * });\n */\n login(options: LoginOptions): Promise<SuccessResponse>;\n\n /**\n * Logout from Stream Video service\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.logout();\n */\n logout(): Promise<SuccessResponse>;\n\n /**\n * Initiate a call to another user\n * @param {CallOptions} options - Call configuration\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.call({\n * userId: 'user-456',\n * type: 'video',\n * ring: true\n * });\n */\n call(options: CallOptions): Promise<SuccessResponse>;\n\n /**\n * End the current call\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.endCall();\n */\n endCall(): Promise<SuccessResponse>;\n\n /**\n * Enable or disable microphone\n * @param {{ enabled: boolean }} options - Microphone state\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.setMicrophoneEnabled({ enabled: false });\n */\n setMicrophoneEnabled(options: { enabled: boolean }): Promise<SuccessResponse>;\n\n /**\n * Enable or disable camera\n * @param {{ enabled: boolean }} options - Camera state\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.setCameraEnabled({ enabled: false });\n */\n setCameraEnabled(options: { enabled: boolean }): Promise<SuccessResponse>;\n\n /**\n * Add listener for call events\n * @param {'callEvent'} eventName - Name of the event to listen for\n * @param {(event: CallEvent) => void} listenerFunc - Callback function\n * @returns {Promise<{ remove: () => Promise<void> }>} Function to remove listener\n * @example\n * const listener = await StreamCall.addListener('callEvent', (event) => {\n * console.log(`Call ${event.callId} is now ${event.state}`);\n * });\n */\n addListener(\n eventName: 'callEvent',\n listenerFunc: (event: CallEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Remove all event listeners\n * @returns {Promise<void>}\n * @example\n * await StreamCall.removeAllListeners();\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Accept an incoming call\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.acceptCall();\n */\n acceptCall(): Promise<SuccessResponse>;\n\n /**\n * Reject an incoming call\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.rejectCall();\n */\n rejectCall(): Promise<SuccessResponse>;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * @interface LoginOptions\n * @description Configuration options for logging into the Stream Video service\n * @property {string} token - Stream Video API token for authentication\n * @property {string} userId - Unique identifier for the current user\n * @property {string} name - Display name for the current user\n * @property {string} [imageURL] - Avatar URL for the current user\n * @property {string} apiKey - Stream Video API key for your application\n * @property {string} [magicDivId] - DOM element ID where video will be rendered\n */\nexport interface LoginOptions {\n /** Stream Video API token */\n token: string;\n /** User ID for the current user */\n userId: string;\n /** Display name for the current user */\n name: string;\n /** Optional avatar URL for the current user */\n imageURL?: string;\n /** Stream Video API key */\n apiKey: string;\n /** ID of the HTML element where the video will be rendered */\n magicDivId?: string;\n}\n\n/**\n * @interface CallOptions\n * @description Options for initiating a video call\n * @property {string} userId - ID of the user to call\n * @property {string} [type=default] - Type of call\n * @property {boolean} [ring=true] - Whether to send ring notification\n */\nexport interface CallOptions {\n /** User ID of the person to call */\n userIds: string[];\n /** Type of call, defaults to 'default' */\n type?: string;\n /** Whether to ring the other user, defaults to true */\n ring?: boolean;\n}\n\n/**\n * @interface SuccessResponse\n * @description Standard response indicating operation success/failure\n * @property {boolean} success - Whether the operation succeeded\n */\nexport interface SuccessResponse {\n /** Whether the operation was successful */\n success: boolean;\n}\n\n/**\n * @interface CallEvent\n * @description Event emitted when call state changes\n * @property {string} callId - Unique identifier of the call\n * @property {string} state - Current state of the call (joined, left, ringing, etc)\n */\nexport interface CallEvent {\n /** ID of the call */\n callId: string;\n /** Current state of the call */\n state: string;\n /** User ID of the participant in the call who triggered the event */\n userId?: string\n}\n\nexport interface CameraEnabledResponse {\n enabled: boolean;\n}\n\n/**\n * @interface StreamCallPlugin\n * @description Capacitor plugin for Stream Video calling functionality\n */\nexport interface StreamCallPlugin {\n /**\n * Login to Stream Video service\n * @param {LoginOptions} options - Login configuration\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.login({\n * token: 'your-token',\n * userId: 'user-123',\n * name: 'John Doe',\n * apiKey: 'your-api-key'\n * });\n */\n login(options: LoginOptions): Promise<SuccessResponse>;\n\n /**\n * Logout from Stream Video service\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.logout();\n */\n logout(): Promise<SuccessResponse>;\n\n /**\n * Initiate a call to another user\n * @param {CallOptions} options - Call configuration\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.call({\n * userId: 'user-456',\n * type: 'video',\n * ring: true\n * });\n */\n call(options: CallOptions): Promise<SuccessResponse>;\n\n /**\n * End the current call\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.endCall();\n */\n endCall(): Promise<SuccessResponse>;\n\n /**\n * Enable or disable microphone\n * @param {{ enabled: boolean }} options - Microphone state\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.setMicrophoneEnabled({ enabled: false });\n */\n setMicrophoneEnabled(options: { enabled: boolean }): Promise<SuccessResponse>;\n\n /**\n * Enable or disable camera\n * @param {{ enabled: boolean }} options - Camera state\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.setCameraEnabled({ enabled: false });\n */\n setCameraEnabled(options: { enabled: boolean }): Promise<SuccessResponse>;\n\n /**\n * Add listener for call events\n * @param {'callEvent'} eventName - Name of the event to listen for\n * @param {(event: CallEvent) => void} listenerFunc - Callback function\n * @returns {Promise<{ remove: () => Promise<void> }>} Function to remove listener\n * @example\n * const listener = await StreamCall.addListener('callEvent', (event) => {\n * console.log(`Call ${event.callId} is now ${event.state}`);\n * });\n */\n addListener(\n eventName: 'callEvent',\n listenerFunc: (event: CallEvent) => void,\n ): Promise<{ remove: () => Promise<void> }>;\n\n /**\n * Remove all event listeners\n * @returns {Promise<void>}\n * @example\n * await StreamCall.removeAllListeners();\n */\n removeAllListeners(): Promise<void>;\n\n /**\n * Accept an incoming call\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.acceptCall();\n */\n acceptCall(): Promise<SuccessResponse>;\n\n /**\n * Reject an incoming call\n * @returns {Promise<SuccessResponse>} Success status\n * @example\n * await StreamCall.rejectCall();\n */\n rejectCall(): Promise<SuccessResponse>;\n isCameraEnabled(): Promise<CameraEnabledResponse>;\n}\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
- import type { CallOptions, StreamCallPlugin, SuccessResponse, LoginOptions } from './definitions';
2
+ import type { CallOptions, StreamCallPlugin, SuccessResponse, LoginOptions, CameraEnabledResponse } from './definitions';
3
3
  export declare class StreamCallWeb extends WebPlugin implements StreamCallPlugin {
4
4
  private client?;
5
5
  private currentCall?;
@@ -29,4 +29,5 @@ export declare class StreamCallWeb extends WebPlugin implements StreamCallPlugin
29
29
  }): Promise<SuccessResponse>;
30
30
  acceptCall(): Promise<SuccessResponse>;
31
31
  rejectCall(): Promise<SuccessResponse>;
32
+ isCameraEnabled(): Promise<CameraEnabledResponse>;
32
33
  }
package/dist/esm/web.js CHANGED
@@ -239,8 +239,8 @@ export class StreamCallWeb extends WebPlugin {
239
239
  throw new Error('Client not initialized - Please login first');
240
240
  }
241
241
  const call = this.client.call(options.type || 'default', crypto.randomUUID());
242
- const members = [{ user_id: options.userId }];
243
- if (this.client.streamClient.userID && options.userId !== this.client.streamClient.userID) {
242
+ const members = options.userIds.map((userId) => ({ user_id: userId }));
243
+ if (this.client.streamClient.userID && options.userIds.includes(this.client.streamClient.userID)) {
244
244
  members.push({ user_id: this.client.streamClient.userID });
245
245
  }
246
246
  await call.getOrCreate({ data: { members } });
@@ -319,5 +319,13 @@ export class StreamCallWeb extends WebPlugin {
319
319
  this.cleanupCall();
320
320
  return { success: true };
321
321
  }
322
+ async isCameraEnabled() {
323
+ if (!this.currentCall) {
324
+ console.log('No active call', this.currentCall);
325
+ throw new Error('No active call');
326
+ }
327
+ const enabled = await this.currentCall.camera.enabled;
328
+ return { enabled };
329
+ }
322
330
  }
323
331
  //# sourceMappingURL=web.js.map