@capgo/capacitor-stream-call 0.0.31 → 0.0.32
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.
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import UIKit
|
|
2
|
+
import os.log
|
|
3
|
+
import WebKit
|
|
2
4
|
|
|
3
5
|
class TouchInterceptView: UIView {
|
|
4
6
|
private weak var webView: UIView?
|
|
@@ -11,58 +13,119 @@ class TouchInterceptView: UIView {
|
|
|
11
13
|
// Ensure this view is transparent and doesn't interfere with display
|
|
12
14
|
self.backgroundColor = .clear
|
|
13
15
|
self.isOpaque = false
|
|
14
|
-
|
|
16
|
+
os_log(.debug, "TouchInterceptView: setupWithWebView - webView: %{public}s, overlayView: %{public}s", String(describing: webView), String(describing: overlayView))
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
private func isInteractive(_ view: UIView) -> Bool {
|
|
20
|
+
if view is UIControl { return true }
|
|
21
|
+
if let grs = view.gestureRecognizers, !grs.isEmpty { return true }
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private func nonGreedyInteractiveHitTest(in view: UIView, point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
26
|
+
// Traverse subviews in reverse order (frontmost first)
|
|
27
|
+
for subview in view.subviews.reversed() where subview.isUserInteractionEnabled && !subview.isHidden && subview.alpha >= 0.01 {
|
|
28
|
+
let converted = view.convert(point, to: subview)
|
|
29
|
+
if subview.point(inside: converted, with: event) {
|
|
30
|
+
if let hit = nonGreedyInteractiveHitTest(in: subview, point: converted, with: event) {
|
|
31
|
+
return hit
|
|
32
|
+
}
|
|
33
|
+
}
|
|
21
34
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
// If no subview handled, return view itself only if truly interactive
|
|
36
|
+
return isInteractive(view) && view.point(inside: point, with: event) ? view : nil
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private func forwardClickToWeb(at pointInSelf: CGPoint) {
|
|
40
|
+
guard let wk = webView as? WKWebView else { return }
|
|
41
|
+
let locationInWeb = self.convert(pointInSelf, to: wk)
|
|
42
|
+
let x = Int(locationInWeb.x)
|
|
43
|
+
let y = Int(locationInWeb.y)
|
|
44
|
+
let js = """
|
|
45
|
+
(() => {
|
|
46
|
+
const x = \(x); const y = \(y);
|
|
47
|
+
const el = document.elementFromPoint(x, y);
|
|
48
|
+
if (!el) return 'NO_ELEM';
|
|
49
|
+
const eventInit = { bubbles: true, cancelable: true, clientX: x, clientY: y };
|
|
50
|
+
const touchInit = { bubbles: true, cancelable: true, touches: [{ clientX: x, clientY: y }], targetTouches: [], changedTouches: [], shiftKey: false };
|
|
51
|
+
const seq = [];
|
|
52
|
+
try {
|
|
53
|
+
seq.push(new TouchEvent('touchstart', touchInit));
|
|
54
|
+
} catch(e) { console.log('TouchEvent not supported', e); }
|
|
55
|
+
seq.push(new PointerEvent('pointerdown', { ...eventInit, pointerType: 'touch' }));
|
|
56
|
+
seq.push(new MouseEvent('mousedown', eventInit));
|
|
57
|
+
try {
|
|
58
|
+
seq.push(new TouchEvent('touchend', touchInit));
|
|
59
|
+
} catch(e) { }
|
|
60
|
+
seq.push(new PointerEvent('pointerup', { ...eventInit, pointerType: 'touch' }));
|
|
61
|
+
seq.push(new MouseEvent('mouseup', eventInit));
|
|
62
|
+
seq.push(new MouseEvent('click', eventInit));
|
|
63
|
+
seq.forEach(evt => el.dispatchEvent(evt));
|
|
64
|
+
console.log('SyntheticClick seq on', el);
|
|
65
|
+
return el.tagName;
|
|
66
|
+
})();
|
|
67
|
+
"""
|
|
68
|
+
os_log(.debug, "TouchInterceptView: forwardClickToWeb - (%{public}d,%{public}d)", x, y)
|
|
69
|
+
wk.evaluateJavaScript(js) { result, error in
|
|
70
|
+
if let error = error {
|
|
71
|
+
os_log(.error, "TouchInterceptView: JS error %{public}s", String(describing: error))
|
|
30
72
|
} else {
|
|
31
|
-
|
|
73
|
+
os_log(.debug, "TouchInterceptView: JS returned %{public}s", String(describing: result))
|
|
32
74
|
}
|
|
33
|
-
} else {
|
|
34
|
-
// print("hitTest: No WebView hit at point \(point) - passing through")
|
|
35
75
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
79
|
+
// Forward to web for debugging every touch point
|
|
80
|
+
os_log(.debug, "TouchInterceptView: hitTest entry at %{public}s. Forwarding click to web.", String(describing: point))
|
|
81
|
+
forwardClickToWeb(at: point)
|
|
82
|
+
// 1. interactive hit on overlay (including root)
|
|
83
|
+
if let overlayView = self.overlayView, !overlayView.isHidden {
|
|
84
|
+
let overlayPoint = self.convert(point, to: overlayView)
|
|
85
|
+
if let overlayHit = nonGreedyInteractiveHitTest(in: overlayView, point: overlayPoint, with: event) {
|
|
86
|
+
os_log(.debug, "TouchInterceptView: hitTest - Overlay view %{public}s at %{public}s", String(describing: overlayHit), String(describing: overlayPoint))
|
|
87
|
+
return overlayHit
|
|
88
|
+
}
|
|
42
89
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
90
|
+
// 2. webView fallback
|
|
91
|
+
if let webView = self.webView {
|
|
92
|
+
let webPoint = self.convert(point, to: webView)
|
|
93
|
+
let result = webView.hitTest(webPoint, with: event)
|
|
94
|
+
os_log(.debug, "TouchInterceptView: hitTest - WebView result %{public}s at %{public}s", String(describing: result), String(describing: webPoint))
|
|
95
|
+
return result
|
|
96
|
+
}
|
|
97
|
+
os_log(.debug, "TouchInterceptView: hitTest - No view found for %{public}s", String(describing: point))
|
|
46
98
|
return nil
|
|
47
99
|
}
|
|
48
100
|
|
|
49
101
|
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
|
50
|
-
guard let webView = webView
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return
|
|
102
|
+
guard let webView = self.webView else {
|
|
103
|
+
os_log(.debug, "TouchInterceptView: point(inside) - webView is nil for point %{public}s. Checking overlay or deferring to super.", String(describing: point))
|
|
104
|
+
if let overlayView = self.overlayView, !overlayView.isHidden {
|
|
105
|
+
let overlayPoint = self.convert(point, to: overlayView)
|
|
106
|
+
let overlayViewConsidersPointInside = overlayView.point(inside: overlayPoint, with: event)
|
|
107
|
+
os_log(.debug, "TouchInterceptView: point(inside) - webView nil. Overlay (%{public}s) for converted point %{public}s = %s", String(describing: overlayViewConsidersPointInside), String(describing: overlayPoint), String(describing: overlayViewConsidersPointInside))
|
|
108
|
+
return overlayViewConsidersPointInside
|
|
109
|
+
}
|
|
110
|
+
return super.point(inside: point, with: event)
|
|
59
111
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
112
|
+
|
|
113
|
+
let webViewPoint = self.convert(point, to: webView)
|
|
114
|
+
let webViewConsidersPointInside = webView.point(inside: webViewPoint, with: event)
|
|
115
|
+
|
|
116
|
+
if let overlayView = self.overlayView, !overlayView.isHidden {
|
|
117
|
+
let overlayPoint = self.convert(point, to: overlayView)
|
|
118
|
+
let overlayViewConsidersPointInside = overlayView.point(inside: overlayPoint, with: event)
|
|
119
|
+
let result = webViewConsidersPointInside || overlayViewConsidersPointInside
|
|
120
|
+
os_log(.debug, "TouchInterceptView: point(inside) - WebView (%{public}s at %{public}s) OR Visible Overlay (%{public}s at %{public}s) for original point %{public}s = %s", String(describing: webViewConsidersPointInside), String(describing: webViewPoint), String(describing: overlayViewConsidersPointInside), String(describing: overlayPoint), String(describing: point), String(describing: result))
|
|
121
|
+
return result
|
|
122
|
+
} else {
|
|
123
|
+
if self.overlayView == nil {
|
|
124
|
+
os_log(.debug, "TouchInterceptView: point(inside) - Overlay nil. WebView (%{public}s at %{public}s) for original point %{public}s = %s", String(describing: webViewConsidersPointInside), String(describing: webViewPoint), String(describing: point), String(describing: webViewConsidersPointInside))
|
|
125
|
+
} else {
|
|
126
|
+
os_log(.debug, "TouchInterceptView: point(inside) - Overlay hidden. WebView (%{public}s at %{public}s) for original point %{public}s = %s", String(describing: webViewConsidersPointInside), String(describing: webViewPoint), String(describing: point), String(describing: webViewConsidersPointInside))
|
|
127
|
+
}
|
|
128
|
+
return webViewConsidersPointInside
|
|
64
129
|
}
|
|
65
|
-
// print("point(inside:with): No view claims point \(point)")
|
|
66
|
-
return false
|
|
67
130
|
}
|
|
68
131
|
}
|
package/package.json
CHANGED