expo-scroll-forwarder 0.1.3 → 0.1.4
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,5 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
|
+
import UIKit
|
|
2
3
|
|
|
3
4
|
class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
4
5
|
var scrollViewTag: Int? {
|
|
@@ -8,6 +9,7 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
private var rctScrollView: RCTScrollView?
|
|
12
|
+
private var rctRefreshCtrl: UIRefreshControl?
|
|
11
13
|
private var cancelGestureRecognizers: [UIGestureRecognizer]?
|
|
12
14
|
private var animTimer: Timer?
|
|
13
15
|
private var initialOffset: CGFloat = 0.0
|
|
@@ -36,7 +38,6 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
36
38
|
if gestureRecognizer is UIPanGestureRecognizer, otherGestureRecognizer is UIPanGestureRecognizer {
|
|
37
39
|
return false
|
|
38
40
|
}
|
|
39
|
-
|
|
40
41
|
return true
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -68,7 +69,6 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
68
69
|
if sv.contentOffset.y < 0 {
|
|
69
70
|
sv.contentOffset.y = 0
|
|
70
71
|
}
|
|
71
|
-
|
|
72
72
|
self.initialOffset = sv.contentOffset.y
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -78,7 +78,6 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
78
78
|
if sv.contentOffset.y <= -130, !didImpact {
|
|
79
79
|
let generator = UIImpactFeedbackGenerator(style: .light)
|
|
80
80
|
generator.impactOccurred()
|
|
81
|
-
|
|
82
81
|
self.didImpact = true
|
|
83
82
|
}
|
|
84
83
|
}
|
|
@@ -88,16 +87,7 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
88
87
|
self.didImpact = false
|
|
89
88
|
|
|
90
89
|
if sv.contentOffset.y <= -130 {
|
|
91
|
-
|
|
92
|
-
if let refreshControl = sv.refreshControl {
|
|
93
|
-
// Animate to proper refresh position
|
|
94
|
-
UIView.animate(withDuration: 0.3, delay: 0, options: .beginFromCurrentState, animations: {
|
|
95
|
-
sv.contentOffset = CGPoint(x: 0, y: -65)
|
|
96
|
-
}, completion: { _ in
|
|
97
|
-
refreshControl.beginRefreshing()
|
|
98
|
-
refreshControl.sendActions(for: .valueChanged)
|
|
99
|
-
})
|
|
100
|
-
}
|
|
90
|
+
self.triggerRefresh()
|
|
101
91
|
return
|
|
102
92
|
}
|
|
103
93
|
|
|
@@ -109,23 +99,43 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
109
99
|
}
|
|
110
100
|
}
|
|
111
101
|
|
|
102
|
+
func triggerRefresh() {
|
|
103
|
+
guard let sv = self.rctScrollView?.scrollView,
|
|
104
|
+
let refreshControl = sv.refreshControl else {
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Animate to the proper refresh position
|
|
109
|
+
UIView.animate(withDuration: 0.3, delay: 0, options: .beginFromCurrentState, animations: {
|
|
110
|
+
sv.contentOffset = CGPoint(x: 0, y: -65)
|
|
111
|
+
}, completion: { [weak self] _ in
|
|
112
|
+
// Begin refreshing and trigger the control changed event
|
|
113
|
+
refreshControl.beginRefreshing()
|
|
114
|
+
|
|
115
|
+
// Use the proper RCT method if available (for React Native refresh control)
|
|
116
|
+
if refreshControl.responds(to: Selector(("forwarderBeginRefreshing"))) {
|
|
117
|
+
refreshControl.perform(Selector(("forwarderBeginRefreshing")))
|
|
118
|
+
} else {
|
|
119
|
+
// Fallback: trigger the valueChanged action manually
|
|
120
|
+
refreshControl.sendActions(for: .valueChanged)
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
func startDecayAnimation(_ translation: CGFloat, _ velocity: CGFloat) {
|
|
113
126
|
guard let sv = self.rctScrollView?.scrollView else {
|
|
114
127
|
return
|
|
115
128
|
}
|
|
116
129
|
|
|
117
130
|
var velocity = velocity
|
|
118
|
-
|
|
119
131
|
self.enableCancelGestureRecognizers()
|
|
120
132
|
|
|
121
|
-
|
|
122
|
-
velocity = min(velocity, 5000)
|
|
123
|
-
} else {
|
|
124
|
-
velocity = max(velocity, -5000)
|
|
125
|
-
}
|
|
133
|
+
velocity = velocity > 0 ? min(velocity, 5000) : max(velocity, -5000)
|
|
126
134
|
|
|
127
135
|
var animTranslation = -translation
|
|
128
|
-
self.animTimer = Timer.scheduledTimer(withTimeInterval: 1.0 / 120, repeats: true) { _ in
|
|
136
|
+
self.animTimer = Timer.scheduledTimer(withTimeInterval: 1.0 / 120, repeats: true) { [weak self] _ in
|
|
137
|
+
guard let self = self else { return }
|
|
138
|
+
|
|
129
139
|
velocity *= 0.9875
|
|
130
140
|
animTranslation = (-velocity / 120) + animTranslation
|
|
131
141
|
|
|
@@ -137,7 +147,6 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
137
147
|
} else {
|
|
138
148
|
sv.contentOffset.y = 0
|
|
139
149
|
}
|
|
140
|
-
|
|
141
150
|
self.stopTimer()
|
|
142
151
|
return
|
|
143
152
|
} else {
|
|
@@ -154,7 +163,6 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
154
163
|
if offset < 0 {
|
|
155
164
|
return offset - (offset * 0.55)
|
|
156
165
|
}
|
|
157
|
-
|
|
158
166
|
return offset
|
|
159
167
|
}
|
|
160
168
|
|
|
@@ -167,6 +175,8 @@ class ExpoScrollForwarderView: ExpoView, UIGestureRecognizerDelegate {
|
|
|
167
175
|
|
|
168
176
|
self.rctScrollView = self.appContext?
|
|
169
177
|
.findView(withTag: scrollViewTag, ofType: RCTScrollView.self)
|
|
178
|
+
|
|
179
|
+
self.rctRefreshCtrl = self.rctScrollView?.scrollView?.refreshControl
|
|
170
180
|
|
|
171
181
|
self.addCancelGestureRecognizers()
|
|
172
182
|
}
|
package/package.json
CHANGED