Skip to content

Commit

Permalink
Android: Use ColorPropConverter to enable PlatformColor on RN63 (#6490)
Browse files Browse the repository at this point in the history
See https://reactnative.dev/docs/platformcolor for an intro to PlatformColor

Internally react-native uses ColorPropConverter to convert the color on Android. Since it was added in RN63, this PR adds a new build flavor.

ColorPropConverter expects a Context object to resolve named colors from resources. Thus, context is now drilled down into the parser.

ColorPropConverter expects the color to be of type ReadableMap. Since we use JSONObject internally, I added methods to JSONParser to convert those back into the react-native Map format.

Related to #6113

Co-authored-by: Guy Carmeli <guyca@users.noreply.github.com>
  • Loading branch information
danilobuerger and guyca authored Aug 23, 2020
1 parent 5dfbcfe commit d7ba3ff
Show file tree
Hide file tree
Showing 34 changed files with 466 additions and 100 deletions.
8 changes: 7 additions & 1 deletion lib/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ android {
dimension "RNN.reactNativeVersion"
buildConfigField("int", "REACT_NATVE_VERSION_MINOR", "62")
}
reactNative63 {
dimension "RNN.reactNativeVersion"
buildConfigField("int", "REACT_NATVE_VERSION_MINOR", "63")
}
}

def flavor = resolveFlavor()
Expand All @@ -109,7 +113,9 @@ String resolveFlavor() {
Integer reactNativeMinorComponent = reactNativeVersionComponents[1].toInteger()
Integer reactNativePatchComponent = reactNativeVersionComponents[2].toInteger()

if (reactNativeMinorComponent >= 62) {
if (reactNativeMinorComponent >= 63) {
return "reactNative63"
} else if (reactNativeMinorComponent >= 62) {
return "reactNative62"
} else if (reactNativeMinorComponent >= 60) {
return "reactNative60"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.reactnativenavigation.options;

import android.content.Context;

import com.reactnativenavigation.options.params.Bool;
import com.reactnativenavigation.options.params.NullBool;
import com.reactnativenavigation.options.params.Text;
Expand All @@ -11,7 +13,7 @@
import org.json.JSONObject;

public class BackButton extends ButtonOptions {
public static BackButton parse(JSONObject json) {
public static BackButton parse(Context context, JSONObject json) {
BackButton result = new BackButton();
if (json == null || json.toString().equals("{}")) return result;

Expand All @@ -22,8 +24,8 @@ public static BackButton parse(JSONObject json) {
result.id = json.optString("id", Constants.BACK_BUTTON_ID);
result.enabled = BoolParser.parse(json, "enabled");
result.disableIconTint = BoolParser.parse(json, "disableIconTint");
result.color = ColorParser.parse(json, "color");
result.disabledColor = ColorParser.parse(json, "disabledColor");
result.color = ColorParser.parse(context, json, "color");
result.disabledColor = ColorParser.parse(context, json, "disabledColor");
result.testId = TextParser.parse(json, "testID");

return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.reactnativenavigation.options;

import android.content.Context;
import android.graphics.Typeface;

import com.reactnativenavigation.options.params.Bool;
Expand All @@ -23,25 +24,25 @@

public class BottomTabOptions {

public static BottomTabOptions parse(TypefaceLoader typefaceManager, JSONObject json) {
public static BottomTabOptions parse(Context context, TypefaceLoader typefaceManager, JSONObject json) {
BottomTabOptions options = new BottomTabOptions();
if (json == null) return options;

options.text = TextParser.parse(json, "text");
options.textColor = ColorParser.parse(json, "textColor");
options.selectedTextColor = ColorParser.parse(json, "selectedTextColor");
options.textColor = ColorParser.parse(context, json, "textColor");
options.selectedTextColor = ColorParser.parse(context, json, "selectedTextColor");
options.icon = IconParser.parse(json, "icon");
options.selectedIcon = IconParser.parse(json, "selectedIcon");
options.iconColor = ColorParser.parse(json, "iconColor");
options.selectedIconColor = ColorParser.parse(json, "selectedIconColor");
options.iconColor = ColorParser.parse(context, json, "iconColor");
options.selectedIconColor = ColorParser.parse(context, json, "selectedIconColor");
options.badge = TextParser.parse(json, "badge");
options.badgeColor = ColorParser.parse(json, "badgeColor");
options.badgeColor = ColorParser.parse(context, json, "badgeColor");
options.animateBadge = BoolParser.parse(json, "animateBadge");
options.testId = TextParser.parse(json, "testID");
options.fontFamily = typefaceManager.getTypeFace(json.optString("fontFamily", ""));
options.fontSize = NumberParser.parse(json, "fontSize");
options.selectedFontSize = NumberParser.parse(json, "selectedFontSize");
options.dotIndicator = DotIndicatorOptions.parse(json.optJSONObject("dotIndicator"));
options.dotIndicator = DotIndicatorOptions.parse(context, json.optJSONObject("dotIndicator"));
options.selectTabOnPress = BoolParser.parse(json, "selectTabOnPress");

return options;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.reactnativenavigation.options;

import android.content.Context;

import com.reactnativenavigation.options.params.Bool;
import com.reactnativenavigation.options.params.Colour;
import com.reactnativenavigation.options.params.Fraction;
Expand All @@ -21,11 +23,11 @@

public class BottomTabsOptions {

public static BottomTabsOptions parse(JSONObject json) {
public static BottomTabsOptions parse(Context context, JSONObject json) {
BottomTabsOptions options = new BottomTabsOptions();
if (json == null) return options;

options.backgroundColor = ColorParser.parse(json, "backgroundColor");
options.backgroundColor = ColorParser.parse(context, json, "backgroundColor");
options.currentTabId = TextParser.parse(json, "currentTabId");
options.currentTabIndex = NumberParser.parse(json,"currentTabIndex");
options.hideOnScroll = BoolParser.parse(json, "hideOnScroll");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.reactnativenavigation.options;

import android.content.Context;
import android.graphics.Typeface;
import android.view.MenuItem;

Expand Down Expand Up @@ -68,7 +69,7 @@ public boolean equals(ButtonOptions other) {
component.equals(other.component);
}

private static ButtonOptions parseJson(JSONObject json, TypefaceLoader typefaceManager) {
private static ButtonOptions parseJson(Context context, JSONObject json, TypefaceLoader typefaceManager) {
ButtonOptions button = new ButtonOptions();
button.id = take(json.optString("id"), "btn" + CompatUtils.generateViewId());
button.accessibilityLabel = TextParser.parse(json, "accessibilityLabel");
Expand All @@ -77,8 +78,8 @@ private static ButtonOptions parseJson(JSONObject json, TypefaceLoader typefaceM
button.enabled = BoolParser.parse(json, "enabled");
button.disableIconTint = BoolParser.parse(json, "disableIconTint");
button.showAsAction = parseShowAsAction(json);
button.color = ColorParser.parse(json, "color");
button.disabledColor = ColorParser.parse(json, "disabledColor");
button.color = ColorParser.parse(context, json, "color");
button.disabledColor = ColorParser.parse(context, json, "disabledColor");
button.fontSize = FractionParser.parse(json, "fontSize");
button.fontFamily = typefaceManager.getTypeFace(json.optString("fontFamily", ""));
button.fontWeight = TextParser.parse(json, "fontWeight");
Expand All @@ -92,26 +93,26 @@ private static ButtonOptions parseJson(JSONObject json, TypefaceLoader typefaceM
return button;
}

public static ArrayList<ButtonOptions> parse(JSONObject json, String buttonsType, TypefaceLoader typefaceLoader) {
public static ArrayList<ButtonOptions> parse(Context context, JSONObject json, String buttonsType, TypefaceLoader typefaceLoader) {
ArrayList<ButtonOptions> buttons = new ArrayList<>();
if (!json.has(buttonsType)) {
return null;
}

JSONArray jsonArray = json.optJSONArray(buttonsType);
if (jsonArray != null) {
buttons.addAll(parseJsonArray(jsonArray, typefaceLoader));
buttons.addAll(parseJsonArray(context, jsonArray, typefaceLoader));
} else {
buttons.add(parseJson(json.optJSONObject(buttonsType), typefaceLoader));
buttons.add(parseJson(context, json.optJSONObject(buttonsType), typefaceLoader));
}
return buttons;
}

private static ArrayList<ButtonOptions> parseJsonArray(JSONArray jsonArray, TypefaceLoader typefaceLoader) {
private static ArrayList<ButtonOptions> parseJsonArray(Context context, JSONArray jsonArray, TypefaceLoader typefaceLoader) {
ArrayList<ButtonOptions> buttons = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.optJSONObject(i);
ButtonOptions button = ButtonOptions.parseJson(json, typefaceLoader);
ButtonOptions button = ButtonOptions.parseJson(context, json, typefaceLoader);
buttons.add(button);
}
return buttons;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.reactnativenavigation.options;

import android.content.Context;

import com.reactnativenavigation.options.params.Bool;
import com.reactnativenavigation.options.params.Colour;
import com.reactnativenavigation.options.params.NullBool;
Expand All @@ -15,11 +17,11 @@
import androidx.annotation.Nullable;

public class DotIndicatorOptions {
public static DotIndicatorOptions parse(@Nullable JSONObject json) {
public static DotIndicatorOptions parse(Context context, @Nullable JSONObject json) {
DotIndicatorOptions options = new DotIndicatorOptions();
if (json == null) return options;

options.color = ColorParser.parse(json, "color");
options.color = ColorParser.parse(context, json, "color");
options.size = NumberParser.parse(json, "size");
options.visible = BoolParser.parse(json, "visible");
options.animate = BoolParser.parse(json, "animate");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.reactnativenavigation.options;


import android.content.Context;

import com.reactnativenavigation.options.params.Bool;
import com.reactnativenavigation.options.params.Colour;
import com.reactnativenavigation.options.params.NullBool;
Expand All @@ -18,23 +20,23 @@

public class FabOptions {

public static FabOptions parse(JSONObject json) {
public static FabOptions parse(Context context, JSONObject json) {
FabOptions options = new FabOptions();
if (json == null) return options;

options.id = TextParser.parse(json, "id");
options.backgroundColor = ColorParser.parse(json, "backgroundColor");
options.clickColor = ColorParser.parse(json, "clickColor");
options.rippleColor = ColorParser.parse(json, "rippleColor");
options.backgroundColor = ColorParser.parse(context, json, "backgroundColor");
options.clickColor = ColorParser.parse(context, json, "clickColor");
options.rippleColor = ColorParser.parse(context, json, "rippleColor");
options.visible = BoolParser.parse(json, "visible");
if (json.has("icon")) {
options.icon = TextParser.parse(json.optJSONObject("icon"), "uri");
}
options.iconColor = ColorParser.parse(json, "iconColor");
options.iconColor = ColorParser.parse(context, json, "iconColor");
if (json.has("actions")) {
JSONArray fabsArray = json.optJSONArray("actions");
for (int i = 0; i < fabsArray.length(); i++) {
options.actionsArray.add(FabOptions.parse(fabsArray.optJSONObject(i)));
options.actionsArray.add(FabOptions.parse(context, fabsArray.optJSONObject(i)));
}
}
options.alignHorizontally = TextParser.parse(json, "alignHorizontally");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.app.Activity;

import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabPresenter;
import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsPresenter;
import com.reactnativenavigation.viewcontrollers.component.ComponentPresenter;
Expand Down Expand Up @@ -69,35 +70,36 @@ public void init(Activity activity, EventEmitter eventEmitter, ChildControllersR
}

public ViewController create(final LayoutNode node) {
final ReactContext context = reactInstanceManager.getCurrentReactContext();
switch (node.type) {
case Component:
return createComponent(node);
return createComponent(context, node);
case ExternalComponent:
return createExternalComponent(node);
return createExternalComponent(context, node);
case Stack:
return createStack(node);
return createStack(context, node);
case BottomTabs:
return createBottomTabs(node);
return createBottomTabs(context, node);
case SideMenuRoot:
return createSideMenuRoot(node);
return createSideMenuRoot(context, node);
case SideMenuCenter:
return createSideMenuContent(node);
case SideMenuLeft:
return createSideMenuLeft(node);
case SideMenuRight:
return createSideMenuRight(node);
case TopTabs:
return createTopTabs(node);
return createTopTabs(context, node);
default:
throw new IllegalArgumentException("Invalid node type: " + node.type);
}
}

private ViewController createSideMenuRoot(LayoutNode node) {
private ViewController createSideMenuRoot(ReactContext context, LayoutNode node) {
SideMenuController sideMenuController = new SideMenuController(activity,
childRegistry,
node.id,
parse(typefaceManager, node.getOptions()),
parse(context, typefaceManager, node.getOptions()),
new SideMenuPresenter(),
new Presenter(activity, defaultOptions)
);
Expand Down Expand Up @@ -149,21 +151,21 @@ private ViewController createSideMenuRight(LayoutNode node) {
return create(node.children.get(0));
}

private ViewController createComponent(LayoutNode node) {
private ViewController createComponent(ReactContext context, LayoutNode node) {
String id = node.id;
String name = node.data.optString("name");
return new ComponentViewController(activity,
childRegistry,
id,
name,
new ComponentViewCreator(reactInstanceManager),
parse(typefaceManager, node.getOptions()),
parse(context, typefaceManager, node.getOptions()),
new Presenter(activity, defaultOptions),
new ComponentPresenter(defaultOptions)
);
}

private ViewController createExternalComponent(LayoutNode node) {
private ViewController createExternalComponent(ReactContext context, LayoutNode node) {
final ExternalComponent externalComponent = ExternalComponent.parse(node.data);
return new ExternalComponentViewController(activity,
childRegistry,
Expand All @@ -172,19 +174,19 @@ private ViewController createExternalComponent(LayoutNode node) {
externalComponent,
externalComponentCreators.get(externalComponent.name.get()),
reactInstanceManager,
new EventEmitter(reactInstanceManager.getCurrentReactContext()),
new EventEmitter(context),
new ExternalComponentPresenter(),
parse(typefaceManager, node.getOptions())
parse(context, typefaceManager, node.getOptions())
);
}

private ViewController createStack(LayoutNode node) {
private ViewController createStack(ReactContext context, LayoutNode node) {
return new StackControllerBuilder(activity, eventEmitter)
.setChildren(createChildren(node.children))
.setChildRegistry(childRegistry)
.setTopBarController(new TopBarController())
.setId(node.id)
.setInitialOptions(parse(typefaceManager, node.getOptions()))
.setInitialOptions(parse(context, typefaceManager, node.getOptions()))
.setStackPresenter(new StackPresenter(activity,
new TitleBarReactViewCreator(reactInstanceManager),
new TopBarBackgroundViewCreator(reactInstanceManager),
Expand All @@ -205,7 +207,7 @@ private List<ViewController> createChildren(List<LayoutNode> children) {
return result;
}

private ViewController createBottomTabs(LayoutNode node) {
private ViewController createBottomTabs(ReactContext context, LayoutNode node) {
List<ViewController> tabs = new ArrayList<>();
for (int i = 0; i < node.children.size(); i++) {
tabs.add(create(node.children.get(i)));
Expand All @@ -217,22 +219,22 @@ private ViewController createBottomTabs(LayoutNode node) {
eventEmitter,
new ImageLoader(),
node.id,
parse(typefaceManager, node.getOptions()),
parse(context, typefaceManager, node.getOptions()),
new Presenter(activity, defaultOptions),
new BottomTabsAttacher(tabs, bottomTabsPresenter, defaultOptions),
bottomTabsPresenter,
new BottomTabPresenter(activity, tabs, new ImageLoader(), defaultOptions));
}

private ViewController createTopTabs(LayoutNode node) {
private ViewController createTopTabs(ReactContext context, LayoutNode node) {
final List<ViewController> tabs = new ArrayList<>();
for (int i = 0; i < node.children.size(); i++) {
ViewController tabController = create(node.children.get(i));
Options options = parse(typefaceManager, node.children.get(i).getOptions());
Options options = parse(context, typefaceManager, node.children.get(i).getOptions());
options.setTopTabIndex(i);
tabs.add(tabController);
}
return new TopTabsController(activity, childRegistry, node.id, tabs, new TopTabsLayoutCreator(activity, tabs), parse(typefaceManager, node.getOptions()), new Presenter(activity, defaultOptions));
return new TopTabsController(activity, childRegistry, node.id, tabs, new TopTabsLayoutCreator(activity, tabs), parse(context, typefaceManager, node.getOptions()), new Presenter(activity, defaultOptions));
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.reactnativenavigation.options;

import android.content.Context;

import com.reactnativenavigation.options.params.Colour;
import com.reactnativenavigation.options.params.NullColor;
import com.reactnativenavigation.options.params.NullNumber;
Expand All @@ -10,12 +12,12 @@
import org.json.JSONObject;

public class LayoutOptions {
public static LayoutOptions parse(JSONObject json) {
public static LayoutOptions parse(Context context, JSONObject json) {
LayoutOptions result = new LayoutOptions();
if (json == null) return result;

result.backgroundColor = ColorParser.parse(json, "backgroundColor");
result.componentBackgroundColor = ColorParser.parse(json, "componentBackgroundColor");
result.backgroundColor = ColorParser.parse(context, json, "backgroundColor");
result.componentBackgroundColor = ColorParser.parse(context, json, "componentBackgroundColor");
result.topMargin = NumberParser.parse(json, "topMargin");
result.orientation = OrientationOptions.parse(json);
result.direction = LayoutDirection.fromString(json.optString("direction", ""));
Expand Down
Loading

0 comments on commit d7ba3ff

Please sign in to comment.