react-native-reanimated 4.2.2 → 4.2.3
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/updates/UpdatesRegistry.cpp +12 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +1 -0
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +463 -416
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +3 -1
- package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +7 -2
- package/android/src/main/cpp/reanimated/android/NativeProxy.h +2 -1
- package/android/src/main/java/com/swmansion/reanimated/DrawPassDetector.java +82 -0
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +4 -2
- package/android/src/main/java/com/swmansion/reanimated/NodesManager.java +32 -4
- package/apple/reanimated/apple/native/NativeProxy.mm +1 -1
- package/compatibility.json +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/package.json +8 -7
- package/scripts/worklets-version.json +1 -4
- package/src/platform-specific/jsVersion.ts +1 -1
|
@@ -99,7 +99,8 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec,
|
|
|
99
99
|
void maybeRunCSSLoop();
|
|
100
100
|
double getCssTimestamp();
|
|
101
101
|
|
|
102
|
-
void performOperations(
|
|
102
|
+
void performOperations();
|
|
103
|
+
void performNonLayoutOperations();
|
|
103
104
|
|
|
104
105
|
void setViewStyle(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &viewStyle) override;
|
|
105
106
|
|
|
@@ -179,6 +180,7 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec,
|
|
|
179
180
|
|
|
180
181
|
private:
|
|
181
182
|
void commitUpdates(jsi::Runtime &rt, const UpdatesBatch &updatesBatch);
|
|
183
|
+
void applySynchronousUpdates(UpdatesBatch &updatesBatch, bool allowPartialUpdates = false);
|
|
182
184
|
|
|
183
185
|
const bool isReducedMotion_;
|
|
184
186
|
bool shouldFlushRegistry_ = false;
|
|
@@ -112,8 +112,12 @@ bool NativeProxy::isAnyHandlerWaitingForEvent(const std::string &eventName, cons
|
|
|
112
112
|
return reanimatedModuleProxy_->isAnyHandlerWaitingForEvent(eventName, emitterReactTag);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
void NativeProxy::performOperations(
|
|
116
|
-
reanimatedModuleProxy_->performOperations(
|
|
115
|
+
void NativeProxy::performOperations() {
|
|
116
|
+
reanimatedModuleProxy_->performOperations();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void NativeProxy::performNonLayoutOperations() {
|
|
120
|
+
reanimatedModuleProxy_->performNonLayoutOperations();
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
bool NativeProxy::getIsReducedMotion() {
|
|
@@ -127,6 +131,7 @@ void NativeProxy::registerNatives() {
|
|
|
127
131
|
makeNativeMethod("installJSIBindings", NativeProxy::installJSIBindings),
|
|
128
132
|
makeNativeMethod("isAnyHandlerWaitingForEvent", NativeProxy::isAnyHandlerWaitingForEvent),
|
|
129
133
|
makeNativeMethod("performOperations", NativeProxy::performOperations),
|
|
134
|
+
makeNativeMethod("performNonLayoutOperations", NativeProxy::performNonLayoutOperations),
|
|
130
135
|
makeNativeMethod("invalidateCpp", NativeProxy::invalidateCpp)});
|
|
131
136
|
}
|
|
132
137
|
|
|
@@ -55,7 +55,8 @@ class NativeProxy : public jni::HybridClass<NativeProxy>, std::enable_shared_fro
|
|
|
55
55
|
|
|
56
56
|
double getAnimationTimestamp();
|
|
57
57
|
bool isAnyHandlerWaitingForEvent(const std::string &eventName, const int emitterReactTag);
|
|
58
|
-
void performOperations(
|
|
58
|
+
void performOperations();
|
|
59
|
+
void performNonLayoutOperations();
|
|
59
60
|
bool getIsReducedMotion();
|
|
60
61
|
void requestRender(std::function<void(double)> onRender);
|
|
61
62
|
void registerEventHandler();
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package com.swmansion.reanimated;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.os.Handler;
|
|
5
|
+
import android.os.Looper;
|
|
6
|
+
import android.view.View;
|
|
7
|
+
import android.view.ViewTreeObserver;
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
9
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
10
|
+
import javax.annotation.Nullable;
|
|
11
|
+
|
|
12
|
+
/** Tracks whether the current UI thread turn is inside a draw pass. */
|
|
13
|
+
class DrawPassDetector {
|
|
14
|
+
private final ReactApplicationContext mContext;
|
|
15
|
+
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
|
16
|
+
private final Runnable mClearRunnable = () -> mIsInDrawPass = false;
|
|
17
|
+
private boolean mIsInDrawPass = false;
|
|
18
|
+
@Nullable private View mDecorView = null;
|
|
19
|
+
|
|
20
|
+
private final ViewTreeObserver.OnDrawListener mOnDrawListener =
|
|
21
|
+
() -> {
|
|
22
|
+
mIsInDrawPass = true;
|
|
23
|
+
mHandler.postAtFrontOfQueue(mClearRunnable);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
DrawPassDetector(ReactApplicationContext context) {
|
|
27
|
+
mContext = context;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void initialize() {
|
|
31
|
+
Activity activity = mContext.getCurrentActivity();
|
|
32
|
+
if (activity == null) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
View decorView = activity.getWindow().getDecorView();
|
|
37
|
+
if (decorView == mDecorView) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Decor view has changed (e.g. Activity recreated) — detach from the old one first.
|
|
42
|
+
if (mDecorView != null) {
|
|
43
|
+
ViewTreeObserver oldObserver = mDecorView.getViewTreeObserver();
|
|
44
|
+
if (oldObserver.isAlive()) {
|
|
45
|
+
oldObserver.removeOnDrawListener(mOnDrawListener);
|
|
46
|
+
}
|
|
47
|
+
mDecorView = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ViewTreeObserver observer = decorView.getViewTreeObserver();
|
|
51
|
+
if (!observer.isAlive()) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
mDecorView = decorView;
|
|
56
|
+
observer.addOnDrawListener(mOnDrawListener);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
boolean isInDrawPass() {
|
|
60
|
+
return mIsInDrawPass;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void invalidate() {
|
|
64
|
+
if (UiThreadUtil.isOnUiThread()) {
|
|
65
|
+
invalidateOnUiThread();
|
|
66
|
+
} else {
|
|
67
|
+
mHandler.post(this::invalidateOnUiThread);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private void invalidateOnUiThread() {
|
|
72
|
+
if (mDecorView != null) {
|
|
73
|
+
ViewTreeObserver observer = mDecorView.getViewTreeObserver();
|
|
74
|
+
if (observer.isAlive()) {
|
|
75
|
+
observer.removeOnDrawListener(mOnDrawListener);
|
|
76
|
+
}
|
|
77
|
+
mDecorView = null;
|
|
78
|
+
}
|
|
79
|
+
mHandler.removeCallbacks(mClearRunnable);
|
|
80
|
+
mIsInDrawPass = false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -110,7 +110,9 @@ public class NativeProxy {
|
|
|
110
110
|
|
|
111
111
|
public native boolean isAnyHandlerWaitingForEvent(String eventName, int emitterReactTag);
|
|
112
112
|
|
|
113
|
-
public native void performOperations(
|
|
113
|
+
public native void performOperations();
|
|
114
|
+
|
|
115
|
+
public native void performNonLayoutOperations();
|
|
114
116
|
|
|
115
117
|
protected native void installJSIBindings();
|
|
116
118
|
|
|
@@ -503,7 +505,7 @@ public class NativeProxy {
|
|
|
503
505
|
void maybeFlushUIUpdatesQueue() {
|
|
504
506
|
UiThreadUtil.assertOnUiThread();
|
|
505
507
|
if (!mNodesManager.isAnimationRunning()) {
|
|
506
|
-
mNodesManager.
|
|
508
|
+
mNodesManager.performOperationsRespectingDrawPass();
|
|
507
509
|
}
|
|
508
510
|
}
|
|
509
511
|
}
|
|
@@ -44,6 +44,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
44
44
|
private ConcurrentLinkedQueue<CopiedEvent> mEventQueue = new ConcurrentLinkedQueue<>();
|
|
45
45
|
private double lastFrameTimeMs;
|
|
46
46
|
private FabricUIManager mFabricUIManager;
|
|
47
|
+
private final DrawPassDetector mDrawPassDetector;
|
|
47
48
|
|
|
48
49
|
public NativeProxy getNativeProxy() {
|
|
49
50
|
return mNativeProxy;
|
|
@@ -57,6 +58,8 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
57
58
|
mNativeProxy = null;
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
mDrawPassDetector.invalidate();
|
|
62
|
+
|
|
60
63
|
if (mFabricUIManager != null) {
|
|
61
64
|
mFabricUIManager.getEventDispatcher().removeListener(this);
|
|
62
65
|
}
|
|
@@ -69,6 +72,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
69
72
|
assert uiManager != null;
|
|
70
73
|
mCustomEventNamesResolver = uiManager::resolveCustomDirectEventName;
|
|
71
74
|
mEventEmitter = context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
|
|
75
|
+
mDrawPassDetector = new DrawPassDetector(context);
|
|
72
76
|
|
|
73
77
|
mReactChoreographer = ReactChoreographer.getInstance();
|
|
74
78
|
mChoreographerCallback =
|
|
@@ -115,11 +119,33 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
|
|
118
|
-
public void performOperations(
|
|
122
|
+
public void performOperations() {
|
|
119
123
|
UiThreadUtil.assertOnUiThread();
|
|
120
124
|
if (mNativeProxy != null) {
|
|
121
|
-
mNativeProxy.performOperations(
|
|
125
|
+
mNativeProxy.performOperations();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
void performNonLayoutOperations() {
|
|
130
|
+
UiThreadUtil.assertOnUiThread();
|
|
131
|
+
if (mNativeProxy != null) {
|
|
132
|
+
mNativeProxy.performNonLayoutOperations();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void performOperationsRespectingDrawPass() {
|
|
137
|
+
mDrawPassDetector.initialize();
|
|
138
|
+
if (isInDrawPass()) {
|
|
139
|
+
performNonLayoutOperations();
|
|
140
|
+
startUpdatingOnAnimationFrame();
|
|
141
|
+
return;
|
|
122
142
|
}
|
|
143
|
+
|
|
144
|
+
performOperations();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
boolean isInDrawPass() {
|
|
148
|
+
return mDrawPassDetector.isInDrawPass();
|
|
123
149
|
}
|
|
124
150
|
|
|
125
151
|
private void onAnimationFrame(long frameTimeNanos) {
|
|
@@ -130,6 +156,8 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
130
156
|
Trace.beginSection("onAnimationFrame");
|
|
131
157
|
}
|
|
132
158
|
|
|
159
|
+
mDrawPassDetector.initialize();
|
|
160
|
+
|
|
133
161
|
double currentFrameTimeMs = frameTimeNanos / 1000000.;
|
|
134
162
|
if (mSlowAnimationsEnabled) {
|
|
135
163
|
currentFrameTimeMs =
|
|
@@ -155,7 +183,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
155
183
|
}
|
|
156
184
|
}
|
|
157
185
|
|
|
158
|
-
performOperations(
|
|
186
|
+
performOperations();
|
|
159
187
|
}
|
|
160
188
|
|
|
161
189
|
mCallbackPosted.set(false);
|
|
@@ -189,7 +217,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
189
217
|
// the UI thread.
|
|
190
218
|
if (UiThreadUtil.isOnUiThread()) {
|
|
191
219
|
handleEvent(event);
|
|
192
|
-
|
|
220
|
+
performOperationsRespectingDrawPass();
|
|
193
221
|
} else {
|
|
194
222
|
String eventName = mCustomEventNamesResolver.resolveCustomEventName(event.getEventName());
|
|
195
223
|
int viewTag = event.getViewTag();
|
|
@@ -46,7 +46,7 @@ std::shared_ptr<ReanimatedModuleProxy> createReanimatedModuleProxy(
|
|
|
46
46
|
std::weak_ptr<ReanimatedModuleProxy> weakReanimatedModuleProxy = reanimatedModuleProxy; // to avoid retain cycle
|
|
47
47
|
[nodesManager registerPerformOperations:^() {
|
|
48
48
|
if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) {
|
|
49
|
-
reanimatedModuleProxy->performOperations(
|
|
49
|
+
reanimatedModuleProxy->performOperations();
|
|
50
50
|
}
|
|
51
51
|
}];
|
|
52
52
|
|
package/compatibility.json
CHANGED
|
@@ -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.2.
|
|
6
|
+
export declare const jsVersion = "4.2.3";
|
|
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.2.
|
|
3
|
+
"version": "4.2.3",
|
|
4
4
|
"description": "More powerful alternative to Animated library for React Native.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"build": "yarn workspace react-native-worklets build && bob build",
|
|
38
38
|
"circular-dependency-check": "yarn madge --extensions js,jsx --circular lib",
|
|
39
39
|
"prepack": "cp ../../README.md ./README.md",
|
|
40
|
-
"postpack": "rm ./README.md"
|
|
40
|
+
"postpack": "rm ./README.md",
|
|
41
|
+
"validate-peers": "node ../../scripts/validate-compatibility-peer-dependencies.js"
|
|
41
42
|
},
|
|
42
43
|
"main": "lib/module/index",
|
|
43
44
|
"module": "lib/module/index",
|
|
@@ -92,13 +93,13 @@
|
|
|
92
93
|
},
|
|
93
94
|
"homepage": "https://docs.swmansion.com/react-native-reanimated",
|
|
94
95
|
"dependencies": {
|
|
95
|
-
"react-native-is-edge-to-edge": "1.2.1",
|
|
96
|
-
"semver": "7.7.3"
|
|
96
|
+
"react-native-is-edge-to-edge": "^1.2.1",
|
|
97
|
+
"semver": "^7.7.3"
|
|
97
98
|
},
|
|
98
99
|
"peerDependencies": {
|
|
99
100
|
"react": "*",
|
|
100
|
-
"react-native": "
|
|
101
|
-
"react-native-worklets": "
|
|
101
|
+
"react-native": "0.80 - 0.84",
|
|
102
|
+
"react-native-worklets": "0.7 - 0.8"
|
|
102
103
|
},
|
|
103
104
|
"devDependencies": {
|
|
104
105
|
"@babel/core": "7.28.4",
|
|
@@ -132,7 +133,7 @@
|
|
|
132
133
|
"react-native-builder-bob": "0.40.13",
|
|
133
134
|
"react-native-svg": "15.14.0",
|
|
134
135
|
"react-native-web": "0.21.1",
|
|
135
|
-
"react-native-worklets": "0.8.0
|
|
136
|
+
"react-native-worklets": "0.8.0",
|
|
136
137
|
"react-test-renderer": "19.2.3",
|
|
137
138
|
"typescript": "5.8.3"
|
|
138
139
|
},
|