Skip to content

Commit

Permalink
Fix showing Modal from TopBar components in RN 62 (#6199)
Browse files Browse the repository at this point in the history
When showing React Native's Modal from a TopBar component - RNN mistakingly considered Modals as yellow boxes and removed them. Apparently this error surfaced in RN62
  • Loading branch information
guyca authored May 11, 2020
1 parent 4c1260a commit 94862ed
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static <T> List<T> findChildrenByClassRecursive(ViewGroup root, Class cla
for (int i = 0; i < root.getChildCount(); i++) {
View view = root.getChildAt(i);
if (view instanceof ViewGroup) {
ret.addAll(findChildrenByClassRecursive((ViewGroup) view, clazz));
ret.addAll(findChildrenByClassRecursive((ViewGroup) view, clazz, matcher));
}
if (clazz.isAssignableFrom(view.getClass()) && matcher.match((T) view)) {
ret.add((T) view);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public ChildControllersRegistry getChildRegistry() {
}

public ChildController(Activity activity, ChildControllersRegistry childRegistry, String id, Presenter presenter, Options initialOptions) {
super(activity, id, new NoOpYellowBoxDelegate(), initialOptions, new ViewControllerOverlay(activity));
super(activity, id, new NoOpYellowBoxDelegate(activity), initialOptions, new ViewControllerOverlay(activity));
this.presenter = presenter;
this.childRegistry = childRegistry;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.reactnativenavigation.viewcontrollers

import android.content.Context
import android.view.View

class NoOpYellowBoxDelegate(context: Context) : YellowBoxDelegate(context) {
override fun onChildViewAdded(parent: View, child: View?) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public TitleBarButtonController(Activity activity,
Button button,
TitleBarButtonCreator viewCreator,
OnClickListener onClickListener) {
super(activity, button.id, new YellowBoxDelegate(), new Options(), new ViewControllerOverlay(activity));
super(activity, button.id, new YellowBoxDelegate(activity), new Options(), new ViewControllerOverlay(activity));
this.navigationIconResolver = navigationIconResolver;
this.presenter = presenter;
this.button = button;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public Component getComponent() {
}

public TitleBarReactViewController(Activity activity, TitleBarReactViewCreator reactViewCreator, Component component) {
super(activity, CompatUtils.generateViewId() + "", new YellowBoxDelegate(), new Options(), new ViewControllerOverlay(activity));
super(activity, CompatUtils.generateViewId() + "", new YellowBoxDelegate(activity), new Options(), new ViewControllerOverlay(activity));
this.reactViewCreator = reactViewCreator;
this.component = component;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.reactnativenavigation.viewcontrollers

import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RestrictTo
import androidx.core.view.doOnPreDraw
import androidx.core.view.forEachIndexed
import androidx.core.view.get
import com.reactnativenavigation.utils.isDebug
import java.util.*

open class YellowBoxDelegate(private val context: Context, private val yellowBoxHelper: YellowBoxHelper = YellowBoxHelper()) {
constructor(context: Context) : this(context, YellowBoxHelper())

@get:RestrictTo(RestrictTo.Scope.TESTS)
var parent: ViewGroup? = null
private set
@get:RestrictTo(RestrictTo.Scope.TESTS)
val yellowBoxes: List<View>
get() = yellowBoxViews

private var isDestroyed = false
private val yellowBoxViews = ArrayList<View>()

open fun onChildViewAdded(parent: View, child: View?) {
if (!context.isDebug()) return
child?.doOnPreDraw { if (yellowBoxHelper.isYellowBox(parent, child)) onYellowBoxAdded(parent) }
}

fun onYellowBoxAdded(parent: View) {
if (isDestroyed) return
this.parent = parent as ViewGroup
for (i in 1 until parent.childCount) {
yellowBoxViews.add(parent[i])
parent.removeView(parent[i])
parent.addView(View(context), i)
}
}

fun destroy() {
isDestroyed = true
if (yellowBoxViews.isNotEmpty()) yellowBoxViews.forEach { parent?.addView(it) }
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
package com.reactnativenavigation.viewcontrollers;

import androidx.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;

import com.facebook.react.views.view.ReactViewBackgroundDrawable;
import com.reactnativenavigation.utils.ViewUtils;

class YellowBoxHelper {
import androidx.annotation.NonNull;

import static com.reactnativenavigation.utils.ViewUtils.findChildrenByClassRecursive;

public class YellowBoxHelper {
private final static int YELLOW_BOX_COLOR = -218449360;

boolean isYellowBox(View parent, View child) {
return parent instanceof ViewGroup &&
child instanceof ViewGroup &&
((ViewGroup) parent).getChildCount() > 1 &&
!ViewUtils.findChildrenByClassRecursive((ViewGroup) child, View.class, YellowBackgroundMather((ViewGroup) child)).isEmpty();
!findChildrenByClassRecursive((ViewGroup) child, View.class, YellowBackgroundMather()).isEmpty();
}

@NonNull
private static ViewUtils.Matcher<View> YellowBackgroundMather(ViewGroup vg) {
private static ViewUtils.Matcher<View> YellowBackgroundMather() {
return child1 -> child1.getBackground() instanceof ReactViewBackgroundDrawable && ((ReactViewBackgroundDrawable) child1.getBackground()).getColor() == YELLOW_BOX_COLOR;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class TopBarBackgroundViewController extends ViewController<TopBarBackgro
private Component component;

public TopBarBackgroundViewController(Activity activity, TopBarBackgroundViewCreator viewCreator) {
super(activity, CompatUtils.generateViewId() + "", new YellowBoxDelegate(), new Options(), new ViewControllerOverlay(activity));
super(activity, CompatUtils.generateViewId() + "", new YellowBoxDelegate(activity), new Options(), new ViewControllerOverlay(activity));
this.viewCreator = viewCreator;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,34 @@

import android.app.*;

public class TestApplication extends Application {
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;

import java.util.Collections;
import java.util.List;

public class TestApplication extends Application implements ReactApplication {
private final ReactNativeHost host = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return true;
}

@Override
protected List<ReactPackage> getPackages() {
return Collections.emptyList();
}
};

@Override
public void onCreate() {
super.onCreate();
setTheme(R.style.Theme_AppCompat);
}

@Override
public ReactNativeHost getReactNativeHost() {
return host;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void holdsARefToActivity() {
@Test
public void canOverrideViewCreation() {
final FrameLayout otherView = new FrameLayout(activity);
yellowBoxDelegate = spy(new YellowBoxDelegate());
yellowBoxDelegate = spy(new YellowBoxDelegate(activity));
ViewController myController = new ViewController(activity, "vc", yellowBoxDelegate, new Options(), new ViewControllerOverlay(activity)) {
@Override
protected FrameLayout createView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void beforeEach() {
yellowBox = new View(context);
parent = new FrameLayout(context);
yellowBoxHelper = Mockito.mock(YellowBoxHelper.class);
uut = new YellowBoxDelegate(yellowBoxHelper);
uut = new YellowBoxDelegate(context, yellowBoxHelper);
parent.addView(new View(context)); // We assume view at index 0 is not a yellow box
parent.addView(yellowBox);
}
Expand Down

0 comments on commit 94862ed

Please sign in to comment.