@capgo/capacitor-stream-call 0.0.24 → 0.0.25-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -57,7 +57,7 @@ struct CallOverlayView: View {
57
57
  }
58
58
 
59
59
  private func changeTrackVisibility(_ participant: CallParticipant?, isVisible: Bool) {
60
- print("changeTrackVisibility for \(String(describing: participant?.userId)), visible: \(isVisible)")
60
+ StreamCallPlugin.dualprint("changeTrackVisibility for \(String(describing: participant?.userId)), visible: \(isVisible)")
61
61
  guard let participant = participant,
62
62
  let call = viewModel.call else { return }
63
63
  Task {
@@ -29,7 +29,7 @@ public struct CustomVideoCallParticipantView<Factory: ViewFactory>: View {
29
29
  customData: [String: RawJSON],
30
30
  call: Call?
31
31
  ) {
32
- print("size: \(availableFrame.size)")
32
+ StreamCallPlugin.dualprint("size: \(availableFrame.size)")
33
33
  self.viewFactory = viewFactory
34
34
  self.participant = participant
35
35
  self.id = id ?? participant.id
@@ -34,8 +34,8 @@ extension View {
34
34
  value: [ViewFramePreferenceData(label: label,
35
35
  frame: geo.frame(in: .global))])
36
36
  .onAppear {
37
- print("ParticipantsView - Collecting frame for label: \(label)")
38
- print("Frame: \(geo.frame(in: .global))")
37
+ StreamCallPlugin.dualprint("ParticipantsView - Collecting frame for label: \(label)")
38
+ StreamCallPlugin.dualprint("Frame: \(geo.frame(in: .global))")
39
39
  }
40
40
  }
41
41
  )
@@ -5,6 +5,7 @@ import StreamVideoSwiftUI
5
5
  import SwiftUI
6
6
  import Combine
7
7
  import WebKit
8
+ import os.log
8
9
 
9
10
  /**
10
11
  * Please read the Capacitor iOS Plugin Development Guide
@@ -27,6 +28,15 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
27
28
  CAPPluginMethod(name: "getCallStatus", returnType: CAPPluginReturnPromise)
28
29
  ]
29
30
 
31
+ // OSLog for streamcall plugin
32
+ private static let osLog = OSLog(subsystem: "com.example.plugin.streamcall", category: "StreamCallPlugin")
33
+
34
+ // Static function for dual printing to console and os.log
35
+ public static func dualprint(_ message: String) {
36
+ print(message)
37
+ os_log("%{public}@", log: osLog, type: .info, message)
38
+ }
39
+
30
40
  private enum State {
31
41
  case notInitialized
32
42
  case initializing
@@ -97,7 +107,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
97
107
 
98
108
  // Check if we have a logged in user for handling incoming calls
99
109
  if let credentials = SecureUserRepository.shared.loadCurrentUser() {
100
- print("Loading user for StreamCallPlugin: \(credentials.user.name)")
110
+ StreamCallPlugin.dualprint("Loading user for StreamCallPlugin: \(credentials.user.name)")
101
111
  DispatchQueue.global(qos: .userInitiated).async {
102
112
  self.initializeStreamVideo()
103
113
  }
@@ -108,7 +118,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
108
118
  wrappedDelegate: self.webView?.navigationDelegate,
109
119
  onSetupOverlay: { [weak self] in
110
120
  guard let self = self else { return }
111
- print("Attempting to setup call view")
121
+ StreamCallPlugin.dualprint("Attempting to setup call view")
112
122
 
113
123
  self.setupViews()
114
124
  }
@@ -128,7 +138,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
128
138
  return
129
139
  }
130
140
 
131
- print("loginMagicToken received token")
141
+ StreamCallPlugin.dualprint("loginMagicToken received token")
132
142
  currentToken = token
133
143
  tokenWaitSemaphore?.signal()
134
144
  call.resolve()
@@ -143,17 +153,17 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
143
153
  guard let self = self else { return }
144
154
  Task {
145
155
  do {
146
- print("Setting up token subscription")
156
+ StreamCallPlugin.dualprint("Setting up token subscription")
147
157
  try self.requireInitialized()
148
158
  if let lastVoIPToken = self.lastVoIPToken, !lastVoIPToken.isEmpty {
149
- print("Deleting device: \(lastVoIPToken)")
159
+ StreamCallPlugin.dualprint("Deleting device: \(lastVoIPToken)")
150
160
  try await self.streamVideo?.deleteDevice(id: lastVoIPToken)
151
161
  }
152
162
  if !updatedDeviceToken.isEmpty {
153
- print("Setting voip device: \(updatedDeviceToken)")
163
+ StreamCallPlugin.dualprint("Setting voip device: \(updatedDeviceToken)")
154
164
  try await self.streamVideo?.setVoipDevice(id: updatedDeviceToken)
155
165
  // Save the token to our secure storage
156
- print("Saving voip token: \(updatedDeviceToken)")
166
+ StreamCallPlugin.dualprint("Saving voip token: \(updatedDeviceToken)")
157
167
  SecureUserRepository.shared.save(voipPushToken: updatedDeviceToken)
158
168
  }
159
169
  self.lastVoIPToken = updatedDeviceToken
@@ -175,7 +185,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
175
185
 
176
186
  // Verify callViewModel exists
177
187
  guard let callViewModel = self.callViewModel, let streamVideo = self.streamVideo else {
178
- print("Warning: setupActiveCallSubscription called but callViewModel or streamVideo is nil")
188
+ StreamCallPlugin.dualprint("Warning: setupActiveCallSubscription called but callViewModel or streamVideo is nil")
179
189
  // Schedule a retry after a short delay if callViewModel is nil
180
190
  DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
181
191
  self?.setupActiveCallSubscription()
@@ -183,7 +193,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
183
193
  return
184
194
  }
185
195
 
186
- print("Setting up active call subscription")
196
+ StreamCallPlugin.dualprint("Setting up active call subscription")
187
197
 
188
198
  // Create a strong reference to callViewModel to ensure it's not deallocated
189
199
  // while the subscription is active
@@ -195,7 +205,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
195
205
  .sink { [weak self, weak viewModel] activeCall in
196
206
  guard let self = self, let viewModel = viewModel else { return }
197
207
 
198
- print("Active call update from streamVideo: \(String(describing: activeCall?.cId))")
208
+ StreamCallPlugin.dualprint("Active call update from streamVideo: \(String(describing: activeCall?.cId))")
199
209
 
200
210
  if let activeCall = activeCall {
201
211
  // Sync callViewModel with activeCall from streamVideo state
@@ -212,24 +222,24 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
212
222
  .receive(on: DispatchQueue.main)
213
223
  .sink { [weak self, weak viewModel] newState in
214
224
  guard let self = self, let viewModel = viewModel else {
215
- print("Warning: Call state update received but self or viewModel is nil")
225
+ StreamCallPlugin.dualprint("Warning: Call state update received but self or viewModel is nil")
216
226
  return
217
227
  }
218
228
 
219
229
  do {
220
230
  try self.requireInitialized()
221
- print("Call State Update: \(newState)")
231
+ StreamCallPlugin.dualprint("Call State Update: \(newState)")
222
232
 
223
233
  if newState == .inCall {
224
- print("- In call state detected")
225
- print("- All participants: \(String(describing: viewModel.participants))")
234
+ StreamCallPlugin.dualprint("- In call state detected")
235
+ StreamCallPlugin.dualprint("- All participants: \(String(describing: viewModel.participants))")
226
236
 
227
237
  // Create/update overlay and make visible when there's an active call
228
238
  self.createCallOverlayView()
229
239
 
230
240
  // Notify that a call has started - but only if we haven't notified for this call yet
231
241
  if let callId = viewModel.call?.cId, !self.hasNotifiedCallJoined || callId != self.currentCallId {
232
- print("Notifying call joined: \(callId)")
242
+ StreamCallPlugin.dualprint("Notifying call joined: \(callId)")
233
243
  self.updateCallStatusAndNotify(callId: callId, state: "joined")
234
244
  self.hasNotifiedCallJoined = true
235
245
  }
@@ -238,7 +248,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
238
248
  } else if newState == .idle && self.streamVideo?.state.activeCall == nil {
239
249
  // Get the call ID that was active before the state changed
240
250
  let endingCallId = viewModel.call?.cId
241
- print("Call ending: \(String(describing: endingCallId))")
251
+ StreamCallPlugin.dualprint("Call ending: \(String(describing: endingCallId))")
242
252
 
243
253
  // Notify that call has ended - use the properly tracked call ID
244
254
  self.updateCallStatusAndNotify(callId: endingCallId ?? "", state: "left")
@@ -254,7 +264,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
254
264
  // Remove call from callStates
255
265
  self.callStates.removeValue(forKey: callCid)
256
266
 
257
- print("Cleaned up resources for ended call: \(callCid)")
267
+ StreamCallPlugin.dualprint("Cleaned up resources for ended call: \(callCid)")
258
268
  }
259
269
 
260
270
  // Remove the call overlay view when not in a call
@@ -271,7 +281,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
271
281
  statePublisher.cancel()
272
282
  }
273
283
 
274
- print("Active call subscription setup completed")
284
+ StreamCallPlugin.dualprint("Active call subscription setup completed")
275
285
 
276
286
  // Schedule a periodic check to ensure subscription is active
277
287
  self.scheduleSubscriptionCheck()
@@ -286,7 +296,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
286
296
 
287
297
  // Check if we're in a state where we need the subscription but it's not active
288
298
  if self.state == .initialized && self.activeCallSubscription == nil && self.callViewModel != nil {
289
- print("Subscription check: Restoring lost activeCallSubscription")
299
+ StreamCallPlugin.dualprint("Subscription check: Restoring lost activeCallSubscription")
290
300
  self.setupActiveCallSubscription()
291
301
  } else {
292
302
  // Schedule the next check
@@ -323,8 +333,8 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
323
333
  let hasAccepted = callState.participantResponses.values.contains { $0 == "accepted" }
324
334
 
325
335
  if !hasAccepted {
326
- print("Call \(callCid) has timed out after \(elapsedSeconds) seconds")
327
- print("No one accepted call \(callCid), marking all non-responders as missed")
336
+ StreamCallPlugin.dualprint("Call \(callCid) has timed out after \(elapsedSeconds) seconds")
337
+ StreamCallPlugin.dualprint("No one accepted call \(callCid), marking all non-responders as missed")
328
338
 
329
339
  // Mark all members who haven't responded as "missed"
330
340
  for member in callState.members {
@@ -386,21 +396,21 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
386
396
  }
387
397
 
388
398
  guard let callState = callState else {
389
- print("Call state not found for cId: \(callCid)")
399
+ StreamCallPlugin.dualprint("Call state not found for cId: \(callCid)")
390
400
  return
391
401
  }
392
402
 
393
403
  let totalParticipants = callState.members.count
394
404
  let responseCount = callState.participantResponses.count
395
405
 
396
- print("Total participants: \(totalParticipants), Responses: \(responseCount)")
406
+ StreamCallPlugin.dualprint("Total participants: \(totalParticipants), Responses: \(responseCount)")
397
407
 
398
408
  let allResponded = responseCount >= totalParticipants
399
409
  let allRejectedOrMissed = allResponded &&
400
410
  callState.participantResponses.values.allSatisfy { $0 == "rejected" || $0 == "missed" }
401
411
 
402
412
  if allResponded && allRejectedOrMissed {
403
- print("All participants have rejected or missed the call")
413
+ StreamCallPlugin.dualprint("All participants have rejected or missed the call")
404
414
 
405
415
  // End the call
406
416
  if let call = streamVideo?.state.activeCall, call.cId == callCid {
@@ -544,18 +554,18 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
544
554
 
545
555
  Task {
546
556
  do {
547
- print("Creating call:")
548
- print("- Call ID: \(callId)")
549
- print("- Call Type: \(callType)")
550
- print("- Users: \(members)")
551
- print("- Should Ring: \(shouldRing)")
552
- print("- Team: \(team)")
557
+ StreamCallPlugin.dualprint("Creating call:")
558
+ StreamCallPlugin.dualprint("- Call ID: \(callId)")
559
+ StreamCallPlugin.dualprint("- Call Type: \(callType)")
560
+ StreamCallPlugin.dualprint("- Users: \(members)")
561
+ StreamCallPlugin.dualprint("- Should Ring: \(shouldRing)")
562
+ StreamCallPlugin.dualprint("- Team: \(team)")
553
563
 
554
564
  // Create the call object
555
565
  let streamCall = streamVideo?.call(callType: callType, callId: callId)
556
566
 
557
567
  // Start the call with the members
558
- print("Creating call with members...")
568
+ StreamCallPlugin.dualprint("Creating call with members...")
559
569
  try await streamCall?.create(
560
570
  memberIds: members,
561
571
  custom: [:],
@@ -563,9 +573,9 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
563
573
  )
564
574
 
565
575
  // Join the call
566
- print("Joining call...")
576
+ StreamCallPlugin.dualprint("Joining call...")
567
577
  try await streamCall?.join(create: false)
568
- print("Successfully joined call")
578
+ StreamCallPlugin.dualprint("Successfully joined call")
569
579
 
570
580
  // Update the CallOverlayView with the active call
571
581
  await MainActor.run {
@@ -695,14 +705,14 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
695
705
  }
696
706
 
697
707
  // Join the call
698
- print("Accepting and joining call \(streamCall!.cId)...")
708
+ StreamCallPlugin.dualprint("Accepting and joining call \(streamCall!.cId)...")
699
709
  guard case .incoming(let incomingCall) = await self.callViewModel?.callingState else {
700
710
  call.reject("Failed to accept call as there is no call ID")
701
711
  return
702
712
  }
703
713
 
704
714
  await self.callViewModel?.acceptCall(callType: incomingCall.type, callId: incomingCall.id)
705
- print("Successfully joined call")
715
+ StreamCallPlugin.dualprint("Successfully joined call")
706
716
 
707
717
  // Update the CallOverlayView with the active call
708
718
  await MainActor.run {
@@ -726,18 +736,18 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
726
736
 
727
737
  private func initializeStreamVideo() {
728
738
  if (state == .initialized) {
729
- print("initializeStreamVideo already initialized")
739
+ StreamCallPlugin.dualprint("initializeStreamVideo already initialized")
730
740
  // Try to get user credentials from repository
731
741
  guard let savedCredentials = SecureUserRepository.shared.loadCurrentUser() else {
732
- print("Save credentials not found, skipping initialization")
742
+ StreamCallPlugin.dualprint("Save credentials not found, skipping initialization")
733
743
  return
734
744
  }
735
745
  if (savedCredentials.user.id == streamVideo?.user.id) {
736
- print("Skipping initializeStreamVideo as user is already logged in")
746
+ StreamCallPlugin.dualprint("Skipping initializeStreamVideo as user is already logged in")
737
747
  return
738
748
  }
739
749
  } else if (state == .initializing) {
740
- print("initializeStreamVideo rejected - already initializing")
750
+ StreamCallPlugin.dualprint("initializeStreamVideo rejected - already initializing")
741
751
  return
742
752
  }
743
753
  state = .initializing
@@ -745,11 +755,11 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
745
755
  // Try to get user credentials from repository
746
756
  guard let savedCredentials = SecureUserRepository.shared.loadCurrentUser(),
747
757
  let apiKey = self.apiKey else {
748
- print("No saved credentials or API key found, skipping initialization")
758
+ StreamCallPlugin.dualprint("No saved credentials or API key found, skipping initialization")
749
759
  state = .notInitialized
750
760
  return
751
761
  }
752
- print("Initializing with saved credentials for user: \(savedCredentials.user.name)")
762
+ StreamCallPlugin.dualprint("Initializing with saved credentials for user: \(savedCredentials.user.name)")
753
763
 
754
764
  LogConfig.level = .debug
755
765
  self.streamVideo = StreamVideo(
@@ -758,7 +768,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
758
768
  token: UserToken(stringLiteral: savedCredentials.tokenValue),
759
769
  tokenProvider: {completion in
760
770
  guard let savedCredentials = SecureUserRepository.shared.loadCurrentUser() else {
761
- print("No saved credentials or API key found, cannot refresh token")
771
+ StreamCallPlugin.dualprint("No saved credentials or API key found, cannot refresh token")
762
772
 
763
773
  completion(.failure(NSError(domain: "No saved credentials or API key found, cannot refresh token", code: 0, userInfo: nil)))
764
774
  return
@@ -851,7 +861,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
851
861
 
852
862
  // Check if we already have an overlay view - do nothing if it exists
853
863
  if let existingOverlayView = self.overlayView, existingOverlayView.superview != nil {
854
- print("Call overlay view already exists, making it visible")
864
+ StreamCallPlugin.dualprint("Call overlay view already exists, making it visible")
855
865
  existingOverlayView.isHidden = false
856
866
  // Make webview transparent to see StreamCall UI underneath
857
867
  webView.isOpaque = false
@@ -860,7 +870,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
860
870
  return
861
871
  }
862
872
 
863
- print("Creating new call overlay view")
873
+ StreamCallPlugin.dualprint("Creating new call overlay view")
864
874
 
865
875
  // First, create the overlay view
866
876
  let overlayView = UIHostingController(rootView: CallOverlayView(viewModel: callOverlayView))
@@ -913,7 +923,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
913
923
  private func ensureViewRemoved() {
914
924
  // Check if we have an overlay view
915
925
  if let existingOverlayView = self.overlayView {
916
- print("Hiding call overlay view")
926
+ StreamCallPlugin.dualprint("Hiding call overlay view")
917
927
 
918
928
  // Hide the view instead of removing it
919
929
  existingOverlayView.isHidden = true
@@ -923,7 +933,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
923
933
  self.webView?.backgroundColor = nil
924
934
  self.webView?.scrollView.backgroundColor = nil
925
935
  } else {
926
- print("No call overlay view to hide")
936
+ StreamCallPlugin.dualprint("No call overlay view to hide")
927
937
  }
928
938
  }
929
939
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-stream-call",
3
- "version": "0.0.24",
3
+ "version": "0.0.25-alpha.0",
4
4
  "description": "Uses the https://getstream.io/ SDK to implement calling in Capacitor",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",