diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java index 67ea71237..8beffc672 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatShadowNode.java @@ -67,7 +67,7 @@ import com.facebook.react.uimanager.ViewProps; } /** - * Collects DrawCommands produced by this FlatShadoNode. + * Collects DrawCommands produced by this FlatShadowNode. */ protected void collectState( StateBuilder stateBuilder, diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatTextShadowNode.java index 6bea964ae..4432a78d5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatTextShadowNode.java @@ -30,6 +30,11 @@ import com.facebook.react.uimanager.ReactShadowNode; if (parent instanceof FlatTextShadowNode) { ((FlatTextShadowNode) parent).notifyChanged(shouldRemeasure); } + + if (this instanceof RCTTextInput) { + // needed to trigger onCollectExtraUpdates + markUpdated(); + } } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java index 78dcb71cc..62182d283 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/FlatUIImplementation.java @@ -58,13 +58,14 @@ public class FlatUIImplementation extends UIImplementation { TypefaceCache.setAssetManager(reactContext.getAssets()); - viewManagers = new ArrayList(viewManagers); + viewManagers = new ArrayList<>(viewManagers); viewManagers.add(new RCTViewManager()); viewManagers.add(new RCTTextManager()); viewManagers.add(new RCTRawTextManager()); viewManagers.add(new RCTVirtualTextManager()); viewManagers.add(new RCTTextInlineImageManager()); viewManagers.add(new RCTImageViewManager()); + viewManagers.add(new RCTTextInputManager()); ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers); FlatNativeViewHierarchyManager nativeViewHierarchyManager = new FlatNativeViewHierarchyManager( diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTTextInput.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTTextInput.java new file mode 100644 index 000000000..c4f942f5d --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTTextInput.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.facebook.react.flat; + +import javax.annotation.Nullable; + +import android.text.SpannableStringBuilder; + +import com.facebook.csslayout.Spacing; +import com.facebook.react.uimanager.UIViewOperationQueue; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.facebook.react.views.text.ReactTextUpdate; + +import static com.facebook.react.views.text.ReactTextShadowNode.UNSET; + +public class RCTTextInput extends RCTVirtualText { + private int mJsEventCount = UNSET; + private @Nullable float[] mComputedPadding; + + public RCTTextInput() { + forceMountToView(); + } + + @Override + public boolean isVirtual() { + return false; + } + + @Override + public boolean isVirtualAnchor() { + return true; + } + + @Override + public void setBackgroundColor(int backgroundColor) { + // suppress, this is handled by a ViewManager + } + + @Override + public void onCollectExtraUpdates(UIViewOperationQueue uiViewOperationQueue) { + super.onCollectExtraUpdates(uiViewOperationQueue); + + if (mComputedPadding != null) { + uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), mComputedPadding); + mComputedPadding = null; + } + + ReactTextUpdate reactTextUpdate = + new ReactTextUpdate(getText(), mJsEventCount, false); + uiViewOperationQueue.enqueueUpdateExtraData(getReactTag(), reactTextUpdate); + } + + @ReactProp(name = "mostRecentEventCount") + public void setMostRecentEventCount(int mostRecentEventCount) { + mJsEventCount = mostRecentEventCount; + } + + @Override + public void setPadding(int spacingType, float padding) { + super.setPadding(spacingType, padding); + mComputedPadding = spacingToFloatArray(getPadding()); + markUpdated(); + } + + private static float[] spacingToFloatArray(Spacing spacing) { + return new float[] { + spacing.get(Spacing.LEFT), + spacing.get(Spacing.TOP), + spacing.get(Spacing.RIGHT), + spacing.get(Spacing.BOTTOM), + }; + } + + /** + * Returns a new CharSequence that includes all the text and styling information to create Layout. + */ + SpannableStringBuilder getText() { + SpannableStringBuilder sb = new SpannableStringBuilder(); + collectText(sb); + applySpans(sb); + return sb; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTTextInputManager.java new file mode 100644 index 000000000..66eea3fd2 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTTextInputManager.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package com.facebook.react.flat; + +import com.facebook.react.views.textinput.ReactTextInputManager; + +/* package */ class RCTTextInputManager extends ReactTextInputManager { + + @Override + public RCTTextInput createShadowNodeInstance() { + return new RCTTextInput(); + } + + @Override + public Class getShadowNodeClass() { + return RCTTextInput.class; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java b/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java index f0622089d..ff0480127 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/StateBuilder.java @@ -9,14 +9,14 @@ package com.facebook.react.flat; -import java.util.ArrayList; - import javax.annotation.Nullable; +import java.util.ArrayList; + import com.facebook.csslayout.CSSNode; import com.facebook.csslayout.Spacing; -import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.OnLayoutEvent; +import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.events.EventDispatcher; /** @@ -240,7 +240,11 @@ import com.facebook.react.uimanager.events.EventDispatcher; isAndroidView, needsCustomLayoutForChildren); - if (node.isVirtualAnchor()) { + // this is a temporary measure to skip adding node regions for RCTTextInput. This will be fixed + // in a patch soon which will convert AndroidView into an interface, thus allowing RCTTextInput + // to be treated as an AndroidView + boolean skipAddingNodeRegion = node instanceof RCTTextInput; + if (!isAndroidView && node.isVirtualAnchor() && !skipAddingNodeRegion) { // If RCTText is mounted to View, virtual children will not receive any touch events // because they don't get added to nodeRegions, so nodeRegions will be empty and // FlatViewGroup.reactTagForTouch() will always return RCTText's id. To fix the issue, @@ -276,6 +280,11 @@ import com.facebook.react.uimanager.events.EventDispatcher; nodeRegions); } + if (node.hasUpdates()) { + node.onCollectExtraUpdates(mOperationsQueue); + node.markUpdateSeen(); + } + final FlatShadowNode[] nativeChildren = mNativeChildren.finish(); if (nativeChildren != null) { updateNativeChildren(node, tag, node.getNativeChildren(), nativeChildren);