Permalink
Browse files

allow finding the rootTag of any reactTag inside UIManager

Summary: added API to in UIManager to find the rootTag/View of any reactTag based on its layout (shadow views) hierarchy (not to be used by JS)

Reviewed By: javache

Differential Revision: D3750410

fbshipit-source-id: 68611e39930d53ece478f25245ddc7f7838daaa6
  • Loading branch information...
1 parent 6729df3 commit 35e7a266db1927d6b3efd5e8b43394518ec86f59 @fkgozali fkgozali committed with Facebook Github Bot 9 Aug 29, 2016
@@ -91,6 +91,17 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
- (void)addUIBlock:(RCTViewManagerUIBlock)block;
/**
+ * Given a reactTag from a component, find its root view, if possible.
+ * Otherwise, this will give back nil.
+ *
+ * @param reactTag the component tag
+ * @param completion the completion block that will hand over the rootView, if any.
+ *
+ * @return the rootView
+ */
+- (void)rootViewForReactTag:(NSNumber *)reactTag withCompletion:(void (^)(UIView *view))completion;
+
+/**
* The view that is currently first responder, according to the JS context.
*/
+ (UIView *)JSResponder;
@@ -1549,6 +1549,54 @@ static void RCTMeasureLayout(RCTShadowView *view,
}];
}
+- (void)rootViewForReactTag:(NSNumber *)reactTag withCompletion:(void (^)(UIView *view))completion
+{
+ RCTAssertMainQueue();
+ RCTAssert(completion != nil, @"Attempted to resolve rootView for tag %@ without a completion block", reactTag);
+
+ if (reactTag == nil) {
+ completion(nil);
+ return;
+ }
+
+ dispatch_async(RCTGetUIManagerQueue(), ^{
+ NSNumber *rootTag = [self _rootTagForReactTag:reactTag];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UIView *rootView = nil;
+ if (rootTag != nil) {
+ rootView = [self viewForReactTag:rootTag];
+ }
+ completion(rootView);
+ });
+ });
+}
+
+- (NSNumber *)_rootTagForReactTag:(NSNumber *)reactTag
+{
+ RCTAssert(!RCTIsMainQueue(), @"Should be called on shadow queue");
+
+ if (reactTag == nil) {
+ return nil;
+ }
+
+ if (RCTIsReactRootView(reactTag)) {
+ return reactTag;
+ }
+
+ NSNumber *rootTag = nil;
+ RCTShadowView *shadowView = _shadowViewRegistry[reactTag];
+ while (shadowView) {
+ RCTShadowView *parent = [shadowView reactSuperview];
+ if (!parent && RCTIsReactRootView(shadowView.reactTag)) {
+ rootTag = shadowView.reactTag;
+ break;
+ }
+ shadowView = parent;
+ }
+
+ return rootTag;
+}
+
static UIView *_jsResponder;
+ (UIView *)JSResponder
@@ -13,6 +13,7 @@
import java.util.Arrays;
import java.util.List;
+import com.facebook.common.logging.FLog;
import com.facebook.csslayout.CSSLayoutContext;
import com.facebook.csslayout.CSSDirection;
import com.facebook.infer.annotation.Assertions;
@@ -24,6 +25,7 @@
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableArray;
+import com.facebook.react.common.ReactConstants;
import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener;
import com.facebook.react.uimanager.events.EventDispatcher;
@@ -575,7 +577,6 @@ public void configureNextLayoutAnimation(
mOperationsQueue.enqueueConfigureLayoutAnimation(config, success, error);
}
-
public void setJSResponder(int reactTag, boolean blockNativeResponder) {
assertViewExists(reactTag, "setJSResponder");
ReactShadowNode node = mShadowNodeRegistry.getNode(reactTag);
@@ -789,4 +790,22 @@ protected void applyUpdatesRecursive(
public void addUIBlock(UIBlock block) {
mOperationsQueue.enqueueUIBlock(block);
}
+
+ public int resolveRootTagFromReactTag(int reactTag) {
+ if (mShadowNodeRegistry.isRootNode(reactTag)) {
+ return reactTag;
+ }
+
+ ReactShadowNode node = resolveShadowNode(reactTag);
+ int rootTag = 0;
+ if (node != null) {
+ rootTag = node.getRootNode().getReactTag();
+ } else {
+ FLog.w(
+ ReactConstants.TAG,
+ "Warning : attempted to resolve a non-existent react shadow node. reactTag=" + reactTag);
+ }
+
+ return rootTag;
+ }
}
@@ -518,4 +518,17 @@ public void execute (NativeViewHierarchyManager nvhm) {
public void addUIBlock (UIBlock block) {
mUIImplementation.addUIBlock(block);
}
+
+ /**
+ * Given a reactTag from a component, find its root node tag, if possible.
+ * Otherwise, this will return 0. If the reactTag belongs to a root node, this
+ * will return the same reactTag.
+ *
+ * @param reactTag the component tag
+ *
+ * @return the rootTag
+ */
+ public int resolveRootTagFromReactTag(int reactTag) {
+ return mUIImplementation.resolveRootTagFromReactTag(reactTag);
+ }
}

0 comments on commit 35e7a26

Please sign in to comment.