Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,6 @@ xcuserdata
# UNKNOWN: recommended by others, but I can't discover what these files are
#
# ...none. Everything is now explained.:
android/gradlew
android/gradlew.bat
android/local.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
Expand All @@ -35,6 +37,7 @@ public class Screen extends JsonObject implements Serializable {
private static final String KEY_TAB_NORMAL_TEXT_COLOR = "tabNormalTextColor";
private static final String KEY_TAB_SELECTED_TEXT_COLOR = "tabSelectedTextColor";
private static final String KEY_TAB_INDICATOR_COLOR = "tabIndicatorColor";
public static final String KEY_PROPS = "passProps";

public final String title;
public final String label;
Expand All @@ -44,6 +47,7 @@ public class Screen extends JsonObject implements Serializable {
public final String navigatorEventId;
public final int icon;
public final ArrayList<Button> buttons;
public HashMap<String, Object> passedProps = new HashMap<>();

// Navigation styling
@Nullable @ColorInt public Integer toolBarColor;
Expand All @@ -57,7 +61,7 @@ public class Screen extends JsonObject implements Serializable {

@NonNull
public List<Button> getButtons() {
return buttons == null ? Collections.EMPTY_LIST : buttons;
return buttons == null ? Collections.<Button>emptyList() : buttons;
}

public Screen(ReadableMap screen) {
Expand All @@ -68,15 +72,16 @@ public Screen(ReadableMap screen) {
navigatorId = getString(screen, KEY_NAVIGATOR_ID);
navigatorEventId = getString(screen, KEY_NAVIGATOR_EVENT_ID);
icon = getInt(screen, KEY_ICON);

if(screen.hasKey(KEY_PROPS)) {
passedProps = ((ReadableNativeMap) screen.getMap(KEY_PROPS)).toHashMap();
}
buttons = getButtons(screen);
setToolbarStyle(screen);
}

private ArrayList<Button> getButtons(ReadableMap screen) {
ArrayList<Button> ret = null;
ArrayList<Button> ret = new ArrayList<>();
if (screen.hasKey(KEY_RIGHT_BUTTONS)) {
ret = new ArrayList<>();
ReadableArray rightButtons = screen.getArray(KEY_RIGHT_BUTTONS);
for (int i = 0; i < rightButtons.size(); i++) {
ret.add(new Button(rightButtons.getMap(i)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.reactnativenavigation.utils;

import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;

/**
* Created by yedidyak on 26/05/2016.
*/
public class BridgeUtils {

@SuppressWarnings("unchecked")
public static Bundle addMapToBundle(HashMap<String, ?> map, Bundle bundle) {
for (String key : map.keySet()) {
Object value = map.get(key);
if (value instanceof String) {
bundle.putString(key, (String) value);
} else if (value instanceof Integer) {
bundle.putInt(key, (Integer) value);
} else if (value instanceof Double) {
bundle.putDouble(key, ((Double) value));
} else if (value instanceof Boolean) {
bundle.putBoolean(key, (Boolean) value);
} else if (value instanceof HashMap) {
bundle.putBundle(key, addMapToBundle((HashMap<String, Object>) value, new Bundle()));
} else if (value instanceof ArrayList) {
putArray(key, (ArrayList) value, bundle);
}
}
return bundle;
}

@SuppressWarnings("unchecked")
private static void putArray(String key, ArrayList arrayList, Bundle bundle) {
if (arrayList.size() == 0) {
bundle.putBooleanArray(key, new boolean[]{});
} else {
verifyArrayListIsSingleType(arrayList);
if (arrayList.get(0) instanceof String) {
bundle.putStringArray(key, toStringArray((ArrayList<String>) arrayList));
} else if (arrayList.get(0) instanceof Integer) {
bundle.putIntArray(key, toIntArray((ArrayList<Integer>) arrayList));
} else if (arrayList.get(0) instanceof Float) {
bundle.putFloatArray(key, toFloatArray((ArrayList<Float>) arrayList));
} else if (arrayList.get(0) instanceof Double) {
bundle.putDoubleArray(key, toDoubleArray((ArrayList<Double>) arrayList));
} else if (arrayList.get(0) instanceof Boolean) {
bundle.putBooleanArray(key, toBooleanArray((ArrayList<Boolean>) arrayList));
} else if (arrayList.get(0) instanceof HashMap) {
bundle.putParcelableArray(key, toBundleArray((ArrayList<HashMap>) arrayList));
} else if (arrayList.get(0) instanceof ArrayList) {
Log.w("RNNavigation", "Arrays of arrays passed in props are converted to dictionaries with indexes as keys");
Bundle innerArray = new Bundle();
for (int i = 0; i < arrayList.size(); i++) {
putArray(String.valueOf(i), (ArrayList) arrayList.get(i), innerArray);
}
bundle.putParcelable(key, innerArray);
}
}
}

private static void verifyArrayListIsSingleType(ArrayList arrayList) {
for (int i = 1; i < arrayList.size(); i++) {
if (!arrayList.get(i - 1).getClass().isInstance(arrayList.get(i))) {
throw new IllegalArgumentException("Cannot pass array of multiple types via props");
}
}
}

@SuppressWarnings("unchecked")
private static Bundle[] toBundleArray(ArrayList<HashMap> arrayList) {
Bundle[] ret = new Bundle[arrayList.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = addMapToBundle(arrayList.get(i), new Bundle());
}
return ret;
}

private static int[] toIntArray(ArrayList<Integer> arrayList) {
int[] ret = new int[arrayList.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = arrayList.get(i);
}
return ret;
}

private static float[] toFloatArray(ArrayList<Float> arrayList) {
float[] ret = new float[arrayList.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = arrayList.get(i);
}
return ret;
}

private static double[] toDoubleArray(ArrayList<Double> arrayList) {
double[] ret = new double[arrayList.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = arrayList.get(i);
}
return ret;
}

private static boolean[] toBooleanArray(ArrayList<Boolean> arrayList) {
boolean[] ret = new boolean[arrayList.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = arrayList.get(i);
}
return ret;
}

private static String[] toStringArray(ArrayList<String> arrayList) {
String[] ret = new String[arrayList.size()];
for (int i=0; i < ret.length; i++) {
ret[i] = arrayList.get(i);
}
return ret;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.facebook.react.ReactRootView;
import com.reactnativenavigation.activities.BaseReactActivity;
import com.reactnativenavigation.core.objects.Screen;
import com.reactnativenavigation.utils.BridgeUtils;

/**
* Created by guyc on 10/03/16.
Expand All @@ -34,6 +35,7 @@ public RctView(BaseReactActivity ctx, ReactInstanceManager rctInstanceManager, S
this(ctx, rctInstanceManager, screen, null);
}

@SuppressWarnings("unchecked")
public RctView(BaseReactActivity ctx, ReactInstanceManager rctInstanceManager, Screen screen,
final OnDisplayedListener onDisplayedListener) {
super(ctx);
Expand All @@ -47,6 +49,9 @@ public RctView(BaseReactActivity ctx, ReactInstanceManager rctInstanceManager, S
passProps.putString(Screen.KEY_SCREEN_INSTANCE_ID, screen.screenInstanceId);
passProps.putString(Screen.KEY_NAVIGATOR_ID, screen.navigatorId);
passProps.putString(Screen.KEY_NAVIGATOR_EVENT_ID, screen.navigatorEventId);
if (screen.passedProps != null) {
BridgeUtils.addMapToBundle(screen.passedProps, passProps);
}

mReactRootView.startReactApplication(rctInstanceManager, componentName, passProps);

Expand Down
51 changes: 48 additions & 3 deletions example-redux/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,28 @@ export default class App {
screen: {
screen: 'example.LoginScreen',
title: 'Login',
navigatorStyle: {}
navigatorStyle: {},
passProps: {
str: 'This is a prop passed in \'startSingleScreenApp()\'!',
obj: {
str: 'This is a prop passed in an object!',
arr: [
{
str: 'This is a prop in an object in an array in an object!'
}
],
arr2: [
[
'array of strings',
'with two strings'
],
[
1, 2, 3
]
]
},
num: 1234
}
}
});
return;
Expand All @@ -52,15 +73,39 @@ export default class App {
icon: require('../img/one.png'),
selectedIcon: require('../img/one_selected.png'),
title: 'Screen One',
navigatorStyle: {}
navigatorStyle: {},
passProps: {
str: 'This is a prop passed in \'startTabBasedApp\'!',
obj: {
str: 'This is a prop passed in an object!',
arr: [
{
str: 'This is a prop in an object in an array in an object!'
}
]
},
num: 1234
}
},
{
label: 'Two',
screen: 'example.SecondTabScreen',
icon: require('../img/two.png'),
selectedIcon: require('../img/two_selected.png'),
title: 'Screen Two',
navigatorStyle: {}
navigatorStyle: {},
passProps: {
str: 'This is a prop passed in \'startTabBasedApp\'!',
obj: {
str: 'This is a prop passed in an object!',
arr: [
{
str: 'This is a prop in an object in an array in an object!'
}
]
},
num: 1234
}
}
],
animationType: 'slide-down',
Expand Down
43 changes: 40 additions & 3 deletions example-redux/src/screens/FirstTabScreen.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, {Component, PropTypes} from 'react';
import {
Text,
View,
Expand Down Expand Up @@ -36,11 +36,19 @@ class FirstTabScreen extends Component {
}
]
};

static propTypes = {
str: PropTypes.string.isRequired,
obj: PropTypes.object.isRequired,
num: PropTypes.number.isRequired
};

constructor(props) {
super(props);
// if you want to listen on navigator events, set this up
this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
}

onNavigatorEvent(event) {
switch (event.id) {
case 'edit':
Expand Down Expand Up @@ -75,6 +83,11 @@ class FirstTabScreen extends Component {
<TouchableOpacity onPress={ this.onShowModalPress.bind(this) }>
<Text style={styles.button}>Modal Screen</Text>
</TouchableOpacity>

<Text style={{fontWeight: '500'}}>String prop: {this.props.str}</Text>
<Text style={{fontWeight: '500'}}>Number prop: {this.props.num}</Text>
<Text style={{fontWeight: '500'}}>Object prop: {this.props.obj.str}</Text>
<Text style={{fontWeight: '500'}}>Array prop: {this.props.obj.arr[0].str}</Text>
</View>
);
}
Expand All @@ -86,14 +99,38 @@ class FirstTabScreen extends Component {
onPushPress() {
this.props.navigator.push({
title: "More",
screen: "example.PushedScreen"
screen: "example.PushedScreen",
passProps: {
passed: 'This is a prop passed in \'navigator.push()\'!',
obj: {
str: 'This is a prop passed in an object!',
arr: [
{
str: 'This is a prop in an object in an array in an object!'
}
]
},
num: 1234
}
});
}

onShowModalPress() {
this.props.navigator.showModal({
title: "Modal Screen",
screen: "example.PushedScreen"
screen: "example.PushedScreen",
passProps: {
passed: 'This is a prop passed in \'navigator.showModal()\'!',
obj: {
str: 'This is a prop passed in an object!',
arr: [
{
str: 'This is a prop in an object in an array in an object!'
}
]
},
num: 1234
}
});
}
}
Expand Down
Loading