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
- // Trigger refresh control programmatically
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
- if velocity > 0 {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-scroll-forwarder",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Forward scroll gestures from any view to a ScrollView in React Native and Expo.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",