Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0 #102

Merged
merged 4 commits into from
Jan 4, 2016
Merged

2.0 #102

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
90 changes: 90 additions & 0 deletions Actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Route from './Route';
import Router from './Router';

function isNumeric(n){
return !isNaN(parseFloat(n)) && isFinite(n);
}

function filterParam(data){
if (data.toString()!='[object Object]')
return data;
if (!data){
return;
}
var proto = (data||{}).constructor.name;
// avoid passing React Native parameters
if (proto != 'Object'){
data = {};
}
if (data.data){
data.data = filterParam(data.data);
}
return data;
}

class Actions {
currentRouter: ?Router;

constructor(){
this.pop = this.pop.bind(this);
this.route = this.route.bind(this);
}

route(name: string, props: { [key: string]: any} = {}){
if (!this.currentRouter){
throw new Error("No current router is set");
}
if (props.toString()!='[object Object]')
props = {data : props};

props = filterParam(props);
// check if route is in children, current or parent routers
let router: Router = this.currentRouter;
// deep into child router
while (router.currentRoute.childRouter){
router = router.currentRoute.childRouter;
}
while (!router.routes[name]){
const route = router.parentRoute;
if (!route || !route.parent){
throw new Error("Cannot find router for route="+name);
}
router = route.parent;
}
if (router.route(name, props)){
this.currentRouter = router;
return true;
}
return false;
}
pop(num: number = 1){
if (!isNumeric(num)){
num = 1;
}
if (!this.currentRouter){
throw new Error("No current router is set");
}
if (num > 1){
for (let i=0;i<num;i++){
if (!Actions.pop()){
return false;
}
}
return true;
} else {
let router: Router = this.currentRouter;
while (router.stack.length <= 1 || router.currentRoute.type === 'switch'){
router = router.parentRoute.parent;
}
if (router.pop()){
this.currentRouter = router;
return true;
} else {
return false;
}

}
}
}

export default new Actions();
23 changes: 23 additions & 0 deletions Common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react-native';

// schema class represents schema for routes and it is processed inside Router component
export class Schema extends React.Component {
className(){
return "Schema";
}
render(){
return null;
}
}

// route class processed inside Router component
export class Route extends React.Component {
className(){
return "Route";
}
render(){
return null;
}

}

195 changes: 195 additions & 0 deletions ExRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import React from 'react-native';
import Router from './Router';
import Route from './Route';
import * as Components from './Common';
import ExNavigator from '@exponent/react-native-navigator';
import Animations from './Animations';
const {TouchableOpacity, StyleSheet, View, Text} = React;
import ReactRouter from './ReactRouter';

export class ExRoute {
name: string;
navigator: ExNavigator;
route: Route;
props: { [key: string]: any};

constructor(route: Route, props:{ [key: string]: any} = {}){
if (!route){
throw new Error("route is not defined ");
}
this.route = route;
this.name = route.name;
if (!this.name){
throw new Error("name is not defined for route");
}
this.props = props;
this.renderScene = this.renderScene.bind(this);
}

configureScene() {
return this.route.type === 'switch' ? Animations.None : this.route.props.sceneConfig || Animations.None;
}

renderScene(navigator) {
const Component = this.route.component;
const child = Component ?
!this.route.wrapRouter ? <Component key={this.route.name} name={this.route.name} {...this.route.props} {...this.props} route={this.route}/>:
<ReactRouter name={this.route.name+"Router"} {...this.route.props} {...this.props} route={this.route} router={ExRouter} >
<Components.Route {...this.route.props} {...this.props} component={Component} name={"_"+this.route.name} type="push" wrapRouter={false}/>
</ReactRouter>
:
React.cloneElement(React.Children.only(this.route.children), {...this.route.props, data:this.props, route:this.route});
return child;
}

getName(){
return this.route.name;
}

getTitle() {
return this.route.title || "";
}

getBackButtonTitle(navigator, index, state){
let previousIndex = index - 1;
let previousRoute = state.routeStack[previousIndex];
let title = previousRoute.getTitle(navigator, previousIndex, state);
return title.length>10 ? null : title;
}

renderRightButton() {
if (this.route.onRight && this.route.rightTitle){
return (<TouchableOpacity
touchRetentionOffset={ExNavigator.Styles.barButtonTouchRetentionOffset}
onPress={() => this.route.onRight({...this.route.props, ...this.props})}
style={[ExNavigator.Styles.barRightButton, this.route.rightButtonStyle]}>
<Text style={[ExNavigator.Styles.barRightButtonText, this.route.rightButtonTextStyle]}>{this.route.rightTitle}</Text>
</TouchableOpacity>);
} else {
return null;
}
}
}

const defaultCreateRoute = function(route, data){
return new ExRoute(route, data);
};

export default class ExRouter extends React.Component {
router: Router;

constructor(props){
super(props);
this.onPop = this.onPop.bind(this);
this.onPush = this.onPush.bind(this);
this.onPop = this.onPop.bind(this);
this.onPush = this.onPush.bind(this);
this.onReplace = this.onReplace.bind(this);
this.onJump = this.onJump.bind(this);
}

onPush(route: Route, props:{ [key: string]: any}):boolean {
if (this.props.onPush){
const res = this.props.onPush(route, props);
if (!res){
return false;
}
}
this.refs.nav.push(new ExRoute(route, props));
return true;
}

onReplace(route: Route, props:{ [key: string]: any}):boolean {
if (this.props.onReplace){
const res = this.props.onReplace(route, props);
if (!res){
return false;
}
}
this.refs.nav.replace(new ExRoute(route, props));
return true;
}

onJump(route: Route, props:{ [key: string]: any}):boolean {
if (this.props.onJump){
const res = this.props.onJump(route, props);
if (!res){
return false;
}
}
const navigator = this.refs.nav;
const routes = navigator.getCurrentRoutes();
const exist = routes.filter(el=>el.getName()==route.name);
if (exist.length){
navigator.jumpTo(exist[0]);
} else {
navigator.push(new ExRoute(route, props));

}
this.setState({selected: route.name});
return true;
}

onPop(num: number){
if (this.props.onPop){
const res = this.props.onPop(num);
if (!res){
return false;
}
}
this.refs.nav.pop();
return true;
}

render() {
const router = this.props.router;
if (!router){
throw new Error("No router is defined");
}
const Header = this.props.header;
const header = Header ? <Header {...this.props} {...this.state}/> : null;

const Footer = this.props.footer;
const footer = Footer ? <Footer {...this.props} {...this.state}/> : null;

return (
<View style={styles.transparent}>
{header}
<ExNavigator ref="nav" initialRouteStack={router.stack.map(route => new ExRoute(router.routes[route]))}
style={styles.transparent}
sceneStyle={{ paddingTop: 0 }}
showNavigationBar={!this.props.hideNavBar}
{...this.props}
/>
{footer}
</View>
);
}


}


var styles = StyleSheet.create({
container: {
position: 'absolute',
top:0,
bottom:0,
left:0,
right:0,
backgroundColor:'transparent',
justifyContent: 'center',
alignItems: 'center',
},
transparent: {
flex:1,
backgroundColor: "transparent"
},
barTitleText: {
fontFamily: '.HelveticaNeueInterface-MediumP4',
fontSize: 17,
marginTop: 11,
},

});

37 changes: 37 additions & 0 deletions ReactRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2015-present, Pavel Aksonov
* 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.
*
*/

import React from 'react-native'
import Router from './Router';
import ExRouter from './ExRouter';
const {StyleSheet, View} = React;
import Actions from './Actions';
export default class extends React.Component {

constructor(props){
super(props);
const createRouter = props.createRouter || this.createRouter;
this.router = createRouter(props);
}

createRouter(props){
const schemas = React.Children.map(props.children, child=>child).filter(child=>child.type.prototype.className() === "Schema").map(child=>child.props);
const routes = React.Children.map(props.children, child=>child).filter(child=>child.type.prototype.className() === "Route").map(child=>child.props);
return new Router(routes, schemas, props.initialRoutes || (props.initial && [props.initial]), props);
}

componentDidMount(){
this.router.delegate = this.refs.router;
}

render(){
const Component = this.props.router || ExRouter;
return (<Component ref="router" {...this.props} router={this.router} />);
}
}
Loading