react-native 0.81.3 → 0.81.5
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/Libraries/Core/ReactNativeVersion.js +1 -1
- package/React/Base/RCTUtils.mm +5 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/CoreModules/RCTDeviceInfo.mm +3 -4
- package/React/Views/RCTSwitchManager.m +24 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +25 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt +2 -2
- package/ReactAndroid/src/main/jni/react/jni/TransformHelper.cpp +3 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
- package/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +0 -3
- package/ReactCommon/react/renderer/components/view/tests/ResolveTransformTest.cpp +377 -0
- package/package.json +8 -8
- package/scripts/cocoapods/autolinking.rb +6 -0
- package/scripts/cocoapods/codegen_utils.rb +1 -1
- package/scripts/codegen/generate-artifacts-executor/index.js +5 -6
- package/scripts/codegen/generate-artifacts-executor/utils.js +41 -10
- package/sdks/hermesc/osx-bin/hermes +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/third-party-podspecs/ReactNativeDependencies.podspec +1 -1
package/React/Base/RCTUtils.mm
CHANGED
|
@@ -432,7 +432,11 @@ CGSize RCTSwitchSize(void)
|
|
|
432
432
|
static dispatch_once_t onceToken;
|
|
433
433
|
dispatch_once(&onceToken, ^{
|
|
434
434
|
RCTUnsafeExecuteOnMainQueueSync(^{
|
|
435
|
-
|
|
435
|
+
CGSize switchSize = [UISwitch new].intrinsicContentSize;
|
|
436
|
+
// Apple does not take into account the thumb border when returning the
|
|
437
|
+
// width of the UISwitch component, so we are adding 2 pixels for the border
|
|
438
|
+
// which is not customizable and it is the same for legacy and liquid glass.
|
|
439
|
+
rctSwitchSize = CGSizeMake(switchSize.width + 2, switchSize.height);
|
|
436
440
|
});
|
|
437
441
|
});
|
|
438
442
|
return rctSwitchSize;
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -238,11 +238,10 @@ static NSDictionary *RCTExportedDimensions(CGFloat fontScale)
|
|
|
238
238
|
- (void)interfaceOrientationDidChange
|
|
239
239
|
{
|
|
240
240
|
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
|
|
241
|
-
|
|
242
|
-
UIInterfaceOrientation nextOrientation =
|
|
241
|
+
UIWindow *window = RCTKeyWindow();
|
|
242
|
+
UIInterfaceOrientation nextOrientation = window.windowScene.interfaceOrientation;
|
|
243
243
|
|
|
244
|
-
BOOL isRunningInFullScreen =
|
|
245
|
-
CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds);
|
|
244
|
+
BOOL isRunningInFullScreen = window ? CGRectEqualToRect(window.frame, window.screen.bounds) : YES;
|
|
246
245
|
// We are catching here two situations for multitasking view:
|
|
247
246
|
// a) The app is in Split View and the container gets resized -> !isRunningInFullScreen
|
|
248
247
|
// b) The app changes to/from fullscreen example: App runs in slide over mode and goes into fullscreen->
|
|
@@ -8,10 +8,29 @@
|
|
|
8
8
|
#import "RCTSwitchManager.h"
|
|
9
9
|
|
|
10
10
|
#import <React/RCTUIManager.h>
|
|
11
|
+
#import <React/RCTUtils.h>
|
|
11
12
|
#import "RCTBridge.h"
|
|
13
|
+
#import "RCTShadowView.h"
|
|
12
14
|
#import "RCTSwitch.h"
|
|
13
15
|
#import "UIView+React.h"
|
|
14
16
|
|
|
17
|
+
@interface RCTSwitchShadowView : RCTShadowView
|
|
18
|
+
|
|
19
|
+
@end
|
|
20
|
+
|
|
21
|
+
@implementation RCTSwitchShadowView
|
|
22
|
+
|
|
23
|
+
- (instancetype)init
|
|
24
|
+
{
|
|
25
|
+
if (self = [super init]) {
|
|
26
|
+
self.intrinsicContentSize = RCTSwitchSize();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return self;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@end
|
|
33
|
+
|
|
15
34
|
@implementation RCTSwitchManager
|
|
16
35
|
|
|
17
36
|
RCT_EXPORT_MODULE()
|
|
@@ -33,6 +52,11 @@ RCT_EXPORT_MODULE()
|
|
|
33
52
|
}
|
|
34
53
|
}
|
|
35
54
|
|
|
55
|
+
- (RCTShadowView *)shadowView
|
|
56
|
+
{
|
|
57
|
+
return [RCTSwitchShadowView new];
|
|
58
|
+
}
|
|
59
|
+
|
|
36
60
|
RCT_EXPORT_METHOD(setValue : (nonnull NSNumber *)viewTag toValue : (BOOL)value)
|
|
37
61
|
{
|
|
38
62
|
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
@@ -21,6 +21,7 @@ import com.facebook.infer.annotation.Assertions;
|
|
|
21
21
|
import com.facebook.infer.annotation.Nullsafe;
|
|
22
22
|
import com.facebook.react.bridge.Callback;
|
|
23
23
|
import com.facebook.react.bridge.ReactContext;
|
|
24
|
+
import com.facebook.react.common.LifecycleState;
|
|
24
25
|
import com.facebook.react.interfaces.fabric.ReactSurface;
|
|
25
26
|
import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags;
|
|
26
27
|
import com.facebook.react.modules.core.PermissionListener;
|
|
@@ -247,7 +248,7 @@ public class ReactActivityDelegate {
|
|
|
247
248
|
|
|
248
249
|
public void onRequestPermissionsResult(
|
|
249
250
|
final int requestCode, final String[] permissions, final int[] grantResults) {
|
|
250
|
-
|
|
251
|
+
Callback permissionsCallback =
|
|
251
252
|
args -> {
|
|
252
253
|
if (mPermissionListener != null
|
|
253
254
|
&& mPermissionListener.onRequestPermissionsResult(
|
|
@@ -255,6 +256,29 @@ public class ReactActivityDelegate {
|
|
|
255
256
|
mPermissionListener = null;
|
|
256
257
|
}
|
|
257
258
|
};
|
|
259
|
+
|
|
260
|
+
LifecycleState lifecycle;
|
|
261
|
+
if (isFabricEnabled()) {
|
|
262
|
+
ReactHost reactHost = getReactHost();
|
|
263
|
+
lifecycle = reactHost != null ? reactHost.getLifecycleState() : LifecycleState.BEFORE_CREATE;
|
|
264
|
+
} else {
|
|
265
|
+
ReactNativeHost reactNativeHost = getReactNativeHost();
|
|
266
|
+
if (!reactNativeHost.hasInstance()) {
|
|
267
|
+
lifecycle = LifecycleState.BEFORE_CREATE;
|
|
268
|
+
} else {
|
|
269
|
+
lifecycle = reactNativeHost.getReactInstanceManager().getLifecycleState();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// If the permission request didn't show a dialog to the user, we can call the callback
|
|
274
|
+
// immediately.
|
|
275
|
+
// Otherwise, we need to wait until onResume to call it.
|
|
276
|
+
if (lifecycle == LifecycleState.RESUMED) {
|
|
277
|
+
permissionsCallback.invoke();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
mPermissionsCallback = permissionsCallback;
|
|
258
282
|
}
|
|
259
283
|
|
|
260
284
|
protected Context getContext() {
|
|
@@ -51,7 +51,7 @@ import kotlin.math.min
|
|
|
51
51
|
* constructed in superclass.
|
|
52
52
|
*/
|
|
53
53
|
@LegacyArchitecture(logLevel = LegacyArchitectureLogLevel.ERROR)
|
|
54
|
-
public class ReactTextShadowNode
|
|
54
|
+
public open class ReactTextShadowNode
|
|
55
55
|
@JvmOverloads
|
|
56
56
|
public constructor(reactTextViewManagerCallback: ReactTextViewManagerCallback? = null) :
|
|
57
57
|
ReactBaseTextShadowNode(reactTextViewManagerCallback) {
|
|
@@ -29,7 +29,7 @@ import java.util.HashMap
|
|
|
29
29
|
*/
|
|
30
30
|
@ReactModule(name = ReactTextViewManager.REACT_CLASS)
|
|
31
31
|
@OptIn(UnstableReactNativeAPI::class)
|
|
32
|
-
public class ReactTextViewManager
|
|
32
|
+
public open class ReactTextViewManager
|
|
33
33
|
@JvmOverloads
|
|
34
34
|
public constructor(
|
|
35
35
|
protected var reactTextViewManagerCallback: ReactTextViewManagerCallback? = null
|
|
@@ -92,7 +92,7 @@ public constructor(
|
|
|
92
92
|
override fun createShadowNodeInstance(): ReactTextShadowNode =
|
|
93
93
|
ReactTextShadowNode(reactTextViewManagerCallback)
|
|
94
94
|
|
|
95
|
-
public fun createShadowNodeInstance(
|
|
95
|
+
public open fun createShadowNodeInstance(
|
|
96
96
|
reactTextViewManagerCallback: ReactTextViewManagerCallback?
|
|
97
97
|
): ReactTextShadowNode = ReactTextShadowNode(reactTextViewManagerCallback)
|
|
98
98
|
|
|
@@ -39,7 +39,9 @@ void processTransform(
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
auto result = BaseViewProps::resolveTransform(
|
|
42
|
-
Size
|
|
42
|
+
Size{.width = viewWidth, .height = viewHeight},
|
|
43
|
+
transform,
|
|
44
|
+
transformOrigin);
|
|
43
45
|
|
|
44
46
|
// Convert from matrix of floats to double matrix
|
|
45
47
|
constexpr size_t MatrixSize = std::tuple_size_v<decltype(result.matrix)>;
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
|
|
15
15
|
#define REACT_NATIVE_VERSION_MAJOR 0
|
|
16
16
|
#define REACT_NATIVE_VERSION_MINOR 81
|
|
17
|
-
#define REACT_NATIVE_VERSION_PATCH
|
|
17
|
+
#define REACT_NATIVE_VERSION_PATCH 5
|
|
18
18
|
|
|
19
19
|
namespace facebook::react {
|
|
20
20
|
|
|
21
21
|
constexpr struct {
|
|
22
22
|
int32_t Major = 0;
|
|
23
23
|
int32_t Minor = 81;
|
|
24
|
-
int32_t Patch =
|
|
24
|
+
int32_t Patch = 5;
|
|
25
25
|
std::string_view Prerelease = "";
|
|
26
26
|
} ReactNativeVersion;
|
|
27
27
|
|
|
@@ -558,9 +558,6 @@ Transform BaseViewProps::resolveTransform(
|
|
|
558
558
|
const Transform& transform,
|
|
559
559
|
const TransformOrigin& transformOrigin) {
|
|
560
560
|
auto transformMatrix = Transform{};
|
|
561
|
-
if (frameSize.width == 0 && frameSize.height == 0) {
|
|
562
|
-
return transformMatrix;
|
|
563
|
-
}
|
|
564
561
|
|
|
565
562
|
// transform is matrix
|
|
566
563
|
if (transform.operations.size() == 1 &&
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <gtest/gtest.h>
|
|
9
|
+
|
|
10
|
+
#include <react/renderer/components/view/BaseViewProps.h>
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
namespace {
|
|
15
|
+
|
|
16
|
+
// For transforms involving rotations, use this helper to fix floating point
|
|
17
|
+
// accuracies
|
|
18
|
+
void expectTransformsEqual(const Transform& t1, const Transform& t2) {
|
|
19
|
+
for (int i = 0; i < 16; i++) {
|
|
20
|
+
EXPECT_NEAR(t1.matrix[i], t2.matrix[i], 0.0001);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
} // namespace
|
|
25
|
+
|
|
26
|
+
class ResolveTransformTest : public ::testing::Test {
|
|
27
|
+
protected:
|
|
28
|
+
TransformOrigin createTransformOriginPoints(float x, float y, float z = 0) {
|
|
29
|
+
TransformOrigin origin;
|
|
30
|
+
origin.xy[0] = ValueUnit(x, UnitType::Point);
|
|
31
|
+
origin.xy[1] = ValueUnit(y, UnitType::Point);
|
|
32
|
+
origin.z = z;
|
|
33
|
+
return origin;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
TransformOrigin createTransformOriginPercent(float x, float y, float z = 0) {
|
|
37
|
+
TransformOrigin origin;
|
|
38
|
+
origin.xy[0] = ValueUnit(x, UnitType::Percent);
|
|
39
|
+
origin.xy[1] = ValueUnit(y, UnitType::Percent);
|
|
40
|
+
origin.z = z;
|
|
41
|
+
return origin;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
TEST_F(ResolveTransformTest, EmptyFrameNoTransformOrigin) {
|
|
46
|
+
Size frameSize{.width = 0, .height = 0};
|
|
47
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
48
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
49
|
+
|
|
50
|
+
auto result =
|
|
51
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
52
|
+
|
|
53
|
+
// With empty frame size and no transform origin, should just apply the
|
|
54
|
+
// transform directly
|
|
55
|
+
EXPECT_EQ(result.matrix, transform.matrix);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPoints) {
|
|
59
|
+
Size frameSize{.width = 0, .height = 0};
|
|
60
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
61
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(5, 8);
|
|
62
|
+
|
|
63
|
+
auto result =
|
|
64
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
65
|
+
|
|
66
|
+
// Should handle transform origin even with empty frame size
|
|
67
|
+
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPercent) {
|
|
71
|
+
Size frameSize{.width = 0, .height = 0};
|
|
72
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
73
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
74
|
+
|
|
75
|
+
auto result =
|
|
76
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
77
|
+
|
|
78
|
+
// Transform origin does not affect translate transform
|
|
79
|
+
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
TEST_F(ResolveTransformTest, NonEmptyFrameNoTransformOrigin) {
|
|
83
|
+
Size frameSize{.width = 100, .height = 200};
|
|
84
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
85
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
86
|
+
|
|
87
|
+
auto result =
|
|
88
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
89
|
+
|
|
90
|
+
// Transform origin does not affect translate transform
|
|
91
|
+
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPoints) {
|
|
95
|
+
Size frameSize{.width = 100, .height = 200};
|
|
96
|
+
Transform transform = Transform::Scale(2.0, 1.5, 0.);
|
|
97
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
98
|
+
|
|
99
|
+
auto result =
|
|
100
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
101
|
+
|
|
102
|
+
auto expected = Transform::Translate(25.0, 25.0, 0.0) * transform;
|
|
103
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPercent) {
|
|
107
|
+
Size frameSize{.width = 100, .height = 200};
|
|
108
|
+
Transform transform = Transform::Scale(2.0, 1.5, 0.);
|
|
109
|
+
TransformOrigin transformOrigin =
|
|
110
|
+
createTransformOriginPercent(25, 75); // 25% width, 75% height
|
|
111
|
+
|
|
112
|
+
auto result =
|
|
113
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
114
|
+
|
|
115
|
+
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
|
|
116
|
+
auto expected = Transform::Translate(25.0, -25.0, 0.0) * transform;
|
|
117
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
TEST_F(ResolveTransformTest, IdentityTransformWithOrigin) {
|
|
121
|
+
Size frameSize{.width = 100, .height = 200};
|
|
122
|
+
Transform transform = Transform::Identity();
|
|
123
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
124
|
+
|
|
125
|
+
auto result =
|
|
126
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
127
|
+
|
|
128
|
+
// Even with identity transform, transform origin should still apply
|
|
129
|
+
// translations but they should cancel out, resulting in identity
|
|
130
|
+
EXPECT_EQ(result.matrix, transform.matrix);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
TEST_F(ResolveTransformTest, MultipleTransformOperations) {
|
|
134
|
+
Size frameSize{.width = 100, .height = 200};
|
|
135
|
+
|
|
136
|
+
Transform transform = Transform::Identity();
|
|
137
|
+
transform = transform * Transform::Translate(10.0, 20.0, 0.0);
|
|
138
|
+
transform = transform * Transform::Scale(2.0, 1.5, 0.0);
|
|
139
|
+
|
|
140
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
141
|
+
|
|
142
|
+
auto result =
|
|
143
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
144
|
+
|
|
145
|
+
EXPECT_EQ(result.matrix, transform.matrix);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
TEST_F(ResolveTransformTest, VariousTransformOriginPositions) {
|
|
149
|
+
Size frameSize{.width = 100, .height = 200};
|
|
150
|
+
Transform transform = Transform::Scale(2.0, 2.0, 0.);
|
|
151
|
+
|
|
152
|
+
// Test origin at top-left (0, 0)
|
|
153
|
+
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
|
|
154
|
+
auto resultTopLeft =
|
|
155
|
+
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
|
|
156
|
+
auto expected = Transform::Translate(50.0, 100.0, 0.0) * transform;
|
|
157
|
+
EXPECT_EQ(resultTopLeft.matrix, expected.matrix);
|
|
158
|
+
|
|
159
|
+
// Test origin at center (50%, 50%)
|
|
160
|
+
TransformOrigin center = createTransformOriginPercent(50, 50);
|
|
161
|
+
auto resultCenter =
|
|
162
|
+
BaseViewProps::resolveTransform(frameSize, transform, center);
|
|
163
|
+
EXPECT_EQ(resultCenter.matrix, transform.matrix);
|
|
164
|
+
|
|
165
|
+
// Test origin at bottom-right (100%, 100%)
|
|
166
|
+
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
|
|
167
|
+
auto resultBottomRight =
|
|
168
|
+
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
|
|
169
|
+
expected = Transform::Translate(-50.0, -100.0, 0.0) * transform;
|
|
170
|
+
EXPECT_EQ(resultBottomRight.matrix, expected.matrix);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Test with z-component in transform origin
|
|
174
|
+
TEST_F(ResolveTransformTest, TransformOriginWithZComponent) {
|
|
175
|
+
Size frameSize{.width = 100, .height = 200};
|
|
176
|
+
Transform transform = Transform::Scale(1.5, 1.5, 0.);
|
|
177
|
+
|
|
178
|
+
TransformOrigin transformOrigin;
|
|
179
|
+
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
|
|
180
|
+
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
|
|
181
|
+
transformOrigin.z = 10.0f;
|
|
182
|
+
|
|
183
|
+
auto result =
|
|
184
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
185
|
+
auto expected = Transform::Translate(0.0, 0.0, 10.0) * transform;
|
|
186
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
TEST_F(ResolveTransformTest, ArbitraryTransformMatrix) {
|
|
190
|
+
Size frameSize{.width = 100, .height = 200};
|
|
191
|
+
|
|
192
|
+
Transform transform;
|
|
193
|
+
transform.operations.push_back({
|
|
194
|
+
.type = TransformOperationType::Arbitrary,
|
|
195
|
+
.x = ValueUnit(0, UnitType::Point),
|
|
196
|
+
.y = ValueUnit(0, UnitType::Point),
|
|
197
|
+
.z = ValueUnit(0, UnitType::Point),
|
|
198
|
+
});
|
|
199
|
+
// Set custom matrix
|
|
200
|
+
transform.matrix = {{2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 10, 20, 0, 1}};
|
|
201
|
+
|
|
202
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
203
|
+
|
|
204
|
+
auto result =
|
|
205
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
206
|
+
|
|
207
|
+
auto expected = Transform::Translate(25.0, 50.0, 0.0) * transform;
|
|
208
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Test rotation with empty frame size and no transform origin
|
|
212
|
+
TEST_F(ResolveTransformTest, RotationEmptyFrameNoTransformOrigin) {
|
|
213
|
+
Size frameSize{.width = 0, .height = 0};
|
|
214
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
215
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
216
|
+
|
|
217
|
+
auto result =
|
|
218
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
219
|
+
|
|
220
|
+
// With empty frame size and no transform origin, should just apply the
|
|
221
|
+
// rotation directly
|
|
222
|
+
expectTransformsEqual(result, transform);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Test rotation with empty frame size and transform origin in points
|
|
226
|
+
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPoints) {
|
|
227
|
+
Size frameSize{.width = 0, .height = 0};
|
|
228
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
229
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(10, 20);
|
|
230
|
+
|
|
231
|
+
auto result =
|
|
232
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
233
|
+
|
|
234
|
+
// With empty frame size, center is (0, 0), so origin offset is (10, 20)
|
|
235
|
+
auto expected = Transform::Translate(10.0, 20.0, 0.0) * transform *
|
|
236
|
+
Transform::Translate(-10.0, -20.0, 0.0);
|
|
237
|
+
expectTransformsEqual(result, expected);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Test rotation with empty frame size and transform origin in percentages
|
|
241
|
+
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPercent) {
|
|
242
|
+
Size frameSize{.width = 0, .height = 0};
|
|
243
|
+
Transform transform = Transform::RotateZ(M_PI / 6.0); // 30 degrees
|
|
244
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
245
|
+
|
|
246
|
+
auto result =
|
|
247
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
248
|
+
|
|
249
|
+
// With 0 frame size, percentages resolve to 0, so no origin offset
|
|
250
|
+
expectTransformsEqual(result, transform);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Test rotation with non-empty frame size and no transform origin
|
|
254
|
+
TEST_F(ResolveTransformTest, RotationNonEmptyFrameNoTransformOrigin) {
|
|
255
|
+
Size frameSize{.width = 100, .height = 200};
|
|
256
|
+
Transform transform = Transform::RotateZ(M_PI / 3.0); // 60 degrees
|
|
257
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
258
|
+
|
|
259
|
+
auto result =
|
|
260
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
261
|
+
|
|
262
|
+
// Without transform origin, rotation should happen around default center
|
|
263
|
+
expectTransformsEqual(result, transform);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Test rotation with non-empty frame size and transform origin in points
|
|
267
|
+
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPoints) {
|
|
268
|
+
Size frameSize{.width = 100, .height = 200};
|
|
269
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
270
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
271
|
+
|
|
272
|
+
auto result =
|
|
273
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
274
|
+
|
|
275
|
+
// Center of 100x200 frame is (50, 100), origin at (25, 50) means offset of
|
|
276
|
+
// (-25, -50)
|
|
277
|
+
auto expected = Transform::Translate(-25.0, -50.0, 0.0) * transform *
|
|
278
|
+
Transform::Translate(25.0, 50.0, 0.0);
|
|
279
|
+
expectTransformsEqual(result, expected);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Test rotation with non-empty frame size and transform origin in percentages
|
|
283
|
+
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPercent) {
|
|
284
|
+
Size frameSize{.width = 100, .height = 200};
|
|
285
|
+
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
|
|
286
|
+
TransformOrigin transformOrigin =
|
|
287
|
+
createTransformOriginPercent(25, 75); // 25% width, 75% height
|
|
288
|
+
|
|
289
|
+
auto result =
|
|
290
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
291
|
+
|
|
292
|
+
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
|
|
293
|
+
// Center is (50, 100), so origin offset is (25-50, 150-100) = (-25, 50)
|
|
294
|
+
auto expected = Transform::Translate(-25.0, 50.0, 0.0) * transform *
|
|
295
|
+
Transform::Translate(25.0, -50.0, 0.0);
|
|
296
|
+
expectTransformsEqual(result, expected);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Test rotation with mixed transform origin units
|
|
300
|
+
TEST_F(ResolveTransformTest, RotationMixedTransformOriginUnits) {
|
|
301
|
+
Size frameSize{.width = 100, .height = 200};
|
|
302
|
+
Transform transform = Transform::RotateZ(M_PI); // 180 degrees
|
|
303
|
+
|
|
304
|
+
TransformOrigin transformOrigin;
|
|
305
|
+
transformOrigin.xy[0] = ValueUnit(30, UnitType::Point); // 30 points
|
|
306
|
+
transformOrigin.xy[1] = ValueUnit(25, UnitType::Percent); // 25% of 200 = 50
|
|
307
|
+
transformOrigin.z = 0;
|
|
308
|
+
|
|
309
|
+
auto result =
|
|
310
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
311
|
+
|
|
312
|
+
// Center is (50, 100), origin is (30, 50), so offset is (-20, -50)
|
|
313
|
+
auto expected = Transform::Translate(-20.0, -50.0, 0.0) * transform *
|
|
314
|
+
Transform::Translate(20.0, 50.0, 0.0);
|
|
315
|
+
expectTransformsEqual(result, expected);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Test multiple rotations (RotateX, RotateY, RotateZ)
|
|
319
|
+
TEST_F(ResolveTransformTest, MultipleRotationsWithTransformOrigin) {
|
|
320
|
+
Size frameSize{.width = 100, .height = 100};
|
|
321
|
+
|
|
322
|
+
Transform transform = Transform::Rotate(M_PI / 6.0, M_PI / 4.0, M_PI / 3.0);
|
|
323
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
324
|
+
|
|
325
|
+
auto result =
|
|
326
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
327
|
+
expectTransformsEqual(result, transform);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Test rotation with z-component in transform origin
|
|
331
|
+
TEST_F(ResolveTransformTest, RotationWithZTransformOrigin) {
|
|
332
|
+
Size frameSize{.width = 100, .height = 200};
|
|
333
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
334
|
+
|
|
335
|
+
TransformOrigin transformOrigin;
|
|
336
|
+
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
|
|
337
|
+
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
|
|
338
|
+
transformOrigin.z = 15.0f;
|
|
339
|
+
|
|
340
|
+
auto result =
|
|
341
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
342
|
+
|
|
343
|
+
// Center is (50, 100), origin is (50, 100, 15), so offset is (0, 0, 15)
|
|
344
|
+
auto expected = Transform::Translate(0.0, 0.0, 15.0) * transform *
|
|
345
|
+
Transform::Translate(0.0, 0.0, -15.0);
|
|
346
|
+
expectTransformsEqual(result, expected);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Test rotation at different origin positions (corners vs center)
|
|
350
|
+
TEST_F(ResolveTransformTest, RotationDifferentOriginPositions) {
|
|
351
|
+
Size frameSize{.width = 100, .height = 100};
|
|
352
|
+
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
|
|
353
|
+
|
|
354
|
+
// Test rotation around top-left corner (0, 0)
|
|
355
|
+
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
|
|
356
|
+
auto resultTopLeft =
|
|
357
|
+
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
|
|
358
|
+
auto expectedTopLeft = Transform::Translate(-50.0, -50.0, 0.0) * transform *
|
|
359
|
+
Transform::Translate(50.0, 50.0, 0.0);
|
|
360
|
+
expectTransformsEqual(resultTopLeft, expectedTopLeft);
|
|
361
|
+
|
|
362
|
+
// Test rotation around center (50%, 50%)
|
|
363
|
+
TransformOrigin center = createTransformOriginPercent(50, 50);
|
|
364
|
+
auto resultCenter =
|
|
365
|
+
BaseViewProps::resolveTransform(frameSize, transform, center);
|
|
366
|
+
expectTransformsEqual(resultCenter, transform);
|
|
367
|
+
|
|
368
|
+
// Test rotation around bottom-right corner (100%, 100%)
|
|
369
|
+
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
|
|
370
|
+
auto resultBottomRight =
|
|
371
|
+
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
|
|
372
|
+
auto expectedBottomRight = Transform::Translate(50.0, 50.0, 0.0) * transform *
|
|
373
|
+
Transform::Translate(-50.0, -50.0, 0.0);
|
|
374
|
+
expectTransformsEqual(resultBottomRight, expectedBottomRight);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
} // namespace facebook::react
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.5",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -162,13 +162,13 @@
|
|
|
162
162
|
},
|
|
163
163
|
"dependencies": {
|
|
164
164
|
"@jest/create-cache-key-function": "^29.7.0",
|
|
165
|
-
"@react-native/assets-registry": "0.81.
|
|
166
|
-
"@react-native/codegen": "0.81.
|
|
167
|
-
"@react-native/community-cli-plugin": "0.81.
|
|
168
|
-
"@react-native/gradle-plugin": "0.81.
|
|
169
|
-
"@react-native/js-polyfills": "0.81.
|
|
170
|
-
"@react-native/normalize-colors": "0.81.
|
|
171
|
-
"@react-native/virtualized-lists": "0.81.
|
|
165
|
+
"@react-native/assets-registry": "0.81.5",
|
|
166
|
+
"@react-native/codegen": "0.81.5",
|
|
167
|
+
"@react-native/community-cli-plugin": "0.81.5",
|
|
168
|
+
"@react-native/gradle-plugin": "0.81.5",
|
|
169
|
+
"@react-native/js-polyfills": "0.81.5",
|
|
170
|
+
"@react-native/normalize-colors": "0.81.5",
|
|
171
|
+
"@react-native/virtualized-lists": "0.81.5",
|
|
172
172
|
"abort-controller": "^3.0.0",
|
|
173
173
|
"anser": "^1.4.9",
|
|
174
174
|
"ansi-regex": "^5.0.0",
|
|
@@ -40,6 +40,12 @@ def list_native_modules!(config_command)
|
|
|
40
40
|
packages = config["dependencies"]
|
|
41
41
|
ios_project_root = Pathname.new(config["project"]["ios"]["sourceDir"])
|
|
42
42
|
react_native_path = Pathname.new(config["reactNativePath"])
|
|
43
|
+
codegen_output_path = ios_project_root.join("build/generated/autolinking/autolinking.json")
|
|
44
|
+
|
|
45
|
+
# Write autolinking react-native-config output to codegen folder
|
|
46
|
+
FileUtils.mkdir_p(File.dirname(codegen_output_path))
|
|
47
|
+
File.write(codegen_output_path, json)
|
|
48
|
+
|
|
43
49
|
found_pods = []
|
|
44
50
|
|
|
45
51
|
packages.each do |package_name, package|
|
|
@@ -87,7 +87,7 @@ class CodegenUtils
|
|
|
87
87
|
codegen_path = file_manager.join(ios_folder, codegen_dir)
|
|
88
88
|
return if !dir_manager.exist?(codegen_path)
|
|
89
89
|
|
|
90
|
-
FileUtils.rm_rf(
|
|
90
|
+
FileUtils.rm_rf("#{codegen_path}")
|
|
91
91
|
base_provider_path = file_manager.join(rn_path, 'React', 'Fabric', 'RCTThirdPartyFabricComponentsProvider')
|
|
92
92
|
FileUtils.rm_rf("#{base_provider_path}.h")
|
|
93
93
|
FileUtils.rm_rf("#{base_provider_path}.mm")
|
|
@@ -86,16 +86,19 @@ function execute(
|
|
|
86
86
|
buildCodegenIfNeeded();
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
const reactNativeConfig = readReactNativeConfig(
|
|
89
|
+
const reactNativeConfig = readReactNativeConfig(
|
|
90
|
+
projectRoot,
|
|
91
|
+
baseOutputPath,
|
|
92
|
+
);
|
|
90
93
|
const codegenEnabledLibraries = findCodegenEnabledLibraries(
|
|
91
94
|
pkgJson,
|
|
92
95
|
projectRoot,
|
|
96
|
+
baseOutputPath,
|
|
93
97
|
reactNativeConfig,
|
|
94
98
|
);
|
|
95
99
|
|
|
96
100
|
if (codegenEnabledLibraries.length === 0) {
|
|
97
101
|
codegenLog('No codegen-enabled libraries found.', true);
|
|
98
|
-
return;
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
let platforms =
|
|
@@ -110,10 +113,6 @@ function execute(
|
|
|
110
113
|
({name}) => !disabledLibraries.includes(name),
|
|
111
114
|
);
|
|
112
115
|
|
|
113
|
-
if (!libraries.length) {
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
116
|
const outputPath = computeOutputPath(
|
|
118
117
|
projectRoot,
|
|
119
118
|
baseOutputPath,
|
|
@@ -97,15 +97,40 @@ function cleanupEmptyFilesAndFolders(filepath /*: string */) {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
function
|
|
101
|
-
|
|
100
|
+
function readGeneratedAutolinkingOutput(
|
|
101
|
+
baseOutputPath /*: string */,
|
|
102
|
+
) /*: $FlowFixMe */ {
|
|
103
|
+
// NOTE: Generated by scripts/cocoapods/autolinking.rb in list_native_modules (called by use_native_modules)
|
|
104
|
+
const autolinkingGeneratedPath = path.resolve(
|
|
105
|
+
baseOutputPath,
|
|
106
|
+
'build/generated/autolinking/autolinking.json',
|
|
107
|
+
);
|
|
108
|
+
if (fs.existsSync(autolinkingGeneratedPath)) {
|
|
109
|
+
// $FlowFixMe[unsupported-syntax]
|
|
110
|
+
return require(autolinkingGeneratedPath);
|
|
111
|
+
} else {
|
|
112
|
+
codegenLog(
|
|
113
|
+
`Could not find generated autolinking output at: ${autolinkingGeneratedPath}`,
|
|
114
|
+
);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
102
118
|
|
|
103
|
-
|
|
119
|
+
function readReactNativeConfig(
|
|
120
|
+
projectRoot /*: string */,
|
|
121
|
+
baseOutputPath /*: string */,
|
|
122
|
+
) /*: $FlowFixMe */ {
|
|
123
|
+
const autolinkingOutput = readGeneratedAutolinkingOutput(baseOutputPath);
|
|
124
|
+
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
|
|
125
|
+
if (autolinkingOutput) {
|
|
126
|
+
return autolinkingOutput;
|
|
127
|
+
} else if (fs.existsSync(rnConfigFilePath)) {
|
|
128
|
+
// $FlowIgnore[unsupported-syntax]
|
|
129
|
+
return require(rnConfigFilePath);
|
|
130
|
+
} else {
|
|
131
|
+
codegenLog(`Could not find React Native config at: ${rnConfigFilePath}`);
|
|
104
132
|
return {};
|
|
105
133
|
}
|
|
106
|
-
|
|
107
|
-
// $FlowIgnore[unsupported-syntax]
|
|
108
|
-
return require(rnConfigFilePath);
|
|
109
134
|
}
|
|
110
135
|
|
|
111
136
|
/**
|
|
@@ -114,17 +139,23 @@ function readReactNativeConfig(projectRoot /*: string */) /*: $FlowFixMe */ {
|
|
|
114
139
|
function findCodegenEnabledLibraries(
|
|
115
140
|
pkgJson /*: $FlowFixMe */,
|
|
116
141
|
projectRoot /*: string */,
|
|
142
|
+
baseOutputPath /*: string */,
|
|
117
143
|
reactNativeConfig /*: $FlowFixMe */,
|
|
118
144
|
) /*: Array<$FlowFixMe> */ {
|
|
119
145
|
const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
|
|
120
146
|
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
|
|
121
147
|
return projectLibraries;
|
|
122
148
|
} else {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
149
|
+
const libraries = [...projectLibraries];
|
|
150
|
+
// If we ran autolinking, we shouldn't try to run our own "autolinking-like"
|
|
151
|
+
// library discovery
|
|
152
|
+
if (!readGeneratedAutolinkingOutput(baseOutputPath)) {
|
|
153
|
+
libraries.push(...findExternalLibraries(pkgJson, projectRoot));
|
|
154
|
+
}
|
|
155
|
+
libraries.push(
|
|
126
156
|
...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
|
|
127
|
-
|
|
157
|
+
);
|
|
158
|
+
return libraries;
|
|
128
159
|
}
|
|
129
160
|
}
|
|
130
161
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -62,7 +62,7 @@ Pod::Spec.new do |spec|
|
|
|
62
62
|
exit 0
|
|
63
63
|
fi
|
|
64
64
|
|
|
65
|
-
cp -R "$HEADERS_PATH
|
|
65
|
+
cp -R "$HEADERS_PATH/." Headers
|
|
66
66
|
mkdir -p framework/packages/react-native
|
|
67
67
|
cp -R "$XCFRAMEWORK_PATH/../." framework/packages/react-native/
|
|
68
68
|
find "$XCFRAMEWORK_PATH/.." -type f -exec rm {} +
|