Skip to content

Commit 4d5c4e7

Browse files
author
Pavlo Aksonov
committed
Merge pull request #196 from danielweinmann/router_rename_done_right
Renames Router to BaseRouter and ReactRouter to Router and router prop on Router to plugin
2 parents 033c274 + 58baab6 commit 4d5c4e7

8 files changed

+262
-262
lines changed

Actions.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Route from './Route';
2-
import Router from './Router';
2+
import BaseRouter from './BaseRouter';
33
import debug from './debug';
44

55
const BEFORE_ROUTE = 'BEFORE_ROUTER_ROUTE';
@@ -31,7 +31,7 @@ function filterParam(data){
3131
}
3232

3333
class Actions {
34-
currentRouter: ?Router;
34+
currentRouter: ?BaseRouter;
3535

3636
constructor(){
3737
this.pop = this.pop.bind(this);
@@ -48,7 +48,7 @@ class Actions {
4848

4949
props = filterParam(props);
5050
// check if route is in children, current or parent routers
51-
let router: Router = this.currentRouter;
51+
let router: BaseRouter = this.currentRouter;
5252

5353
// deep into child router
5454
while (router.currentRoute.childRouter){
@@ -87,7 +87,7 @@ class Actions {
8787
}
8888
dismiss(props: { [key: string]: any} = {}){
8989
props = filterParam(props);
90-
let router: Router = this.currentRouter;
90+
let router: BaseRouter = this.currentRouter;
9191
// go to root router
9292
while (router.parentRoute){
9393
router = router.parentRoute.parent;
@@ -118,7 +118,7 @@ class Actions {
118118
}
119119
return true;
120120
} else {
121-
let router: Router = this.currentRouter;
121+
let router: BaseRouter = this.currentRouter;
122122
debug("Pop, router="+router.name+" stack length:"+router.stack.length);
123123
debug("Current route="+router.currentRoute.name+" type="+router.currentRoute.type);
124124
while (router.stack.length <= 1 || router.currentRoute.type === 'switch'){

BaseRouter.js

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/**
2+
* Copyright (c) 2015-present, Pavel Aksonov
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*
8+
*/
9+
10+
import Route from './Route';
11+
import Actions from './Actions';
12+
import debug from './debug';
13+
14+
export class RouterDelegate {
15+
onPush(route:Route, props:{ [key: string]: any}):boolean {
16+
return true;
17+
}
18+
onPop(num: number = 1, route:Route, props:{ [key: string]: any}): boolean {
19+
return true;
20+
}
21+
onReplace(route:Route, props:{ [key: string]: any}):boolean {
22+
return true;
23+
}
24+
onReset(route:Route, props:{ [key: string]: any}):boolean {
25+
return true;
26+
}
27+
onSwitch(route:Route, props:{ [key: string]: any}):boolean {
28+
return true;
29+
}
30+
}
31+
32+
export default class BaseRouter {
33+
name:string;
34+
routes: {[key: string]: Route };
35+
schemas: {[key: string]: {[key:string]:any } };
36+
props: { [key: string]: any};
37+
parentRoute: ?Route;
38+
nextRoute: ?Route;
39+
_stack: Array<string>;
40+
delegate:RouterDelegate;
41+
42+
set stack(stack:Array<string>) {
43+
if (!stack || !stack.length) {
44+
throw new Error("Cannot be set to empty stack");
45+
}
46+
this._stack = stack;
47+
}
48+
49+
get stack():Array<string> {
50+
return this._stack;
51+
}
52+
53+
get currentRoute():Route {
54+
return this.routes[this._stack[this._stack.length-1]];
55+
}
56+
57+
get previousRoute():Route {
58+
if (this._stack.length > 1){
59+
return this.routes[this._stack[this._stack.length-2]];
60+
} else {
61+
return null;
62+
}
63+
}
64+
65+
constructor(routes: Array<{ [key: string]: any}>,
66+
schemas:Array<{ [key: string]: any}> = [],
67+
stack:Array<string> = null, props:{ [key: string]: any} = {}){
68+
this.schemas = {};
69+
this.routes = {};
70+
this.pop = this.pop.bind(this);
71+
this.route = this.route.bind(this);
72+
this.delegate = new RouterDelegate();
73+
if (!routes || !routes.length){
74+
throw new Error("routes is not defined");
75+
}
76+
this.props = props;
77+
this.name = props && props.name;
78+
this.parentRoute = props && props.route;
79+
if (this.parentRoute){
80+
if (this.parentRoute.parent){
81+
// copy parent schemas
82+
Object.keys(this.parentRoute.parent.schemas).forEach(el=>
83+
this._addSchema(this.parentRoute.parent.schemas[el].name, this.parentRoute.parent.schemas[el]));
84+
}
85+
this.parentRoute.childRouter = this;
86+
}
87+
88+
89+
schemas.forEach(el=>this._addSchema(el.name, el));
90+
let selected = null;
91+
routes.forEach(el=>{if (el.initial) selected = el.name;this._addRoute(el.name, el)});
92+
93+
// select first one as initial
94+
if (!stack || !stack.length){
95+
stack = [selected || routes[0].name];
96+
}
97+
this.stack = stack;
98+
// add actions
99+
this._addActions();
100+
}
101+
102+
_addSchema(name: string, props:{ [key: string]: any}){
103+
if (!name){
104+
throw new Error("Schema name is not defined");
105+
}
106+
if (this.schemas[name]){
107+
throw new Error("Schema="+name+" is not unique!");
108+
}
109+
this.schemas[name] = props;
110+
}
111+
112+
_addRoute(routeName: string, props:{ [key: string]: any}){
113+
if (!routeName){
114+
throw new Error("Route name is not defined");
115+
}
116+
const schemaName: string = props.schema || 'default';
117+
const schema = this.schemas[schemaName] || {};
118+
// pass router data to inner routes
119+
const {children, name, header, footer, showNavigationBar, route, component, hideNavBar, sceneConfig, type, ...routerProps} = this.props;
120+
const routeProps = Object.assign({}, schema, routerProps, props);
121+
122+
if (this.routes[routeName]){
123+
throw new Error("Route="+routeName+" is not unique!");
124+
}
125+
126+
this.routes[routeName] = new Route(routeProps, this);
127+
128+
}
129+
130+
_addActions(){
131+
if (!Actions.currentRouter){
132+
Actions.currentRouter = this;
133+
debug("Set current router:"+this.name);
134+
}
135+
Object.keys(this.routes).forEach(name=>{
136+
if (!Actions[name]){
137+
Actions[name] = function(data){
138+
return Actions.route(name, data);
139+
}
140+
}
141+
});
142+
}
143+
144+
route(name: string, props:{ [key: string]: any} = {}){
145+
if (!this.routes[name]){
146+
throw new Error("No route is defined for name="+name);
147+
}
148+
const type = props.type ? props.type : this.routes[name].type;
149+
const action = type === "switch" ? "jump": type;
150+
if (!action){
151+
throw new Error("No type is defined for name="+name);
152+
}
153+
if (!this["_"+action]){
154+
throw new Error("No type="+action+" is supported");
155+
}
156+
this.nextRoute = this.routes[name];
157+
158+
const handler = "on"+capitalizeFirstLetter(action);
159+
if (this.delegate[handler]) {
160+
debug("Run handler "+handler);
161+
const res:boolean = this.delegate[handler](this.routes[name], props);
162+
if (!res) {
163+
console.log("Ignore "+action+", handler returns false");
164+
return false;
165+
}
166+
} else {
167+
throw new Error("No handler "+handler+" for route="+name);
168+
}
169+
this["_"+action](name, props);
170+
return true;
171+
}
172+
173+
_modal(name:string, props:{ [key: string]: any} ) {
174+
}
175+
176+
_push(name:string, props:{ [key: string]: any} ){
177+
this._stack.push(name);
178+
}
179+
180+
_replace(name:string, props:{ [key: string]: any} ) {
181+
this._stack[this._stack.length - 1] = name;
182+
}
183+
/***
184+
* Reset every scene with an array of routes
185+
* @param route defined route
186+
*/
187+
_reset(name:string, props:{ [key: string]: any} ) {
188+
this._stack = [name];
189+
}
190+
191+
_jump(name:string, props:{ [key: string]: any} ) {
192+
if (this._stack.indexOf(name) != -1){
193+
const pos = this._stack.indexOf(name);
194+
// swap latest with found element (because currentRoute always points to latest)
195+
this._stack[pos] = this._stack[this._stack.length - 1];
196+
this._stack[this._stack.length - 1] = name;
197+
} else {
198+
this._stack.push(name);
199+
}
200+
}
201+
202+
pop(num: number = 1, props:{ [key: string]: any} = {}){
203+
if (this._stack.length <= num){
204+
return false;
205+
}
206+
this.nextRoute = null;
207+
if (this.delegate.onPop && this.delegate.onPop(num, this.currentRoute, props)){
208+
const routes = this._stack.splice(-num, num);
209+
return true;
210+
}
211+
return false;
212+
}
213+
214+
dismiss() {
215+
return this.delegate.onDismiss && this.delegate.onDismiss();
216+
}
217+
218+
219+
}
220+
221+
function capitalizeFirstLetter(string) {
222+
return string.charAt(0).toUpperCase() + string.slice(1);
223+
}

ExRouter.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import React from 'react-native';
2-
import Router from './Router';
2+
import BaseRouter from './BaseRouter';
33
import Route from './Route';
44
import * as Components from './Common';
55
import ExNavigator from '@exponent/react-native-navigator';
66
import ExNavigatorStyles from '@exponent/react-native-navigator/ExNavigatorStyles';
77
import { BackIcon } from '@exponent/react-native-navigator/ExNavigatorIcons';
88
import Animations from './Animations';
99
const {TouchableOpacity, Navigator, StyleSheet, View, Text} = React;
10-
import ReactRouter from './ReactRouter';
10+
import Router from './Router';
1111
import Actions from './Actions';
1212
import debug from './debug';
1313

@@ -55,9 +55,9 @@ export class ExRouteAdapter {
5555
const {initial, ...routeProps} = this.route.props;
5656
const child = Component ?
5757
!this.route.wrapRouter ? <Component key={this.route.name} name={this.route.name} {...routeProps} {...this.props} route={this.route}/>:
58-
<ReactRouter name={this.route.name+"Router"} {...routeProps} {...this.props} route={this.route} router={ExRouter} initial={"_"+this.route.name} footer={null} header={null}>
58+
<Router name={this.route.name+"Router"} {...routeProps} {...this.props} route={this.route} router={ExRouter} initial={"_"+this.route.name} footer={null} header={null}>
5959
<Components.Route {...routeProps} {...this.props} component={Component} name={"_"+this.route.name} type="push" wrapRouter={false} initial={true}/>
60-
</ReactRouter>
60+
</Router>
6161
:
6262
React.cloneElement(React.Children.only(this.route.children), {...routeProps, ...this.props, route:this.route});
6363

@@ -178,7 +178,7 @@ class ExNavigationBar extends Navigator.NavigationBar {
178178
}
179179

180180
export default class ExRouter extends React.Component {
181-
router: Router;
181+
router: BaseRouter;
182182

183183
constructor(props){
184184
super(props);

ReactRouter.js

-38
This file was deleted.

Route.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*/
99

10-
import type Router from './Router';
10+
import type BaseRouter from './BaseRouter';
1111
export default class Route {
1212
name: string;
1313
type: string;
@@ -17,11 +17,11 @@ export default class Route {
1717
component: any;
1818
children: any;
1919
props: { [key: string]: any};
20-
parent: Router;
20+
parent: BaseRouter;
2121
navigator: any;
22-
childRouter: ?Router;
22+
childRouter: ?BaseRouter;
2323

24-
constructor({name, type, component, schema, children, header, footer, wrapRouter, ...props}: { [key: string]: any} = {}, parent: Router = null) {
24+
constructor({name, type, component, schema, children, header, footer, wrapRouter, ...props}: { [key: string]: any} = {}, parent: BaseRouter = null) {
2525
if (!name) {
2626
throw new Error("no name is defined for Route=" + name);
2727
}

0 commit comments

Comments
 (0)