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.
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +34 -2
- package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +15 -1
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +9 -0
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
- package/Common/cpp/reanimated/Fabric/updates/SynchronousWritesTracker.cpp +103 -0
- package/Common/cpp/reanimated/Fabric/updates/SynchronousWritesTracker.h +74 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +15 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +5 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +10 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +3 -0
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +97 -54
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +5 -1
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +23 -5
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +17 -1
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +9 -9
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +35 -8
- package/Common/cpp/reanimated/LayoutAnimations/PropsDiffer.h +2 -2
- package/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +11 -11
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +75 -2
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +11 -1
- package/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +4 -1
- package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +13 -3
- package/android/src/main/cpp/reanimated/android/NativeProxy.h +2 -0
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt +84 -9
- package/android/src/main/java/com/swmansion/reanimated/NodesManager.kt +2 -4
- package/android/src/main/java/com/swmansion/reanimated/nativeProxy/EventHandler.kt +4 -3
- package/android/src/main/java/com/swmansion/reanimated/sensor/ReanimatedSensor.kt +1 -1
- package/android/src/main/java/com/swmansion/reanimated/sensor/ReanimatedSensorListener.kt +44 -33
- package/apple/reanimated/apple/REASynchronousPropsRewriter.h +18 -0
- package/apple/reanimated/apple/REASynchronousPropsRewriter.mm +37 -0
- package/apple/reanimated/apple/ReanimatedModule.mm +7 -0
- package/apple/reanimated/apple/keyboardObserver/REAKeyboardEventObserver.mm +20 -3
- package/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm +24 -1
- package/lib/module/animation/timing.js +15 -2
- package/lib/module/animation/timing.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/typescript/animation/timing.d.ts.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/package.json +3 -1
- package/src/animation/timing.ts +20 -2
- 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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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":"AAAA,YAAY;;AAUZ,SAASA,MAAM,QAAQ,cAAW;AAClC,SACEC,qBAAqB,EACrBC,eAAe,EACfC,2BAA2B,QACtB,QAAQ;;AAEf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA2BA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,GAAG,SAAAA,CACxBC,OAAwB,EACxBC,UAAyB,EACzBC,QAA4B,EACA;EAC5B,SAAS;;EAET,IAAIC,OAAO,IAAIF,UAAU,EAAEG,MAAM,EAAE;IACjCR,qBAAqB,CAACK,UAAU,CAACG,MAAM,CAAC;EAC1C;EAEA,OAAOP,eAAe,CAAkBG,OAAO,EAAE,MAAM;IACrD,SAAS;;IACT,MAAMK,MAAoD,GAAG;MAC3DC,QAAQ,EAAE,GAAG;MACbF,MAAM,EAAET,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC;IACD,IAAIP,UAAU,EAAE;MACdQ,MAAM,CAACC,IAAI,CAACT,UAAU,CAAC,CAACU,OAAO,CAC5BC,GAAG;MACF;MACEP,MAAM,CAASO,GAAG,CAAC,GAAGX,UAAU,CAACW,GAAG,CAC1C,CAAC;IACH;IAEA,SAASC,MAAMA,CAACC,SAA+B,EAAEC,GAAc,EAAW;MACxE;MACA,MAAM;QAAEf,OAAO;QAAEgB,SAAS;QAAEC;MAAW,CAAC,GAAGH,SAAS;MACpD,
|
|
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":[]}
|
|
@@ -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,
|
|
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.
|
|
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.
|
|
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",
|
package/src/animation/timing.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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;
|