Skip to content

Commit dd8d9d2

Browse files
committed
measureViewByNativeId for ios
1 parent 4a42785 commit dd8d9d2

File tree

2 files changed

+198
-151
lines changed

2 files changed

+198
-151
lines changed

ios/JsiViewHelpers.mm

Lines changed: 197 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -54,164 +54,211 @@ @implementation JsiViewHelpers
5454
jsi::Runtime *_runtime;
5555

5656
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) {
57-
NSLog(@"Installing JsiViewHelpers polyfill Bindings...");
58-
59-
_bridge = [RCTBridge currentBridge];
60-
_cxxBridge = (RCTCxxBridge*)_bridge;
61-
if (_cxxBridge == nil) return @false;
62-
_runtime = (jsi::Runtime*) _cxxBridge.runtime;
63-
if (_runtime == nil) return @false;
64-
auto& runtime = *_runtime;
65-
66-
67-
auto measureText = jsi::Function::createFromHostFunction(runtime,
68-
jsi::PropNameID::forUtf8(runtime, "measureText"),
69-
1,
70-
[](jsi::Runtime& runtime,
71-
const jsi::Value& thisArg,
72-
const jsi::Value* args,
73-
size_t count) -> jsi::Value {
74-
auto params = args[0].asObject(runtime);
75-
auto rawText = params.getProperty(runtime, "text").asString(runtime).utf8(runtime);
76-
auto fontSize = params.getProperty(runtime, "fontSize").asNumber();
77-
auto width = params.getProperty(runtime, "maxWidth").asNumber();
78-
auto allowFontScaling = true;
79-
auto usePreciseWidth = false;
80-
81-
if (params.hasProperty(runtime, "allowFontScaling")) {
82-
allowFontScaling = params.getProperty(runtime, "allowFontScaling").getBool();
83-
}
84-
85-
if (params.hasProperty(runtime, "usePreciseWidth")) {
86-
usePreciseWidth = params.getProperty(runtime, "usePreciseWidth").getBool();
87-
}
88-
89-
NSString *fontFamily = nil;
90-
if (params.hasProperty(runtime, "fontFamily")) {
91-
auto pr = params.getProperty(runtime, "fontFamily");
92-
if (!(pr.isUndefined() || pr.isNull())) {
93-
auto rawFontFamily = pr.asString(runtime).utf8(runtime);
94-
fontFamily = [NSString stringWithUTF8String:rawFontFamily.c_str()];
95-
}
96-
}
97-
98-
NSString *weight = nil;
99-
if (params.hasProperty(runtime, "weight")) {
100-
auto pr = params.getProperty(runtime, "weight");
101-
if (!(pr.isUndefined() || pr.isNull())) {
102-
auto rawWeight = pr.asString(runtime).utf8(runtime);
103-
weight = [NSString stringWithUTF8String:rawWeight.c_str()];
104-
}
105-
}
106-
107-
auto text = [NSString stringWithUTF8String:rawText.c_str()];
108-
109-
auto result = [[[RNTextSize alloc] init] measure:text
110-
width:[[NSNumber alloc] initWithDouble:width]
111-
fontSize:[[NSNumber alloc] initWithDouble:fontSize]
112-
usePreciseWidth:usePreciseWidth
113-
allowFontScaling:allowFontScaling
114-
fontFamily:fontFamily
115-
weight:weight];
116-
117-
return convertNSDictionaryToJSIObject(runtime, result);
118-
});
119-
120-
auto measureView = jsi::Function::createFromHostFunction(runtime,
121-
jsi::PropNameID::forUtf8(runtime, "measureView"),
122-
1,
123-
[self](jsi::Runtime& runtime,
124-
const jsi::Value& thisArg,
125-
const jsi::Value* args,
126-
size_t count) -> jsi::Value {
127-
128-
auto viewId = args[0].asNumber();
129-
__block CGRect viewFrame = CGRectZero;
130-
__block CGRect globalBounds = CGRectZero;
131-
dispatch_sync(dispatch_get_main_queue(), ^{
132-
auto idNumber = [[NSNumber alloc] initWithDouble:viewId];
133-
auto view = [_bridge.uiManager viewForReactTag: idNumber];
134-
UIView *rootView = view;
135-
if (view != nil) {
136-
viewFrame = view.frame;
137-
while (rootView.superview && ![rootView isReactRootView]) {
138-
rootView = rootView.superview;
139-
}
140-
if (rootView) {
141-
globalBounds = [view convertRect:view.bounds toView:rootView];
142-
}
143-
}
144-
});
145-
146-
147-
148-
if (CGRectIsEmpty(globalBounds)) return jsi::Value::undefined();
149-
150-
jsi::Object result = jsi::Object(runtime);
151-
result.setProperty(runtime, "width", jsi::Value(globalBounds.size.width));
152-
result.setProperty(runtime, "height", jsi::Value(globalBounds.size.height));
153-
result.setProperty(runtime, "x", jsi::Value(globalBounds.origin.x));
154-
result.setProperty(runtime, "y", jsi::Value(globalBounds.origin.y));
155-
156-
return result;
157-
});
158-
159-
auto scrollToChild = jsi::Function::createFromHostFunction(runtime,
160-
jsi::PropNameID::forUtf8(runtime, "scrollToChild"),
161-
1,
162-
[](jsi::Runtime& runtime,
57+
NSLog(@"Installing JsiViewHelpers polyfill Bindings...");
58+
59+
_bridge = [RCTBridge currentBridge];
60+
_cxxBridge = (RCTCxxBridge*)_bridge;
61+
if (_cxxBridge == nil) return @false;
62+
_runtime = (jsi::Runtime*) _cxxBridge.runtime;
63+
if (_runtime == nil) return @false;
64+
auto& runtime = *_runtime;
65+
66+
67+
auto measureText = jsi::Function::createFromHostFunction(runtime,
68+
jsi::PropNameID::forUtf8(runtime, "measureText"),
69+
1,
70+
[](jsi::Runtime& runtime,
71+
const jsi::Value& thisArg,
72+
const jsi::Value* args,
73+
size_t count) -> jsi::Value {
74+
auto params = args[0].asObject(runtime);
75+
auto rawText = params.getProperty(runtime, "text").asString(runtime).utf8(runtime);
76+
auto fontSize = params.getProperty(runtime, "fontSize").asNumber();
77+
auto width = params.getProperty(runtime, "maxWidth").asNumber();
78+
auto allowFontScaling = true;
79+
auto usePreciseWidth = false;
80+
81+
if (params.hasProperty(runtime, "allowFontScaling")) {
82+
allowFontScaling = params.getProperty(runtime, "allowFontScaling").getBool();
83+
}
84+
85+
if (params.hasProperty(runtime, "usePreciseWidth")) {
86+
usePreciseWidth = params.getProperty(runtime, "usePreciseWidth").getBool();
87+
}
88+
89+
NSString *fontFamily = nil;
90+
if (params.hasProperty(runtime, "fontFamily")) {
91+
auto rawFontFamily = params.getProperty(runtime, "fontFamily").asString(runtime).utf8(runtime);
92+
fontFamily = [NSString stringWithUTF8String:rawFontFamily.c_str()];
93+
}
94+
95+
NSString *weight = nil;
96+
if (params.hasProperty(runtime, "weight")) {
97+
auto rawWeight = params.getProperty(runtime, "weight").asString(runtime).utf8(runtime);
98+
weight = [NSString stringWithUTF8String:rawWeight.c_str()];
99+
}
100+
101+
auto text = [NSString stringWithUTF8String:rawText.c_str()];
102+
103+
auto result = [[[RNTextSize alloc] init] measure:text
104+
width:[[NSNumber alloc] initWithDouble:width]
105+
fontSize:[[NSNumber alloc] initWithDouble:fontSize]
106+
usePreciseWidth:usePreciseWidth
107+
allowFontScaling:allowFontScaling
108+
fontFamily:fontFamily
109+
weight:weight];
110+
111+
return convertNSDictionaryToJSIObject(runtime, result);
112+
});
113+
114+
auto measureView = jsi::Function::createFromHostFunction(runtime,
115+
jsi::PropNameID::forUtf8(runtime, "measureView"),
116+
1,
117+
[self](jsi::Runtime& runtime,
118+
const jsi::Value& thisArg,
119+
const jsi::Value* args,
120+
size_t count) -> jsi::Value {
121+
122+
auto viewId = args[0].asNumber();
123+
__block CGRect viewFrame = CGRectZero;
124+
__block CGRect globalBounds = CGRectZero;
125+
dispatch_sync(dispatch_get_main_queue(), ^{
126+
auto idNumber = [[NSNumber alloc] initWithDouble:viewId];
127+
auto view = [_bridge.uiManager viewForReactTag: idNumber];
128+
UIView *rootView = view;
129+
if (view != nil) {
130+
viewFrame = view.frame;
131+
while (rootView.superview && ![rootView isReactRootView]) {
132+
rootView = rootView.superview;
133+
}
134+
if (rootView) {
135+
globalBounds = [view convertRect:view.bounds toView:rootView];
136+
}
137+
}
138+
});
139+
140+
141+
142+
if (CGRectIsEmpty(globalBounds)) return jsi::Value::undefined();
143+
144+
jsi::Object result = jsi::Object(runtime);
145+
result.setProperty(runtime, "width", jsi::Value(globalBounds.size.width));
146+
result.setProperty(runtime, "height", jsi::Value(globalBounds.size.height));
147+
result.setProperty(runtime, "x", jsi::Value(globalBounds.origin.x));
148+
result.setProperty(runtime, "y", jsi::Value(globalBounds.origin.y));
149+
150+
return result;
151+
});
152+
153+
auto measureViewByNativeId = jsi::Function::createFromHostFunction(runtime,
154+
jsi::PropNameID::forUtf8(runtime, "measureViewByNativeId"),
155+
1,
156+
[self](jsi::Runtime& runtime,
163157
const jsi::Value& thisArg,
164158
const jsi::Value* args,
165159
size_t count) -> jsi::Value {
166-
167-
168-
auto params = args[0].asObject(runtime);
169-
auto childId = params.getProperty(runtime, "childNativeID").asString(runtime).utf8(runtime);
170-
auto offset = params.getProperty(runtime, "offset").asNumber();
171-
auto scrollToEnd = params.getProperty(runtime, "scrollToEnd").getBool();
172-
173-
auto scrollId = params.getProperty(runtime, "scrollViewId");
174-
auto scrollNativeId = params.getProperty(runtime, "scrollNativeID");
175-
NSNumber* refScrollId;
176-
NSString* nativeScrollId;
177-
NSString* nativeChildId = [[NSString alloc] initWithCString:childId.c_str() encoding:NSUTF8StringEncoding];
160+
161+
auto viewId = args[0].asString(runtime).utf8(runtime);
162+
__block CGRect viewFrame = CGRectZero;
163+
__block CGRect globalBounds = CGRectZero;
164+
165+
NSString* nativeViewId = [[NSString alloc] initWithCString:viewId.c_str() encoding:NSUTF8StringEncoding];
166+
167+
dispatch_sync(dispatch_get_main_queue(), ^{
168+
169+
UIView* parent = RCTKeyWindow().rootViewController.view;
170+
UIView* view = [Scroller findInParent:parent nativeID:nativeViewId];
171+
auto presented = RCTPresentedViewController();
172+
if (!view && presented && presented.view) {
173+
view = [Scroller findInParent:presented.view nativeID:nativeViewId];
174+
}
178175

179-
if (!scrollId.isNull() && !scrollId.isUndefined()) {
180-
refScrollId = [[NSNumber alloc] initWithDouble:scrollId.asNumber()];
181-
} else if (!scrollNativeId.isNull() && !scrollNativeId.isUndefined()) {
182-
nativeScrollId = [[NSString alloc] initWithCString:scrollNativeId.asString(runtime).utf8(runtime).c_str() encoding:NSUTF8StringEncoding];
176+
UIView *rootView = view;
177+
if (view != nil) {
178+
viewFrame = view.frame;
179+
while (rootView.superview && ![rootView isReactRootView]) {
180+
rootView = rootView.superview;
183181
}
184-
185-
dispatch_async(dispatch_get_main_queue(), ^{
186-
RCTScrollView *foundScrollView;
187-
if (refScrollId != NULL) {
188-
UIView* view = [_bridge.uiManager viewForReactTag:refScrollId];
189-
foundScrollView = (RCTScrollView*)view;
190-
} else if (nativeScrollId != NULL) {
191-
UIView* parent = UIApplication.sharedApplication.keyWindow.rootViewController.view;
192-
UIView* view = [Scroller findInParent:parent nativeID:nativeScrollId];
193-
foundScrollView = (RCTScrollView*)view;
194-
}
195-
196-
if (foundScrollView == NULL) return;
197-
UIView* childView = [Scroller findInParent:foundScrollView nativeID:nativeChildId];
198-
[Scroller scrollToView:foundScrollView.scrollView
199-
view:childView
200-
offset:CGFloat(offset)
201-
scrollToEnd:scrollToEnd
202-
animated:true];
203-
});
204-
205-
return jsi::Value::undefined();
182+
if (rootView) {
183+
globalBounds = [view convertRect:view.bounds toView:rootView];
184+
}
185+
}
206186
});
207187

208-
jsi::Object viewHelpers = jsi::Object(runtime);
209-
viewHelpers.setProperty(runtime, "measureView", std::move(measureView));
210-
viewHelpers.setProperty(runtime, "measureText", std::move(measureText));
211-
viewHelpers.setProperty(runtime, "scrollToChild", std::move(scrollToChild));
212-
runtime.global().setProperty(runtime, "__viewHelpers", std::move(viewHelpers));
213188

214-
return @true;
189+
190+
if (CGRectIsEmpty(globalBounds)) return jsi::Value::undefined();
191+
192+
jsi::Object result = jsi::Object(runtime);
193+
result.setProperty(runtime, "width", jsi::Value(globalBounds.size.width));
194+
result.setProperty(runtime, "height", jsi::Value(globalBounds.size.height));
195+
result.setProperty(runtime, "x", jsi::Value(globalBounds.origin.x));
196+
result.setProperty(runtime, "y", jsi::Value(globalBounds.origin.y));
197+
198+
return result;
199+
});
200+
201+
auto scrollToChild = jsi::Function::createFromHostFunction(runtime,
202+
jsi::PropNameID::forUtf8(runtime, "scrollToChild"),
203+
1,
204+
[](jsi::Runtime& runtime,
205+
const jsi::Value& thisArg,
206+
const jsi::Value* args,
207+
size_t count) -> jsi::Value {
208+
209+
210+
auto params = args[0].asObject(runtime);
211+
auto childId = params.getProperty(runtime, "childNativeID").asString(runtime).utf8(runtime);
212+
auto offset = params.getProperty(runtime, "offset").asNumber();
213+
auto scrollToEnd = params.getProperty(runtime, "scrollToEnd").getBool();
214+
215+
auto scrollId = params.getProperty(runtime, "scrollViewId");
216+
auto scrollNativeId = params.getProperty(runtime, "scrollNativeID");
217+
NSNumber* refScrollId;
218+
NSString* nativeScrollId;
219+
NSString* nativeChildId = [[NSString alloc] initWithCString:childId.c_str() encoding:NSUTF8StringEncoding];
220+
221+
if (!scrollId.isNull() && !scrollId.isUndefined()) {
222+
refScrollId = [[NSNumber alloc] initWithDouble:scrollId.asNumber()];
223+
} else if (!scrollNativeId.isNull() && !scrollNativeId.isUndefined()) {
224+
nativeScrollId = [[NSString alloc] initWithCString:scrollNativeId.asString(runtime).utf8(runtime).c_str() encoding:NSUTF8StringEncoding];
225+
}
226+
227+
dispatch_async(dispatch_get_main_queue(), ^{
228+
RCTScrollView *foundScrollView;
229+
if (refScrollId != NULL) {
230+
UIView* view = [_bridge.uiManager viewForReactTag:refScrollId];
231+
foundScrollView = (RCTScrollView*)view;
232+
} else if (nativeScrollId != NULL) {
233+
UIView* parent = RCTKeyWindow().rootViewController.view;
234+
UIView* view = [Scroller findInParent:parent nativeID:nativeScrollId];
235+
auto presented = RCTPresentedViewController();
236+
if (!view && presented && presented.view) {
237+
view = [Scroller findInParent:presented.view nativeID:nativeScrollId];
238+
}
239+
foundScrollView = (RCTScrollView*)view;
240+
}
241+
242+
if (foundScrollView == NULL) return;
243+
UIView* childView = [Scroller findInParent:foundScrollView nativeID:nativeChildId];
244+
[Scroller scrollToView:foundScrollView.scrollView
245+
view:childView
246+
offset:CGFloat(offset)
247+
scrollToEnd:scrollToEnd
248+
animated:true];
249+
});
250+
251+
return jsi::Value::undefined();
252+
});
253+
254+
jsi::Object viewHelpers = jsi::Object(runtime);
255+
viewHelpers.setProperty(runtime, "measureView", std::move(measureView));
256+
viewHelpers.setProperty(runtime, "measureViewByNativeId", std::move(measureViewByNativeId));
257+
viewHelpers.setProperty(runtime, "measureText", std::move(measureText));
258+
viewHelpers.setProperty(runtime, "scrollToChild", std::move(scrollToChild));
259+
runtime.global().setProperty(runtime, "__viewHelpers", std::move(viewHelpers));
260+
261+
return @true;
215262
}
216263

217264
@end

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-jsi-view-helpers",
3-
"version": "1.0.9",
3+
"version": "1.0.10",
44
"description": "React Native Jsi view helpers",
55
"main": "src/index",
66
"module": "src/index",

0 commit comments

Comments
 (0)