expo-modules-core 57.0.12 → 57.0.14
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/CHANGELOG.md +17 -0
- package/android/build.gradle +2 -2
- package/android/src/main/cpp/fabric/NativeStatePropsGetter.cpp +29 -0
- package/android/src/main/cpp/fabric/NativeStatePropsGetter.h +17 -0
- package/android/src/main/java/expo/modules/kotlin/jni/fabric/NativeStatePropsGetter.kt +23 -0
- package/android/src/main/java/expo/modules/kotlin/views/ShadowNodeProxy.kt +14 -0
- package/build/NativeViewManagerAdapter.native.d.ts.map +1 -1
- package/common/cpp/fabric/ContentOriginRegistry.h +63 -0
- package/common/cpp/fabric/ExpoViewComponentDescriptor.h +6 -16
- package/common/cpp/fabric/ExpoViewShadowNode.h +26 -0
- package/ios/Core/Views/SwiftUI/SwiftUIShadowNodeProxy.swift +3 -0
- package/ios/Core/Views/SwiftUI/SwiftUIVirtualView.swift +12 -0
- package/ios/Core/Views/SwiftUI/SwiftUIVirtualViewObjC.h +17 -0
- package/ios/Core/Views/SwiftUI/SwiftUIVirtualViewObjCDev.h +13 -0
- package/ios/Core/Views/SwiftUI/SwiftUIVirtualViewSharedImpl+Private.h +18 -0
- package/ios/Fabric/EXContentOriginRegistry.h +17 -0
- package/ios/Fabric/EXContentOriginRegistry.mm +13 -0
- package/package.json +3 -3
- package/prebuilds/output/debug/xcframeworks/ExpoModulesCore.tar.gz +0 -0
- package/prebuilds/output/debug/xcframeworks/ExpoModulesWorklets.tar.gz +0 -0
- package/prebuilds/output/release/xcframeworks/ExpoModulesCore.tar.gz +0 -0
- package/prebuilds/output/release/xcframeworks/ExpoModulesWorklets.tar.gz +0 -0
- package/src/NativeViewManagerAdapter.native.tsx +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,23 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 57.0.14 — 2026-08-26
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Added `getNativeRef()` to views created with `requireNativeViewManager`, which returns the underlying host component. ([#48788](https://github.com/expo/expo/pull/48788) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- [iOS] Measure hosted React Native views where SwiftUI placed them, instead of at their Yoga box. ([#48969](https://github.com/expo/expo/pull/48969) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
22
|
+
- [Android] Measure hosted React Native views where Jetpack Compose placed them, instead of at their Yoga box. ([#48970](https://github.com/expo/expo/pull/48970) by [@nishan](https://github.com/intergalacticspacehighway))
|
|
23
|
+
|
|
24
|
+
## 57.0.13 — 2026-08-24
|
|
25
|
+
|
|
26
|
+
### 🐛 Bug fixes
|
|
27
|
+
|
|
28
|
+
- [iOS] Fixed `matchContents` hosts sometimes being laid out at a stale size. Regression from [#48059](https://github.com/expo/expo/pull/48059). ([#49211](https://github.com/expo/expo/pull/49211) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
|
|
29
|
+
|
|
13
30
|
## 57.0.12 — 2026-08-20
|
|
14
31
|
|
|
15
32
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -27,7 +27,7 @@ if (shouldIncludeCompose) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
group = 'host.exp.exponent'
|
|
30
|
-
version = '57.0.
|
|
30
|
+
version = '57.0.14'
|
|
31
31
|
|
|
32
32
|
def isExpoModulesCoreTests = {
|
|
33
33
|
Gradle gradle = getGradle()
|
|
@@ -94,7 +94,7 @@ android {
|
|
|
94
94
|
defaultConfig {
|
|
95
95
|
consumerProguardFiles 'proguard-rules.pro'
|
|
96
96
|
versionCode 1
|
|
97
|
-
versionName "57.0.
|
|
97
|
+
versionName "57.0.14"
|
|
98
98
|
buildConfigField "String", "EXPO_MODULES_CORE_VERSION", "\"${versionName}\""
|
|
99
99
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", "true"
|
|
100
100
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include "NativeStatePropsGetter.h"
|
|
2
2
|
#include "AndroidExpoViewState.h"
|
|
3
|
+
#include "ContentOriginRegistry.h"
|
|
3
4
|
#include <react/fabric/StateWrapperImpl.h>
|
|
4
5
|
|
|
5
6
|
#include <react/renderer/core/ConcreteState.h>
|
|
@@ -11,6 +12,9 @@ void NativeStatePropsGetter::registerNatives() {
|
|
|
11
12
|
makeNativeMethod("getStateProps", NativeStatePropsGetter::getStateProps),
|
|
12
13
|
makeNativeMethod("updateStyleSizeImmediateImpl", NativeStatePropsGetter::updateStyleSizeImmediate),
|
|
13
14
|
makeNativeMethod("updateViewSizeImmediateImpl", NativeStatePropsGetter::updateViewSizeImmediate),
|
|
15
|
+
makeNativeMethod("setContentOriginImpl", NativeStatePropsGetter::setContentOrigin),
|
|
16
|
+
makeNativeMethod("clearContentOriginImpl", NativeStatePropsGetter::clearContentOrigin),
|
|
17
|
+
makeNativeMethod("clearAllContentOriginsImpl", NativeStatePropsGetter::clearAllContentOrigins),
|
|
14
18
|
});
|
|
15
19
|
}
|
|
16
20
|
|
|
@@ -57,6 +61,31 @@ void NativeStatePropsGetter::updateViewSizeImmediate(
|
|
|
57
61
|
state->updateState(std::move(newState), react::EventQueue::UpdateMode::unstable_Immediate);
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
void NativeStatePropsGetter::setContentOrigin(
|
|
65
|
+
jni::alias_ref<NativeStatePropsGetter::javaobject> self,
|
|
66
|
+
jint tag,
|
|
67
|
+
jdouble x,
|
|
68
|
+
jdouble y
|
|
69
|
+
) {
|
|
70
|
+
ContentOriginRegistry::set(
|
|
71
|
+
static_cast<react::Tag>(tag),
|
|
72
|
+
react::Point{.x = static_cast<react::Float>(x), .y = static_cast<react::Float>(y)}
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void NativeStatePropsGetter::clearContentOrigin(
|
|
77
|
+
jni::alias_ref<NativeStatePropsGetter::javaobject> self,
|
|
78
|
+
jint tag
|
|
79
|
+
) {
|
|
80
|
+
ContentOriginRegistry::clear(static_cast<react::Tag>(tag));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void NativeStatePropsGetter::clearAllContentOrigins(
|
|
84
|
+
jni::alias_ref<NativeStatePropsGetter::javaobject> self
|
|
85
|
+
) {
|
|
86
|
+
ContentOriginRegistry::clearAll();
|
|
87
|
+
}
|
|
88
|
+
|
|
60
89
|
jni::local_ref<jni::JMap<jstring, jobject>> NativeStatePropsGetter::getStateProps(
|
|
61
90
|
jni::alias_ref<NativeStatePropsGetter::javaobject> self,
|
|
62
91
|
jni::alias_ref<jobject> stateWrapper
|
|
@@ -35,6 +35,23 @@ public:
|
|
|
35
35
|
jdouble width,
|
|
36
36
|
jdouble height
|
|
37
37
|
);
|
|
38
|
+
|
|
39
|
+
// Publishes where Compose actually placed a hosted view inside its `Host`, which Yoga cannot see.
|
|
40
|
+
static void setContentOrigin(
|
|
41
|
+
jni::alias_ref<NativeStatePropsGetter::javaobject> self,
|
|
42
|
+
jint tag,
|
|
43
|
+
jdouble x,
|
|
44
|
+
jdouble y
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
static void clearContentOrigin(
|
|
48
|
+
jni::alias_ref<NativeStatePropsGetter::javaobject> self,
|
|
49
|
+
jint tag
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
static void clearAllContentOrigins(
|
|
53
|
+
jni::alias_ref<NativeStatePropsGetter::javaobject> self
|
|
54
|
+
);
|
|
38
55
|
};
|
|
39
56
|
|
|
40
57
|
} // namespace expo
|
|
@@ -24,6 +24,29 @@ class NativeStatePropsGetter {
|
|
|
24
24
|
updateViewSizeImmediateImpl(stateWrapper, width, height)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Publishes where the native layout system placed a hosted view inside its `Host`, keyed by the
|
|
29
|
+
* view's tag. Read while measuring, so `measure()` reports the position the content occupies
|
|
30
|
+
* rather than its Yoga box.
|
|
31
|
+
*/
|
|
32
|
+
fun setContentOrigin(tag: Int, x: Double, y: Double) {
|
|
33
|
+
setContentOriginImpl(tag, x, y)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fun clearContentOrigin(tag: Int) {
|
|
37
|
+
clearContentOriginImpl(tag)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun clearAllContentOrigins() {
|
|
41
|
+
clearAllContentOriginsImpl()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private external fun setContentOriginImpl(tag: Int, x: Double, y: Double)
|
|
45
|
+
|
|
46
|
+
private external fun clearContentOriginImpl(tag: Int)
|
|
47
|
+
|
|
48
|
+
private external fun clearAllContentOriginsImpl()
|
|
49
|
+
|
|
27
50
|
private external fun updateStyleSizeImmediateImpl(
|
|
28
51
|
stateWrapper: Any,
|
|
29
52
|
styleWidth: Double,
|
|
@@ -28,6 +28,20 @@ class ShadowNodeProxy(expoView: ExpoView) {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Reports where the native layout system drew this view inside its `Host`, in dp relative to the
|
|
33
|
+
* `Host`'s origin.
|
|
34
|
+
*/
|
|
35
|
+
fun setContentOrigin(x: Double, y: Double) {
|
|
36
|
+
val view = weakExpoView.get() ?: return
|
|
37
|
+
stateUpdater.setContentOrigin(view.id, x, y)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun clearContentOrigin() {
|
|
41
|
+
val view = weakExpoView.get() ?: return
|
|
42
|
+
stateUpdater.clearContentOrigin(view.id)
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
private fun scheduleFlush(flush: (stateWrapper: Any) -> Unit) {
|
|
32
46
|
pendingFlush = flush
|
|
33
47
|
val view = weakExpoView.get() ?: return
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeViewManagerAdapter.native.d.ts","sourceRoot":"","sources":["../src/NativeViewManagerAdapter.native.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAkB,KAAK,aAAa,EAA4B,MAAM,OAAO,CAAC;AA4HrF;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,aAAa,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"NativeViewManagerAdapter.native.d.ts","sourceRoot":"","sources":["../src/NativeViewManagerAdapter.native.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAkB,KAAK,aAAa,EAA4B,MAAM,OAAO,CAAC;AA4HrF;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,aAAa,CAAC,CAAC,CAAC,CA6ClB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
|
|
5
|
+
#ifdef __cplusplus
|
|
6
|
+
|
|
7
|
+
#include <mutex>
|
|
8
|
+
#include <optional>
|
|
9
|
+
#include <unordered_map>
|
|
10
|
+
|
|
11
|
+
#include <react/renderer/core/ReactPrimitives.h>
|
|
12
|
+
#include <react/renderer/graphics/Point.h>
|
|
13
|
+
|
|
14
|
+
namespace expo {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
Where the native layout system drew a view's contents, keyed by React tag.
|
|
18
|
+
|
|
19
|
+
This sits outside the shadow tree on purpose. `ExpoViewState` would be the idiomatic home, but a
|
|
20
|
+
state update enqueues a commit, and the origin changes on every native layout pass — a commit per
|
|
21
|
+
pass can re-run layout, move the origin, and commit again. Writing here schedules no work.
|
|
22
|
+
*/
|
|
23
|
+
class ContentOriginRegistry {
|
|
24
|
+
public:
|
|
25
|
+
static void set(facebook::react::Tag tag, facebook::react::Point origin) {
|
|
26
|
+
std::lock_guard<std::mutex> lock(mutex());
|
|
27
|
+
storage()[tag] = origin;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static void clear(facebook::react::Tag tag) {
|
|
31
|
+
std::lock_guard<std::mutex> lock(mutex());
|
|
32
|
+
storage().erase(tag);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static void clearAll() {
|
|
36
|
+
std::lock_guard<std::mutex> lock(mutex());
|
|
37
|
+
storage().clear();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static std::optional<facebook::react::Point> find(facebook::react::Tag tag) {
|
|
41
|
+
std::lock_guard<std::mutex> lock(mutex());
|
|
42
|
+
auto it = storage().find(tag);
|
|
43
|
+
if (it == storage().end()) {
|
|
44
|
+
return std::nullopt;
|
|
45
|
+
}
|
|
46
|
+
return it->second;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private:
|
|
50
|
+
static std::mutex &mutex() {
|
|
51
|
+
static std::mutex instance;
|
|
52
|
+
return instance;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static std::unordered_map<facebook::react::Tag, facebook::react::Point> &storage() {
|
|
56
|
+
static std::unordered_map<facebook::react::Tag, facebook::react::Point> instance;
|
|
57
|
+
return instance;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
} // namespace expo
|
|
62
|
+
|
|
63
|
+
#endif // __cplusplus
|
|
@@ -67,29 +67,19 @@ public:
|
|
|
67
67
|
snode->getProps());
|
|
68
68
|
|
|
69
69
|
auto &style = const_cast<facebook::yoga::Style &>(props.yogaStyle);
|
|
70
|
-
bool changedStyle = false;
|
|
71
70
|
|
|
72
71
|
if (!isnan(styleWidth)) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
style.setDimension(facebook::yoga::Dimension::Width, expectedWidth);
|
|
76
|
-
changedStyle = true;
|
|
77
|
-
}
|
|
72
|
+
style.setDimension(facebook::yoga::Dimension::Width,
|
|
73
|
+
facebook::yoga::StyleSizeLength::points(styleWidth));
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
if (!isnan(styleHeight)) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
style.setDimension(facebook::yoga::Dimension::Height, expectedHeight);
|
|
84
|
-
changedStyle = true;
|
|
85
|
-
}
|
|
77
|
+
style.setDimension(facebook::yoga::Dimension::Height,
|
|
78
|
+
facebook::yoga::StyleSizeLength::points(styleHeight));
|
|
86
79
|
}
|
|
87
80
|
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
snode->updateYogaProps();
|
|
91
|
-
snode->dirtyLayout();
|
|
92
|
-
}
|
|
81
|
+
// Updates yoga style from props and sets the node dirty
|
|
82
|
+
snode->updateYogaProps();
|
|
93
83
|
}
|
|
94
84
|
facebook::react::ConcreteComponentDescriptor<ShadowNodeType>::adopt(shadowNode);
|
|
95
85
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
8
|
|
|
9
|
+
#include "ContentOriginRegistry.h"
|
|
9
10
|
#include "ExpoViewEventEmitter.h"
|
|
10
11
|
#include "ExpoViewProps.h"
|
|
11
12
|
#include "ExpoViewState.h"
|
|
@@ -51,6 +52,31 @@ public:
|
|
|
51
52
|
return traits;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
Used by `RNHostView`. Reports where this view's contents were actually drawn, for views laid
|
|
57
|
+
out by SwiftUI or Compose instead of Yoga. Without it `measure()` returns this node's Yoga box,
|
|
58
|
+
which is not where the hosted content ended up.
|
|
59
|
+
*/
|
|
60
|
+
facebook::react::Point getContentOriginOffset(bool includeTransform) const override {
|
|
61
|
+
// A `false` caller is asking for a scroll offset, which this view never has. Only the layout
|
|
62
|
+
// path passes `true`, and that is the one this override is for.
|
|
63
|
+
if (!includeTransform) {
|
|
64
|
+
return ConcreteViewShadowNode::getContentOriginOffset(includeTransform);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
auto contentOrigin = ContentOriginRegistry::find(this->getTag());
|
|
68
|
+
if (!contentOrigin) {
|
|
69
|
+
return ConcreteViewShadowNode::getContentOriginOffset(includeTransform);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// `computeRelativeLayoutMetrics` adds this node's own Yoga origin before consulting us,
|
|
73
|
+
// so subtract them as we only want content origin to be considered.
|
|
74
|
+
// Publish only the part Yoga cannot see: where
|
|
75
|
+
// the native layout system placed the content inside its host.
|
|
76
|
+
auto ownOrigin = this->getLayoutMetrics().frame.origin;
|
|
77
|
+
return {.x = contentOrigin->x - ownOrigin.x, .y = contentOrigin->y - ownOrigin.y};
|
|
78
|
+
}
|
|
79
|
+
|
|
54
80
|
private:
|
|
55
81
|
void initialize() noexcept {
|
|
56
82
|
auto &viewProps = static_cast<const ExpoViewProps &>(*this->props_);
|
|
@@ -12,5 +12,8 @@ extension ExpoSwiftUI {
|
|
|
12
12
|
|
|
13
13
|
public var setViewSize: ((CGSize) -> Void)?
|
|
14
14
|
public var setStyleSize: ((NSNumber?, NSNumber?) -> Void)?
|
|
15
|
+
// Where the native layout system drew this view's contents, relative to its host.
|
|
16
|
+
public var setContentOrigin: ((CGPoint) -> Void)?
|
|
17
|
+
public var clearContentOrigin: (() -> Void)?
|
|
15
18
|
}
|
|
16
19
|
}
|
|
@@ -51,6 +51,12 @@ extension ExpoSwiftUI {
|
|
|
51
51
|
props.shadowNodeProxy.setStyleSize = { [weak self] width, height in
|
|
52
52
|
self?.setStyleSize(width, height: height)
|
|
53
53
|
}
|
|
54
|
+
props.shadowNodeProxy.setContentOrigin = { [weak self] origin in
|
|
55
|
+
self?.setContentOrigin(origin)
|
|
56
|
+
}
|
|
57
|
+
props.shadowNodeProxy.clearContentOrigin = { [weak self] in
|
|
58
|
+
self?.clearContentOrigin()
|
|
59
|
+
}
|
|
54
60
|
|
|
55
61
|
installEventDispatchers()
|
|
56
62
|
}
|
|
@@ -213,6 +219,12 @@ extension ExpoSwiftUI {
|
|
|
213
219
|
props.shadowNodeProxy.setStyleSize = { [weak self] width, height in
|
|
214
220
|
self?.setStyleSize(width, height: height)
|
|
215
221
|
}
|
|
222
|
+
props.shadowNodeProxy.setContentOrigin = { [weak self] origin in
|
|
223
|
+
self?.setContentOrigin(origin)
|
|
224
|
+
}
|
|
225
|
+
props.shadowNodeProxy.clearContentOrigin = { [weak self] in
|
|
226
|
+
self?.clearContentOrigin()
|
|
227
|
+
}
|
|
216
228
|
|
|
217
229
|
installEventDispatchers()
|
|
218
230
|
}
|
|
@@ -14,6 +14,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
14
14
|
@property (nonatomic) NSInteger tag;
|
|
15
15
|
@property (nonatomic, copy, nullable) NSString *componentName;
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
The tag this view last published a content origin under.
|
|
19
|
+
|
|
20
|
+
React Native zeroes `tag` when it recycles a component view, and it does so *before* calling
|
|
21
|
+
`prepareForRecycle` or `invalidate`, so a teardown hook cannot use `tag` to find its own registry
|
|
22
|
+
entry. Remembering it here is what lets the entry be removed rather than leaked.
|
|
23
|
+
*/
|
|
24
|
+
@property (nonatomic) NSInteger publishedContentOriginTag;
|
|
25
|
+
|
|
17
26
|
- (void)dispatchEvent:(nonnull NSString *)eventName payload:(nullable id)payload;
|
|
18
27
|
|
|
19
28
|
- (void)updateProps:(nonnull NSDictionary<NSString *, id> *)props NS_SWIFT_UI_ACTOR;
|
|
@@ -24,6 +33,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
24
33
|
|
|
25
34
|
- (void)setStyleSize:(nullable NSNumber *)width height:(nullable NSNumber *)height;
|
|
26
35
|
|
|
36
|
+
/**
|
|
37
|
+
Publishes where SwiftUI drew this view's contents, relative to its host, so `measure()` matches
|
|
38
|
+
what is on screen. Pass `CGPointZero`-equivalent by calling `clearContentOrigin`.
|
|
39
|
+
*/
|
|
40
|
+
- (void)setContentOrigin:(CGPoint)contentOrigin;
|
|
41
|
+
|
|
42
|
+
- (void)clearContentOrigin;
|
|
43
|
+
|
|
27
44
|
- (BOOL)supportsPropWithName:(nonnull NSString *)name;
|
|
28
45
|
|
|
29
46
|
/*
|
|
@@ -17,6 +17,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
17
17
|
// `tag` is inherited from UIView
|
|
18
18
|
@property (nonatomic, copy, nullable) NSString *componentName;
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
The tag this view last published a content origin under.
|
|
22
|
+
|
|
23
|
+
React Native zeroes `tag` when it recycles a component view, and it does so *before* calling
|
|
24
|
+
`prepareForRecycle` or `invalidate`, so a teardown hook cannot use `tag` to find its own registry
|
|
25
|
+
entry. Remembering it here is what lets the entry be removed rather than leaked.
|
|
26
|
+
*/
|
|
27
|
+
@property (nonatomic) NSInteger publishedContentOriginTag;
|
|
28
|
+
|
|
20
29
|
- (void)dispatchEvent:(nonnull NSString *)eventName payload:(nullable id)payload;
|
|
21
30
|
|
|
22
31
|
- (void)updateProps:(nonnull NSDictionary<NSString *, id> *)props NS_SWIFT_UI_ACTOR;
|
|
@@ -27,6 +36,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
27
36
|
|
|
28
37
|
- (void)setStyleSize:(nullable NSNumber *)width height:(nullable NSNumber *)height;
|
|
29
38
|
|
|
39
|
+
- (void)setContentOrigin:(CGPoint)contentOrigin;
|
|
40
|
+
|
|
41
|
+
- (void)clearContentOrigin;
|
|
42
|
+
|
|
30
43
|
- (BOOL)supportsPropWithName:(nonnull NSString *)name;
|
|
31
44
|
|
|
32
45
|
/*
|
|
@@ -98,6 +98,7 @@ namespace react = facebook::react;
|
|
|
98
98
|
- (void)prepareForRecycle
|
|
99
99
|
{
|
|
100
100
|
// Default implementation does nothing.
|
|
101
|
+
[self clearContentOrigin];
|
|
101
102
|
_eventEmitter.reset();
|
|
102
103
|
}
|
|
103
104
|
|
|
@@ -186,6 +187,23 @@ namespace react = facebook::react;
|
|
|
186
187
|
}
|
|
187
188
|
}
|
|
188
189
|
|
|
190
|
+
- (void)setContentOrigin:(CGPoint)contentOrigin
|
|
191
|
+
{
|
|
192
|
+
self.publishedContentOriginTag = self.tag;
|
|
193
|
+
expo::ContentOriginRegistry::set(
|
|
194
|
+
(react::Tag)self.tag,
|
|
195
|
+
react::Point{.x = (react::Float)contentOrigin.x, .y = (react::Float)contentOrigin.y});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
- (void)clearContentOrigin
|
|
199
|
+
{
|
|
200
|
+
// Not `self.tag`: by the time a teardown hook runs, React Native has already zeroed it.
|
|
201
|
+
if (self.publishedContentOriginTag != 0) {
|
|
202
|
+
expo::ContentOriginRegistry::clear((react::Tag)self.publishedContentOriginTag);
|
|
203
|
+
self.publishedContentOriginTag = 0;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
189
207
|
- (BOOL)supportsPropWithName:(nonnull NSString *)name
|
|
190
208
|
{
|
|
191
209
|
// Implemented in `SwiftUIVirtualView.swift`
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
NS_SWIFT_NAME(ContentOriginRegistry)
|
|
8
|
+
@interface EXContentOriginRegistry : NSObject
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
Drops every published content origin
|
|
12
|
+
*/
|
|
13
|
+
+ (void)clearAll;
|
|
14
|
+
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright 2025-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
#import <ExpoModulesCore/EXContentOriginRegistry.h>
|
|
4
|
+
#import <ExpoModulesCore/ContentOriginRegistry.h>
|
|
5
|
+
|
|
6
|
+
@implementation EXContentOriginRegistry
|
|
7
|
+
|
|
8
|
+
+ (void)clearAll
|
|
9
|
+
{
|
|
10
|
+
expo::ContentOriginRegistry::clearAll();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "57.0.
|
|
3
|
+
"version": "57.0.14",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@expo/expo-modules-macros-plugin": "0.6.1",
|
|
50
|
-
"expo-modules-jsi": "~57.0.
|
|
50
|
+
"expo-modules-jsi": "~57.0.6",
|
|
51
51
|
"invariant": "^2.2.4"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@types/invariant": "^2.2.33",
|
|
67
67
|
"expo-module-scripts": "56.0.3"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "c300d2cc60c9e684e64f48d9bc90ea18a571d01d",
|
|
70
70
|
"scripts": {
|
|
71
71
|
"build": "expo-module build",
|
|
72
72
|
"clean": "expo-module clean",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -150,6 +150,13 @@ export function requireNativeViewManager<P>(
|
|
|
150
150
|
this.nativeTag = findNodeHandle(this.nativeRef.current);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
/**
|
|
154
|
+
* The underlying host component
|
|
155
|
+
*/
|
|
156
|
+
getNativeRef(): (Component & ReactNativeElement) | null {
|
|
157
|
+
return this.nativeRef.current;
|
|
158
|
+
}
|
|
159
|
+
|
|
153
160
|
render() {
|
|
154
161
|
return <ReactNativeComponent {...this.props} ref={this.nativeRef} />;
|
|
155
162
|
}
|