react-native-reanimated 4.7.0 → 4.7.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.
Files changed (41) hide show
  1. package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +34 -2
  2. package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +15 -1
  3. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +9 -0
  4. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
  5. package/Common/cpp/reanimated/Fabric/updates/SynchronousWritesTracker.cpp +103 -0
  6. package/Common/cpp/reanimated/Fabric/updates/SynchronousWritesTracker.h +74 -0
  7. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +15 -0
  8. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +5 -0
  9. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +10 -0
  10. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +3 -0
  11. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +97 -54
  12. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +5 -1
  13. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +23 -5
  14. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +17 -1
  15. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +9 -9
  16. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +35 -8
  17. package/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.h +2 -2
  18. package/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +11 -11
  19. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +75 -2
  20. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +11 -1
  21. package/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +4 -1
  22. package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +13 -3
  23. package/android/src/main/cpp/reanimated/android/NativeProxy.h +2 -0
  24. package/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt +84 -9
  25. package/android/src/main/java/com/swmansion/reanimated/NodesManager.kt +2 -4
  26. package/android/src/main/java/com/swmansion/reanimated/nativeProxy/EventHandler.kt +4 -3
  27. package/android/src/main/java/com/swmansion/reanimated/sensor/ReanimatedSensor.kt +1 -1
  28. package/android/src/main/java/com/swmansion/reanimated/sensor/ReanimatedSensorListener.kt +44 -33
  29. package/apple/reanimated/apple/REASynchronousPropsRewriter.h +18 -0
  30. package/apple/reanimated/apple/REASynchronousPropsRewriter.mm +37 -0
  31. package/apple/reanimated/apple/ReanimatedModule.mm +7 -0
  32. package/apple/reanimated/apple/keyboardObserver/REAKeyboardEventObserver.mm +20 -3
  33. package/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm +24 -1
  34. package/lib/module/animation/timing.js +15 -2
  35. package/lib/module/animation/timing.js.map +1 -1
  36. package/lib/module/platform-specific/jsVersion.js +1 -1
  37. package/lib/typescript/animation/timing.d.ts.map +1 -1
  38. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  39. package/package.json +3 -1
  40. package/src/animation/timing.ts +20 -2
  41. package/src/platform-specific/jsVersion.ts +1 -1
@@ -4,6 +4,7 @@ import android.hardware.Sensor
4
4
  import android.hardware.SensorEvent
5
5
  import android.hardware.SensorEventListener
6
6
  import android.hardware.SensorManager
7
+ import android.util.Log
7
8
  import android.view.Display
8
9
  import android.view.Surface
9
10
  import com.swmansion.reanimated.nativeProxy.SensorSetter
@@ -12,8 +13,10 @@ class ReanimatedSensorListener(
12
13
  private val setter: SensorSetter,
13
14
  private val interval: Double,
14
15
  private val display: Display,
16
+ private val sensorType: ReanimatedSensorType,
15
17
  ) : SensorEventListener {
16
18
  private var lastRead = System.currentTimeMillis().toDouble()
19
+ private var didWarnAboutMislabeledEvent = false
17
20
 
18
21
  private val rotation = FloatArray(9)
19
22
  private val orientation = FloatArray(3)
@@ -24,8 +27,8 @@ class ReanimatedSensorListener(
24
27
  if (current - lastRead < interval) {
25
28
  return
26
29
  }
27
- val sensorType = event.sensor.type
28
30
  lastRead = current
31
+ warnOnceAboutMislabeledEvent(event.sensor)
29
32
 
30
33
  val orientationDegrees =
31
34
  when (display.rotation) {
@@ -35,43 +38,51 @@ class ReanimatedSensorListener(
35
38
  else -> 0
36
39
  }
37
40
 
38
- when (sensorType) {
39
- Sensor.TYPE_ROTATION_VECTOR -> {
40
- SensorManager.getQuaternionFromVector(quaternion, event.values)
41
- SensorManager.getRotationMatrixFromVector(rotation, event.values)
42
- SensorManager.getOrientation(rotation, orientation)
43
- val data =
44
- floatArrayOf(
45
- quaternion[1], // qx
46
- quaternion[3], // qy -> we set qz to match iOS
47
- -quaternion[2], // qz -> we set -qy to match iOS
48
- quaternion[0], // qw
49
- // make Android consistent with iOS, which is better documented here:
50
- // https://developer.apple.com/documentation/coremotion/getting_processed_device-motion_data/
51
- -orientation[0], // yaw
52
- -orientation[1], // pitch
53
- orientation[2], // roll
54
- )
55
- setter.sensorSetter(data, orientationDegrees)
41
+ val values = event.values
42
+ val data =
43
+ when (sensorType) {
44
+ ReanimatedSensorType.ROTATION_VECTOR -> rotationData(values)
45
+ ReanimatedSensorType.GYROSCOPE,
46
+ ReanimatedSensorType.MAGNETIC_FIELD,
47
+ -> floatArrayOf(values[0], values[1], values[2])
48
+ ReanimatedSensorType.GRAVITY,
49
+ ReanimatedSensorType.ACCELEROMETER,
50
+ -> floatArrayOf(-values[0], -values[1], -values[2])
56
51
  }
57
- Sensor.TYPE_GYROSCOPE,
58
- Sensor.TYPE_MAGNETIC_FIELD,
59
- -> {
60
- val data = floatArrayOf(event.values[0], event.values[1], event.values[2])
61
- setter.sensorSetter(data, orientationDegrees)
62
- }
63
- Sensor.TYPE_GRAVITY,
64
- Sensor.TYPE_LINEAR_ACCELERATION,
65
- -> {
66
- val data = floatArrayOf(-event.values[0], -event.values[1], -event.values[2])
67
- setter.sensorSetter(data, orientationDegrees)
68
- }
69
- else -> throw IllegalArgumentException("[Reanimated] Unknown sensor type.")
70
- }
52
+ setter.sensorSetter(data, orientationDegrees)
71
53
  }
72
54
 
73
55
  override fun onAccuracyChanged(
74
56
  sensor: Sensor,
75
57
  accuracy: Int,
76
58
  ) {}
59
+
60
+ private fun warnOnceAboutMislabeledEvent(eventSensor: Sensor) {
61
+ if (didWarnAboutMislabeledEvent || eventSensor.type == sensorType.getType()) {
62
+ return
63
+ }
64
+ didWarnAboutMislabeledEvent = true
65
+ Log.w(
66
+ "Reanimated",
67
+ "Sensor $sensorType (type ${sensorType.getType()}) receives events from " +
68
+ "\"${eventSensor.name}\" (type ${eventSensor.type}).",
69
+ )
70
+ }
71
+
72
+ private fun rotationData(values: FloatArray): FloatArray {
73
+ SensorManager.getQuaternionFromVector(quaternion, values)
74
+ SensorManager.getRotationMatrixFromVector(rotation, values)
75
+ SensorManager.getOrientation(rotation, orientation)
76
+ return floatArrayOf(
77
+ quaternion[1], // qx
78
+ quaternion[3], // qy -> we set qz to match iOS
79
+ -quaternion[2], // qz -> we set -qy to match iOS
80
+ quaternion[0], // qw
81
+ // make Android consistent with iOS, which is better documented here:
82
+ // https://developer.apple.com/documentation/coremotion/getting_processed_device-motion_data/
83
+ -orientation[0], // yaw
84
+ -orientation[1], // pitch
85
+ orientation[2], // roll
86
+ )
87
+ }
77
88
  }
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #import <React/RCTSurfacePresenter.h>
4
+ #import <reanimated/NativeModules/ReanimatedModuleProxy.h>
5
+
6
+ #import <memory>
7
+
8
+ NS_ASSUME_NONNULL_BEGIN
9
+
10
+ @interface REASynchronousPropsRewriter : NSObject <RCTSurfacePresenterObserver>
11
+
12
+ - (instancetype)initWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter
13
+ reanimatedModuleProxy:
14
+ (const std::shared_ptr<reanimated::ReanimatedModuleProxy> &)reanimatedModuleProxy;
15
+
16
+ @end
17
+
18
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,37 @@
1
+ #import <reanimated/apple/REASynchronousPropsRewriter.h>
2
+
3
+ #import <React/RCTAssert.h>
4
+
5
+ @implementation REASynchronousPropsRewriter {
6
+ __weak RCTSurfacePresenter *_surfacePresenter;
7
+ std::weak_ptr<reanimated::ReanimatedModuleProxy> _reanimatedModuleProxy;
8
+ }
9
+
10
+ - (instancetype)initWithSurfacePresenter:(RCTSurfacePresenter *)surfacePresenter
11
+ reanimatedModuleProxy:
12
+ (const std::shared_ptr<reanimated::ReanimatedModuleProxy> &)reanimatedModuleProxy
13
+ {
14
+ if (self = [super init]) {
15
+ _surfacePresenter = surfacePresenter;
16
+ _reanimatedModuleProxy = reanimatedModuleProxy;
17
+ // `addObserver:` is deprecated, but its replacement has no hook for an external observer.
18
+ // See `REAPseudoSelectorAttachQueue`.
19
+ [surfacePresenter addObserver:self];
20
+ }
21
+ return self;
22
+ }
23
+
24
+ - (void)dealloc
25
+ {
26
+ [_surfacePresenter removeObserver:self];
27
+ }
28
+
29
+ - (void)didMountComponentsWithRootTag:(NSInteger)rootTag
30
+ {
31
+ RCTAssertMainQueue();
32
+ if (const auto reanimatedModuleProxy = _reanimatedModuleProxy.lock()) {
33
+ reanimatedModuleProxy->rewriteSynchronousProps();
34
+ }
35
+ }
36
+
37
+ @end
@@ -10,6 +10,7 @@
10
10
  #import <reanimated/apple/REAAssertJavaScriptQueue.h>
11
11
  #import <reanimated/apple/REAAssertTurboModuleManagerQueue.h>
12
12
  #import <reanimated/apple/REANodesManager.h>
13
+ #import <reanimated/apple/REASynchronousPropsRewriter.h>
13
14
  #import <reanimated/apple/ReanimatedModule.h>
14
15
  #import <reanimated/apple/native/NativeProxy.h>
15
16
  #import <reanimated/apple/native/REAJSIUtils.h>
@@ -25,6 +26,7 @@ using namespace worklets;
25
26
  @implementation ReanimatedModule {
26
27
  __weak RCTSurfacePresenter *_surfacePresenter;
27
28
  std::shared_ptr<ReanimatedModuleProxy> _reanimatedModuleProxy;
29
+ REASynchronousPropsRewriter *_synchronousPropsRewriter;
28
30
  #ifndef NDEBUG
29
31
  reanimated::SingleInstanceChecker<ReanimatedModule> singleInstanceChecker_;
30
32
  #endif // NDEBUG
@@ -41,6 +43,7 @@ RCT_EXPORT_MODULE(ReanimatedModule);
41
43
  REAAssertTurboModuleManagerQueue();
42
44
 
43
45
  [_nodesManager invalidate];
46
+ _synchronousPropsRewriter = nil;
44
47
  _reanimatedModuleProxy.reset();
45
48
  [super invalidate];
46
49
  }
@@ -184,6 +187,10 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(installTurboModule)
184
187
  const auto &uiManager = scheduler.uiManager;
185
188
  react_native_assert(uiManager.get() != nil);
186
189
  _reanimatedModuleProxy->initializeFabric(uiManager);
190
+ if (_reanimatedModuleProxy->hasSynchronousWritesTracker()) {
191
+ _synchronousPropsRewriter = [[REASynchronousPropsRewriter alloc] initWithSurfacePresenter:_surfacePresenter
192
+ reanimatedModuleProxy:_reanimatedModuleProxy];
193
+ }
187
194
  [self attachReactEventListener:_reanimatedModuleProxy];
188
195
  [self registerRCTEventHandler:_reanimatedModuleProxy uiWorkletRuntime:uiWorkletRuntime];
189
196
 
@@ -86,6 +86,23 @@ typedef NS_ENUM(NSUInteger, KeyboardState) { // NOLINT(performance-enum-size,cpp
86
86
 
87
87
  #else
88
88
 
89
+ static UIWindow *_Nullable REAFindKeyWindow(void)
90
+ {
91
+ // The window used to be read straight off the app delegate. Apps that adopt the UIScene
92
+ // life cycle own their window in a UISceneDelegate, so their app delegate may not declare
93
+ // `window` at all and messaging it raises NSInvalidArgumentException. Prefer the delegate
94
+ // when it is available so existing apps keep the exact same window, and otherwise fall back
95
+ // to the scene-aware lookup (cf. -[REATouchHoverCoordinator activeKeyWindow]).
96
+ id<UIApplicationDelegate> delegate = RCTSharedApplication().delegate;
97
+ if ([delegate respondsToSelector:@selector(window)]) {
98
+ UIWindow *window = delegate.window;
99
+ if (window != nil) {
100
+ return window;
101
+ }
102
+ }
103
+ return RCTKeyWindow();
104
+ }
105
+
89
106
  - (void)runListeners:(float)keyboardHeight
90
107
  {
91
108
  for (NSString *key in _listeners.allKeys) {
@@ -185,7 +202,7 @@ typedef NS_ENUM(NSUInteger, KeyboardState) { // NOLINT(performance-enum-size,cpp
185
202
  CGRect beginFrame = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
186
203
  CGRect endFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
187
204
  NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
188
- auto window = [[[UIApplication sharedApplication] delegate] window];
205
+ auto window = REAFindKeyWindow();
189
206
 
190
207
  /*
191
208
  The keyboard frame is in the screen's coordinate space and must first be converted
@@ -238,7 +255,7 @@ typedef NS_ENUM(NSUInteger, KeyboardState) { // NOLINT(performance-enum-size,cpp
238
255
  RCTExecuteOnMainQueue(^() {
239
256
  if (!self->_measuringView) {
240
257
  self->_measuringView = [[UIView alloc] initWithFrame:CGRectMake(0, -1, 0, 0)];
241
- UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];
258
+ UIWindow *keyWindow = REAFindKeyWindow();
242
259
  [keyWindow addSubview:self->_measuringView];
243
260
  }
244
261
  if ([self->_listeners count] == 0) {
@@ -301,7 +318,7 @@ typedef NS_ENUM(NSUInteger, KeyboardState) { // NOLINT(performance-enum-size,cpp
301
318
  {
302
319
  [[self getDisplayLink] setPaused:YES];
303
320
 
304
- auto window = [[[UIApplication sharedApplication] delegate] window];
321
+ auto window = REAFindKeyWindow();
305
322
  auto keyboardView = [self getKeyboardView];
306
323
  if (keyboardView) {
307
324
  CGRect frameIntersection = CGRectIntersection(window.bounds, keyboardView.frame);
@@ -12,9 +12,11 @@
12
12
  #import <reanimated/apple/pseudoSelectors/REAPseudoSelectorAttachQueue.h>
13
13
  #import <reanimated/apple/sensor/ReanimatedSensorContainer.h>
14
14
 
15
+ #import <React/RCTAssert.h>
15
16
  #import <React/RCTComponentViewProtocol.h>
16
17
  #import <React/RCTComponentViewRegistry.h>
17
18
  #import <React/RCTMountingManager.h>
19
+ #import <React/RCTViewComponentView.h>
18
20
 
19
21
  #import <memory>
20
22
  #import <variant>
@@ -194,18 +196,36 @@ std::shared_ptr<css::CSSPlatformTransitionBackend> makePlatformTransitionBackend
194
196
 
195
197
  ForceScreenSnapshotFunction makeForceScreenSnapshotFunction(REANodesManager *nodesManager)
196
198
  {
197
- auto forceScreenSnapshot = [=](Tag tag) {
199
+ auto forceScreenSnapshot = [=](Tag tag) -> bool {
198
200
  RCTSurfacePresenter *surfacePresenter = nodesManager.surfacePresenter;
199
201
  RCTComponentViewRegistry *componentViewRegistry = surfacePresenter.mountingManager.componentViewRegistry;
200
202
  REAUIView<RCTComponentViewProtocol> *maybeRNSScreenView = [componentViewRegistry findComponentViewWithTag:tag];
201
203
  SEL setSnapshotAfterUpdatesSelector = @selector(setSnapshotAfterUpdates:);
202
204
  if ([maybeRNSScreenView respondsToSelector:setSnapshotAfterUpdatesSelector]) {
203
205
  [static_cast<id<RNScreenViewOptionalProtocol>>(maybeRNSScreenView) setSnapshotAfterUpdates:YES];
206
+ return true;
204
207
  }
208
+ return false;
205
209
  };
206
210
  return forceScreenSnapshot;
207
211
  }
208
212
 
213
+ ReadMountedViewPropsFunction makeReadMountedViewPropsFunction(REANodesManager *nodesManager)
214
+ {
215
+ auto readMountedViewProps = [=](Tag tag) -> Props::Shared {
216
+ RCTAssertMainQueue();
217
+ RCTSurfacePresenter *surfacePresenter = nodesManager.surfacePresenter;
218
+ RCTComponentViewRegistry *componentViewRegistry = surfacePresenter.mountingManager.componentViewRegistry;
219
+ REAUIView<RCTComponentViewProtocol> *componentView = [componentViewRegistry findComponentViewWithTag:tag];
220
+ // The default `props` getter of `UIView` asserts.
221
+ if (![componentView isKindOfClass:[RCTViewComponentView class]]) {
222
+ return nullptr;
223
+ }
224
+ return [componentView props];
225
+ };
226
+ return readMountedViewProps;
227
+ }
228
+
209
229
  PlatformAttachPseudoSelectorFunction makeAttachPseudoSelectorFunction(REAPseudoSelectorAttachQueue *attachQueue)
210
230
  {
211
231
  return [attachQueue](Tag tag, PseudoSelector selector, std::function<void(bool)> callback) {
@@ -228,6 +248,8 @@ PlatformDepMethodsHolder makePlatformDepMethodsHolder(RCTModuleRegistry *moduleR
228
248
 
229
249
  auto forceScreenSnapshotFunction = makeForceScreenSnapshotFunction(nodesManager);
230
250
 
251
+ auto readMountedViewPropsFunction = makeReadMountedViewPropsFunction(nodesManager);
252
+
231
253
  auto synchronouslyUpdateUIPropsFunction = makeSynchronouslyUpdateUIPropsFunction(nodesManager);
232
254
 
233
255
  auto getAnimationTimestamp = makeGetAnimationTimestamp();
@@ -258,6 +280,7 @@ PlatformDepMethodsHolder makePlatformDepMethodsHolder(RCTModuleRegistry *moduleR
258
280
  PlatformDepMethodsHolder platformDepMethodsHolder = {
259
281
  requestRender,
260
282
  forceScreenSnapshotFunction,
283
+ readMountedViewPropsFunction,
261
284
  synchronouslyUpdateUIPropsFunction,
262
285
  getAnimationTimestamp,
263
286
  registerSensorFunction,
@@ -56,14 +56,27 @@ export const withTiming = function (toValue, userConfig, callback) {
56
56
  startTime,
57
57
  startValue
58
58
  } = animation;
59
- const runtime = now - startTime;
59
+ let runtime = now - startTime;
60
+ if (runtime < 0) {
61
+ // `startTime` comes from `global.__frameTimestamp ||
62
+ // global._getAnimationTimestamp()` (see `valueSetter`). An animation
63
+ // started outside a frame flush - from a gesture callback, for
64
+ // instance - takes the second branch and reads the clock at that
65
+ // instant, while the frame that first progresses it passes its vsync
66
+ // timestamp, which is earlier. The first tick then sees a small
67
+ // negative runtime. This can potentially cause glitches during
68
+ // animations.
69
+ animation.startTime = now;
70
+ runtime = 0;
71
+ }
60
72
  if (runtime >= config.duration) {
61
73
  // reset startTime to avoid reusing finished animation config in `start` method
62
74
  animation.startTime = 0;
63
75
  animation.current = toValue;
64
76
  return true;
65
77
  }
66
- const progress = animation.easing(runtime / config.duration);
78
+ const normalizedTime = Math.min(Math.max(runtime / config.duration, 0), 1);
79
+ const progress = animation.easing(normalizedTime);
67
80
  animation.current = startValue + (toValue - startValue) * progress;
68
81
  return false;
69
82
  }
@@ -1 +1 @@
1
- {"version":3,"names":["Easing","assertEasingIsWorklet","defineAnimation","getReduceMotionForAnimation","withTiming","toValue","userConfig","callback","__DEV__","easing","config","duration","inOut","quad","Object","keys","forEach","key","timing","animation","now","startTime","startValue","runtime","current","progress","onStart","value","previousAnimation","type","factory","onFrame","reduceMotion"],"sourceRoot":"../../../src","sources":["animation/timing.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["Easing","assertEasingIsWorklet","defineAnimation","getReduceMotionForAnimation","withTiming","toValue","userConfig","callback","__DEV__","easing","config","duration","inOut","quad","Object","keys","forEach","key","timing","animation","now","startTime","startValue","runtime","current","normalizedTime","Math","min","max","progress","onStart","value","previousAnimation","type","factory","onFrame","reduceMotion"],"sourceRoot":"../../../src","sources":["animation/timing.ts"],"mappings":"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","ignoreList":[]}
@@ -5,5 +5,5 @@
5
5
  * version used to build the native part of the library in runtime. Remember to
6
6
  * keep this in sync with the version declared in `package.json`
7
7
  */
8
- export const jsVersion = '4.7.0';
8
+ export const jsVersion = '4.7.1';
9
9
  //# sourceMappingURL=jsVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../../src/animation/timing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,SAAS,EACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAQvD;;;;;;;;;;GAUG;AACH,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,CAAC,EAAE,cAAc,GAAG,qBAAqB,CAAC;CACjD;AAED,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAE5C,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,eAAe,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAWD,KAAK,cAAc,GAAG,CAAC,CAAC,SAAS,eAAe,EAC9C,OAAO,EAAE,CAAC,EACV,UAAU,CAAC,EAAE,YAAY,EACzB,QAAQ,CAAC,EAAE,iBAAiB,KACzB,CAAC,CAAC;AAEP;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU,EAuFlB,cAAc,CAAC"}
1
+ {"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../../src/animation/timing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,SAAS,EACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAQvD;;;;;;;;;;GAUG;AACH,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,CAAC,EAAE,cAAc,GAAG,qBAAqB,CAAC;CACjD;AAED,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAE5C,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,eAAe,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,eAAe,CAAC;IAC5B,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,eAAe,CAAC;CAC1B;AAWD,KAAK,cAAc,GAAG,CAAC,CAAC,SAAS,eAAe,EAC9C,OAAO,EAAE,CAAC,EACV,UAAU,CAAC,EAAE,YAAY,EACzB,QAAQ,CAAC,EAAE,iBAAiB,KACzB,CAAC,CAAC;AAEP;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,UAAU,EAyGlB,cAAc,CAAC"}
@@ -3,5 +3,5 @@
3
3
  * version used to build the native part of the library in runtime. Remember to
4
4
  * keep this in sync with the version declared in `package.json`
5
5
  */
6
- export declare const jsVersion = "4.7.0";
6
+ export declare const jsVersion = "4.7.1";
7
7
  //# sourceMappingURL=jsVersion.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-reanimated",
3
- "version": "4.7.0",
3
+ "version": "4.7.1",
4
4
  "description": "More powerful alternative to Animated library for React Native.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -9,6 +9,8 @@
9
9
  "reanimated"
10
10
  ],
11
11
  "scripts": {
12
+ "changelog:add": "node --experimental-strip-types ../../scripts/changelog/add.mts",
13
+ "changelog:squash": "node --experimental-strip-types ../../scripts/changelog/squash.mts",
12
14
  "test": "yarn run --top-level jest",
13
15
  "lint": "yarn lint:js && yarn lint:android && yarn lint:apple && yarn lint:clang-tidy",
14
16
  "lint:js": "eslint src __tests__ __typetests__ && yarn run --top-level oxfmt --check src __tests__ __typetests__ && yarn validate-mock",
@@ -101,7 +101,20 @@ export const withTiming = function (
101
101
  function timing(animation: InnerTimingAnimation, now: Timestamp): boolean {
102
102
  // eslint-disable-next-line @typescript-eslint/no-shadow
103
103
  const { toValue, startTime, startValue } = animation;
104
- const runtime = now - startTime;
104
+ let runtime = now - startTime;
105
+
106
+ if (runtime < 0) {
107
+ // `startTime` comes from `global.__frameTimestamp ||
108
+ // global._getAnimationTimestamp()` (see `valueSetter`). An animation
109
+ // started outside a frame flush - from a gesture callback, for
110
+ // instance - takes the second branch and reads the clock at that
111
+ // instant, while the frame that first progresses it passes its vsync
112
+ // timestamp, which is earlier. The first tick then sees a small
113
+ // negative runtime. This can potentially cause glitches during
114
+ // animations.
115
+ animation.startTime = now;
116
+ runtime = 0;
117
+ }
105
118
 
106
119
  if (runtime >= config.duration) {
107
120
  // reset startTime to avoid reusing finished animation config in `start` method
@@ -109,7 +122,12 @@ export const withTiming = function (
109
122
  animation.current = toValue;
110
123
  return true;
111
124
  }
112
- const progress = animation.easing(runtime / config.duration);
125
+
126
+ const normalizedTime = Math.min(
127
+ Math.max(runtime / config.duration, 0),
128
+ 1
129
+ );
130
+ const progress = animation.easing(normalizedTime);
113
131
  animation.current =
114
132
  (startValue as number) + (toValue - (startValue as number)) * progress;
115
133
  return false;
@@ -4,4 +4,4 @@
4
4
  * version used to build the native part of the library in runtime. Remember to
5
5
  * keep this in sync with the version declared in `package.json`
6
6
  */
7
- export const jsVersion = '4.7.0';
7
+ export const jsVersion = '4.7.1';