@capgo/capacitor-inappbrowser 8.12.2-beta.pr634.524.1 → 8.12.2-beta.pr634.543.1
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.
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +2 -6
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +16 -14
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController+ReloadGesture.swift +45 -15
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +7 -3
- package/package.json +1 -1
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/ReloadGestureSupport.java +0 -16
|
@@ -3868,12 +3868,8 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
|
|
|
3868
3868
|
if (_webView != webView) {
|
|
3869
3869
|
return;
|
|
3870
3870
|
}
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
webView.scrollTo(webView.getScrollX(), targetY);
|
|
3874
|
-
}
|
|
3875
|
-
if (swipeRefreshLayout != null) {
|
|
3876
|
-
swipeRefreshLayout.setRefreshing(false);
|
|
3871
|
+
if (webView.getScrollY() != 0) {
|
|
3872
|
+
webView.scrollTo(webView.getScrollX(), 0);
|
|
3877
3873
|
}
|
|
3878
3874
|
});
|
|
3879
3875
|
}
|
|
@@ -250,9 +250,6 @@ enum CustomWebViewFrameSupport {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
enum ReloadGestureSupport {
|
|
253
|
-
/// Approximate UIRefreshControl activation distance in points.
|
|
254
|
-
static let defaultPullThreshold: CGFloat = 60
|
|
255
|
-
|
|
256
253
|
/// UIRefreshControl may fire valueChanged while the finger is still down.
|
|
257
254
|
/// Match browser UX: commit reload only after touch end.
|
|
258
255
|
static func shouldDeferReloadUntilTouchEnd(isTracking: Bool, isDragging: Bool) -> Bool {
|
|
@@ -264,25 +261,30 @@ enum ReloadGestureSupport {
|
|
|
264
261
|
max(0, -(contentOffsetY + adjustedContentInsetTop))
|
|
265
262
|
}
|
|
266
263
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
264
|
+
/// After intentional touch end, reload only if still near the activation pull distance
|
|
265
|
+
/// captured when UIRefreshControl fired `.valueChanged` (not a fixed constant).
|
|
266
|
+
static func shouldReloadOnTouchEnd(
|
|
267
|
+
pendingReload: Bool,
|
|
268
|
+
currentPullDistance: CGFloat,
|
|
269
|
+
armedPullDistance: CGFloat
|
|
271
270
|
) -> Bool {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
/// After intentional touch end, reload only if pull is still past the threshold.
|
|
276
|
-
static func shouldReloadOnTouchEnd(pendingReload: Bool, isPullPastThreshold: Bool) -> Bool {
|
|
277
|
-
pendingReload && isPullPastThreshold
|
|
271
|
+
guard pendingReload, armedPullDistance > 0 else { return false }
|
|
272
|
+
// Allow slight finger jitter below the exact activation point.
|
|
273
|
+
return currentPullDistance >= armedPullDistance * 0.9
|
|
278
274
|
}
|
|
279
275
|
|
|
280
276
|
/// Resting offset for the current adjusted top inset (safe-area aware).
|
|
277
|
+
/// - Parameter forceToRestingTop: After gesture reload, always snap to resting top (fixes clipped header).
|
|
278
|
+
/// Otherwise only un-overscroll after a cancelled pull.
|
|
281
279
|
static func contentOffsetYAfterReloadReset(
|
|
282
280
|
currentY: CGFloat,
|
|
283
|
-
adjustedContentInsetTop: CGFloat
|
|
281
|
+
adjustedContentInsetTop: CGFloat,
|
|
282
|
+
forceToRestingTop: Bool = false
|
|
284
283
|
) -> CGFloat {
|
|
285
284
|
let restingY = -adjustedContentInsetTop
|
|
285
|
+
if forceToRestingTop {
|
|
286
|
+
return restingY
|
|
287
|
+
}
|
|
286
288
|
return currentY < restingY ? restingY : currentY
|
|
287
289
|
}
|
|
288
290
|
}
|
|
@@ -11,6 +11,7 @@ extension WKWebViewController {
|
|
|
11
11
|
|
|
12
12
|
guard enableReloadGesture, !disableOverscroll else {
|
|
13
13
|
pendingReloadFromGesture = false
|
|
14
|
+
reloadGestureArmedPullDistance = 0
|
|
14
15
|
return
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -40,6 +41,11 @@ extension WKWebViewController {
|
|
|
40
41
|
isDragging: scrollView.isDragging
|
|
41
42
|
) {
|
|
42
43
|
pendingReloadFromGesture = true
|
|
44
|
+
// Capture the real activation pull distance from UIRefreshControl.
|
|
45
|
+
reloadGestureArmedPullDistance = ReloadGestureSupport.pullDistance(
|
|
46
|
+
contentOffsetY: scrollView.contentOffset.y,
|
|
47
|
+
adjustedContentInsetTop: scrollView.adjustedContentInset.top
|
|
48
|
+
)
|
|
43
49
|
return
|
|
44
50
|
}
|
|
45
51
|
|
|
@@ -52,30 +58,35 @@ extension WKWebViewController {
|
|
|
52
58
|
|
|
53
59
|
switch gesture.state {
|
|
54
60
|
case .ended:
|
|
55
|
-
let
|
|
61
|
+
let pullDistance = ReloadGestureSupport.pullDistance(
|
|
56
62
|
contentOffsetY: scrollView.contentOffset.y,
|
|
57
63
|
adjustedContentInsetTop: scrollView.adjustedContentInset.top
|
|
58
64
|
)
|
|
59
65
|
let shouldReload = ReloadGestureSupport.shouldReloadOnTouchEnd(
|
|
60
66
|
pendingReload: pendingReloadFromGesture,
|
|
61
|
-
|
|
67
|
+
currentPullDistance: pullDistance,
|
|
68
|
+
armedPullDistance: reloadGestureArmedPullDistance
|
|
62
69
|
)
|
|
63
70
|
pendingReloadFromGesture = false
|
|
71
|
+
reloadGestureArmedPullDistance = 0
|
|
64
72
|
|
|
65
73
|
if shouldReload {
|
|
66
74
|
performReloadFromGesture()
|
|
67
75
|
} else if !reloadFromGestureInProgress,
|
|
68
76
|
scrollView.refreshControl?.isRefreshing == true {
|
|
69
77
|
scrollView.refreshControl?.endRefreshing()
|
|
70
|
-
resetReloadGestureScrollState(on: scrollView)
|
|
78
|
+
resetReloadGestureScrollState(on: scrollView, forceToRestingTop: false)
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
case .cancelled, .failed:
|
|
74
82
|
// System interruption — never commit a reload.
|
|
75
83
|
pendingReloadFromGesture = false
|
|
84
|
+
reloadGestureArmedPullDistance = 0
|
|
85
|
+
// Don't touch an in-flight gesture reload's spinner / scroll.
|
|
86
|
+
guard !reloadFromGestureInProgress else { break }
|
|
76
87
|
if scrollView.refreshControl?.isRefreshing == true {
|
|
77
88
|
scrollView.refreshControl?.endRefreshing()
|
|
78
|
-
resetReloadGestureScrollState(on: scrollView)
|
|
89
|
+
resetReloadGestureScrollState(on: scrollView, forceToRestingTop: false)
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
default:
|
|
@@ -85,40 +96,59 @@ extension WKWebViewController {
|
|
|
85
96
|
|
|
86
97
|
private func performReloadFromGesture() {
|
|
87
98
|
pendingReloadFromGesture = false
|
|
99
|
+
reloadGestureArmedPullDistance = 0
|
|
88
100
|
reloadFromGestureInProgress = true
|
|
89
|
-
|
|
101
|
+
// Track this navigation so cancelled prior loads don't clear gesture state early.
|
|
102
|
+
reloadGestureNavigation = self.capableWebView?.reload()
|
|
103
|
+
if reloadGestureNavigation == nil {
|
|
104
|
+
stopReloadGesture()
|
|
105
|
+
}
|
|
90
106
|
}
|
|
91
107
|
|
|
92
|
-
private func resetReloadGestureScrollState(on scrollView: UIScrollView) {
|
|
93
|
-
// Keep baseline/safe-area insets; only clamp sticky refresh overscroll.
|
|
108
|
+
private func resetReloadGestureScrollState(on scrollView: UIScrollView, forceToRestingTop: Bool) {
|
|
94
109
|
let resetY = ReloadGestureSupport.contentOffsetYAfterReloadReset(
|
|
95
110
|
currentY: scrollView.contentOffset.y,
|
|
96
|
-
adjustedContentInsetTop: scrollView.adjustedContentInset.top
|
|
111
|
+
adjustedContentInsetTop: scrollView.adjustedContentInset.top,
|
|
112
|
+
forceToRestingTop: forceToRestingTop
|
|
97
113
|
)
|
|
98
114
|
if resetY != scrollView.contentOffset.y {
|
|
99
115
|
scrollView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: resetY), animated: false)
|
|
100
116
|
}
|
|
101
117
|
}
|
|
102
118
|
|
|
103
|
-
func stopReloadGesture() {
|
|
119
|
+
func stopReloadGesture(for navigation: WKNavigation? = nil) {
|
|
120
|
+
// Ordinary page finishes must not clear an armed pull the user is still holding.
|
|
121
|
+
guard reloadFromGestureInProgress else { return }
|
|
122
|
+
|
|
123
|
+
// Ignore unrelated navigation callbacks while a gesture reload is in flight.
|
|
124
|
+
if let expected = reloadGestureNavigation,
|
|
125
|
+
let navigation,
|
|
126
|
+
expected !== navigation {
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
104
130
|
pendingReloadFromGesture = false
|
|
105
|
-
let shouldResetScroll = reloadFromGestureInProgress
|
|
106
131
|
reloadFromGestureInProgress = false
|
|
132
|
+
reloadGestureNavigation = nil
|
|
133
|
+
reloadGestureArmedPullDistance = 0
|
|
107
134
|
|
|
108
135
|
guard let activeWebView = self.capableWebView else { return }
|
|
109
136
|
let scrollView = activeWebView.scrollView
|
|
110
137
|
scrollView.refreshControl?.endRefreshing()
|
|
111
138
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// UIRefreshControl + WKWebView.reload() often leave a top gap and block the next pull
|
|
115
|
-
// until a full document navigation recreates scroll state.
|
|
139
|
+
// UIRefreshControl + WKWebView.reload() often leave offset at 0 instead of
|
|
140
|
+
// -adjustedContentInset.top (clips header ~safe-area) and block the next pull.
|
|
116
141
|
DispatchQueue.main.async { [weak self] in
|
|
117
142
|
guard let self, let activeWebView = self.capableWebView else { return }
|
|
118
143
|
let scrollView = activeWebView.scrollView
|
|
119
144
|
scrollView.refreshControl?.endRefreshing()
|
|
120
|
-
self.resetReloadGestureScrollState(on: scrollView)
|
|
145
|
+
self.resetReloadGestureScrollState(on: scrollView, forceToRestingTop: true)
|
|
121
146
|
self.configureReloadGesture(for: activeWebView)
|
|
147
|
+
// Rebind can change adjusted insets; snap again to the new resting top.
|
|
148
|
+
self.resetReloadGestureScrollState(
|
|
149
|
+
on: activeWebView.scrollView,
|
|
150
|
+
forceToRestingTop: true
|
|
151
|
+
)
|
|
122
152
|
}
|
|
123
153
|
}
|
|
124
154
|
}
|
|
@@ -474,6 +474,8 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
474
474
|
var enableReloadGesture: Bool = false
|
|
475
475
|
var pendingReloadFromGesture = false
|
|
476
476
|
var reloadFromGestureInProgress = false
|
|
477
|
+
var reloadGestureNavigation: WKNavigation?
|
|
478
|
+
var reloadGestureArmedPullDistance: CGFloat = 0
|
|
477
479
|
var reloadPanObserverInstalled = false
|
|
478
480
|
var disableOverscroll: Bool = false
|
|
479
481
|
var proxyRequests: Bool = false
|
|
@@ -2576,6 +2578,8 @@ public extension WKWebViewController {
|
|
|
2576
2578
|
}
|
|
2577
2579
|
pendingReloadFromGesture = false
|
|
2578
2580
|
reloadFromGestureInProgress = false
|
|
2581
|
+
reloadGestureNavigation = nil
|
|
2582
|
+
reloadGestureArmedPullDistance = 0
|
|
2579
2583
|
|
|
2580
2584
|
// Remove KVO observers FIRST, before any operation that could trigger them
|
|
2581
2585
|
webView.removeObserver(self, forKeyPath: estimatedProgressKeyPath)
|
|
@@ -3522,7 +3526,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3522
3526
|
lastInjectedSafeAreaInsets = nil
|
|
3523
3527
|
syncWebViewSafeAreaLayout()
|
|
3524
3528
|
emit("browserPageLoaded")
|
|
3525
|
-
stopReloadGesture()
|
|
3529
|
+
stopReloadGesture(for: navigation)
|
|
3526
3530
|
}
|
|
3527
3531
|
|
|
3528
3532
|
public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
|
@@ -3532,7 +3536,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3532
3536
|
self.url = url
|
|
3533
3537
|
delegate?.webViewController?(self, didFail: url, withError: error)
|
|
3534
3538
|
}
|
|
3535
|
-
stopReloadGesture()
|
|
3539
|
+
stopReloadGesture(for: navigation)
|
|
3536
3540
|
emit("pageLoadError")
|
|
3537
3541
|
}
|
|
3538
3542
|
|
|
@@ -3543,7 +3547,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3543
3547
|
self.url = url
|
|
3544
3548
|
delegate?.webViewController?(self, didFail: url, withError: error)
|
|
3545
3549
|
}
|
|
3546
|
-
stopReloadGesture()
|
|
3550
|
+
stopReloadGesture(for: navigation)
|
|
3547
3551
|
emit("pageLoadError")
|
|
3548
3552
|
}
|
|
3549
3553
|
|
package/package.json
CHANGED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
package ee.forgr.capacitor_inappbrowser;
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pure helpers for pull-to-refresh reset after a gesture reload.
|
|
5
|
-
* Sticky scrollY greater than 0 makes SwipeRefreshLayout think the child can scroll up,
|
|
6
|
-
* which disables the next pull until a full document navigation.
|
|
7
|
-
*/
|
|
8
|
-
final class ReloadGestureSupport {
|
|
9
|
-
|
|
10
|
-
private ReloadGestureSupport() {}
|
|
11
|
-
|
|
12
|
-
/** Pin vertical scroll to top after a gesture reload so the next pull can start. */
|
|
13
|
-
static int webViewScrollYAfterGestureReload(int currentScrollY) {
|
|
14
|
-
return 0;
|
|
15
|
-
}
|
|
16
|
-
}
|