@capgo/capacitor-stream-call 0.0.22 → 0.0.23

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.
@@ -791,38 +791,57 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
791
791
  }
792
792
 
793
793
  private func setupViews() {
794
-
795
-
796
- // // Create SwiftUI view with view model
797
- // let (hostingController, viewModel) = CallOverlayView.create(streamVideo: self.streamVideo)
798
- // hostingController.view.backgroundColor = .clear
799
- // hostingController.view.translatesAutoresizingMaskIntoConstraints = false
800
- //
801
- // self.hostingController = hostingController
802
- // self.overlayViewModel = viewModel
803
- // self.overlayView = hostingController.view
804
- //
805
- // if let overlayView = self.overlayView {
806
- // // Setup the views in TouchInterceptView
807
- // touchInterceptView.setupWithWebView(webView, overlayView: overlayView)
808
- //
809
- // // Setup constraints for webView
810
- // NSLayoutConstraint.activate([
811
- // webView.topAnchor.constraint(equalTo: touchInterceptView.topAnchor),
812
- // webView.bottomAnchor.constraint(equalTo: touchInterceptView.bottomAnchor),
813
- // webView.leadingAnchor.constraint(equalTo: touchInterceptView.leadingAnchor),
814
- // webView.trailingAnchor.constraint(equalTo: touchInterceptView.trailingAnchor)
815
- // ])
816
- //
817
- // // Setup constraints for overlayView
818
- // let safeGuide = touchInterceptView.safeAreaLayoutGuide
819
- // NSLayoutConstraint.activate([
820
- // overlayView.topAnchor.constraint(equalTo: safeGuide.topAnchor),
821
- // overlayView.bottomAnchor.constraint(equalTo: safeGuide.bottomAnchor),
822
- // overlayView.leadingAnchor.constraint(equalTo: safeGuide.leadingAnchor),
823
- // overlayView.trailingAnchor.constraint(equalTo: safeGuide.trailingAnchor)
824
- // ])
825
- // }
794
+ guard let webView = self.webView, let parent = webView.superview else { return }
795
+
796
+ // Create the touch intercept view as an overlay for touch passthrough
797
+ let touchInterceptView = TouchInterceptView(frame: parent.bounds)
798
+ touchInterceptView.translatesAutoresizingMaskIntoConstraints = false
799
+ touchInterceptView.backgroundColor = .clear
800
+ touchInterceptView.isOpaque = false
801
+
802
+ // Create SwiftUI view with view model if not already created
803
+ if self.overlayView == nil, let callViewModel = self.callViewModel {
804
+ let hostingController = UIHostingController(rootView: CallOverlayView(viewModel: callViewModel))
805
+ hostingController.view.backgroundColor = .clear
806
+ hostingController.view.translatesAutoresizingMaskIntoConstraints = false
807
+ hostingController.view.isHidden = true // Initially hidden until a call is active
808
+
809
+ self.hostingController = hostingController
810
+ self.overlayView = hostingController.view
811
+
812
+ if let overlayView = self.overlayView {
813
+ // Insert overlay view below webview
814
+ parent.insertSubview(overlayView, belowSubview: webView)
815
+
816
+ // Setup constraints for overlayView
817
+ let safeGuide = parent.safeAreaLayoutGuide
818
+ NSLayoutConstraint.activate([
819
+ overlayView.topAnchor.constraint(equalTo: safeGuide.topAnchor),
820
+ overlayView.bottomAnchor.constraint(equalTo: safeGuide.bottomAnchor),
821
+ overlayView.leadingAnchor.constraint(equalTo: safeGuide.leadingAnchor),
822
+ overlayView.trailingAnchor.constraint(equalTo: safeGuide.trailingAnchor)
823
+ ])
824
+ }
825
+ }
826
+
827
+ // Setup touch intercept view with references to webview and overlay
828
+ if let overlayView = self.overlayView {
829
+ touchInterceptView.setupWithWebView(webView, overlayView: overlayView)
830
+ // Insert touchInterceptView above webView
831
+ parent.insertSubview(touchInterceptView, aboveSubview: webView)
832
+ } else {
833
+ // If overlayView is not present, just add on top of webView
834
+ touchInterceptView.setupWithWebView(webView, overlayView: webView)
835
+ parent.insertSubview(touchInterceptView, aboveSubview: webView)
836
+ }
837
+
838
+ // Setup constraints for touchInterceptView to cover the entire parent
839
+ NSLayoutConstraint.activate([
840
+ touchInterceptView.topAnchor.constraint(equalTo: parent.topAnchor),
841
+ touchInterceptView.bottomAnchor.constraint(equalTo: parent.bottomAnchor),
842
+ touchInterceptView.leadingAnchor.constraint(equalTo: parent.leadingAnchor),
843
+ touchInterceptView.trailingAnchor.constraint(equalTo: parent.trailingAnchor)
844
+ ])
826
845
  }
827
846
 
828
847
  private func createCallOverlayView() {
@@ -832,17 +851,23 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
832
851
 
833
852
  // Check if we already have an overlay view - do nothing if it exists
834
853
  if let existingOverlayView = self.overlayView, existingOverlayView.superview != nil {
835
- print("Call overlay view already exists, doing nothing")
854
+ print("Call overlay view already exists, making it visible")
855
+ existingOverlayView.isHidden = false
856
+ // Make webview transparent to see StreamCall UI underneath
857
+ webView.isOpaque = false
858
+ webView.backgroundColor = .clear
859
+ webView.scrollView.backgroundColor = .clear
836
860
  return
837
861
  }
838
862
 
839
863
  print("Creating new call overlay view")
840
864
 
841
865
  // First, create the overlay view
842
- let overlayView = CallOverlayView.create(callViewModel: callOverlayView)
866
+ let overlayView = UIHostingController(rootView: CallOverlayView(viewModel: callOverlayView))
843
867
  overlayView.view.translatesAutoresizingMaskIntoConstraints = false
868
+ overlayView.view.isHidden = false // Make visible during a call
844
869
 
845
- // Important: Insert the overlay view BELOW the webView in the view hierarchy
870
+ // Insert the overlay view below the webView in the view hierarchy
846
871
  parent.insertSubview(overlayView.view, belowSubview: webView)
847
872
 
848
873
  // Set constraints to fill the parent's safe area
@@ -855,7 +880,7 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
855
880
  overlayView.view.trailingAnchor.constraint(equalTo: safeGuide.trailingAnchor)
856
881
  ])
857
882
 
858
- // Set opacity for visual effect - make webView transparent to see overlay
883
+ // Make webview transparent to see StreamCall UI underneath
859
884
  webView.isOpaque = false
860
885
  webView.backgroundColor = .clear
861
886
  webView.scrollView.backgroundColor = .clear
@@ -863,26 +888,42 @@ public class StreamCallPlugin: CAPPlugin, CAPBridgedPlugin {
863
888
  // Store reference to the hosting controller
864
889
  self.hostingController = overlayView
865
890
  self.overlayView = overlayView.view
891
+
892
+ // Ensure touch intercept view is on top
893
+ if let touchInterceptView = parent.subviews.first(where: { $0 is TouchInterceptView }) {
894
+ parent.bringSubviewToFront(touchInterceptView)
895
+ } else {
896
+ // Create touch intercept view if not already created
897
+ let touchInterceptView = TouchInterceptView(frame: parent.bounds)
898
+ touchInterceptView.translatesAutoresizingMaskIntoConstraints = false
899
+ touchInterceptView.backgroundColor = .clear
900
+ touchInterceptView.isOpaque = false
901
+ touchInterceptView.setupWithWebView(webView, overlayView: overlayView.view)
902
+ parent.addSubview(touchInterceptView)
903
+
904
+ NSLayoutConstraint.activate([
905
+ touchInterceptView.topAnchor.constraint(equalTo: parent.topAnchor),
906
+ touchInterceptView.bottomAnchor.constraint(equalTo: parent.bottomAnchor),
907
+ touchInterceptView.leadingAnchor.constraint(equalTo: parent.leadingAnchor),
908
+ touchInterceptView.trailingAnchor.constraint(equalTo: parent.trailingAnchor)
909
+ ])
910
+ }
866
911
  }
867
912
 
868
913
  private func ensureViewRemoved() {
869
914
  // Check if we have an overlay view
870
915
  if let existingOverlayView = self.overlayView {
871
- print("Removing call overlay view")
916
+ print("Hiding call overlay view")
872
917
 
873
- // Remove the view from its superview
874
- existingOverlayView.removeFromSuperview()
918
+ // Hide the view instead of removing it
919
+ existingOverlayView.isHidden = true
875
920
 
876
921
  // Reset opacity for webView
877
922
  self.webView?.isOpaque = true
878
923
  self.webView?.backgroundColor = nil
879
924
  self.webView?.scrollView.backgroundColor = nil
880
-
881
- // Clear references
882
- self.overlayView = nil
883
- self.hostingController = nil
884
925
  } else {
885
- print("No call overlay view to remove")
926
+ print("No call overlay view to hide")
886
927
  }
887
928
  }
888
929
 
@@ -0,0 +1,68 @@
1
+ import UIKit
2
+
3
+ class TouchInterceptView: UIView {
4
+ private weak var webView: UIView?
5
+ private weak var overlayView: UIView?
6
+
7
+ func setupWithWebView(_ webView: UIView, overlayView: UIView) {
8
+ self.webView = webView
9
+ self.overlayView = overlayView
10
+
11
+ // Ensure this view is transparent and doesn't interfere with display
12
+ self.backgroundColor = .clear
13
+ self.isOpaque = false
14
+ print("TouchInterceptView setup with webView: \(webView) and overlayView: \(overlayView)")
15
+ }
16
+
17
+ override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
18
+ guard let webView = webView, let overlayView = overlayView, overlayView.isHidden == false else {
19
+ // print("hitTest: Conditions not met - webView: \(webView?.description ?? "nil"), overlayView: \(overlayView?.description ?? "nil"), overlayHidden: \(overlayView?.isHidden ?? true)")
20
+ return super.hitTest(point, with: event)
21
+ }
22
+
23
+ // First, check if the webview has a specific subview to interact with at this point
24
+ let webViewHit = webView.hitTest(point, with: event)
25
+ if webViewHit != nil && webViewHit != webView {
26
+ // Check if the hit view is a specific interactive element (like a button)
27
+ if webViewHit is UIButton || webViewHit?.accessibilityTraits.contains(.button) == true {
28
+ // print("hitTest: WebView interactive element hit at point \(point) - returning \(webViewHit?.description ?? "nil")")
29
+ return webViewHit
30
+ } else {
31
+ // print("hitTest: WebView hit at point \(point) but not an interactive element - passing through")
32
+ }
33
+ } else {
34
+ // print("hitTest: No WebView hit at point \(point) - passing through")
35
+ }
36
+
37
+ // If no specific interactive element in webview is hit, pass through to overlay (StreamCall UI)
38
+ let overlayHit = overlayView.hitTest(point, with: event)
39
+ if overlayHit != nil {
40
+ // print("hitTest: Overlay hit at point \(point) - returning \(overlayHit?.description ?? "nil")")
41
+ return overlayHit
42
+ }
43
+
44
+ // If neither webview nor overlay handles the touch, return nil to pass through
45
+ // print("hitTest: No hit at point \(point) - returning nil")
46
+ return nil
47
+ }
48
+
49
+ override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
50
+ guard let webView = webView, let overlayView = overlayView, overlayView.isHidden == false else {
51
+ // print("point(inside:with): Conditions not met - webView: \(webView?.description ?? "nil"), overlayView: \(overlayView?.description ?? "nil"), overlayHidden: \(overlayView?.isHidden ?? true)")
52
+ return false
53
+ }
54
+ // Check if webview has content at this point
55
+ if webView.point(inside: point, with: event) {
56
+ // If webview claims the point, check for interactive elements in hitTest
57
+ // print("point(inside:with): WebView claims point \(point) - will check for interactive elements")
58
+ return true
59
+ }
60
+ // Otherwise, allow touches to pass through to the overlay if relevant
61
+ if overlayView.point(inside: point, with: event) {
62
+ // print("point(inside:with): Overlay claims point \(point)")
63
+ return true
64
+ }
65
+ // print("point(inside:with): No view claims point \(point)")
66
+ return false
67
+ }
68
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-stream-call",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
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",