Skip to content

Commit

Permalink
fix(router): route information is stateless
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed May 8, 2018
1 parent ba551fd commit 0f8477d
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 37 deletions.
44 changes: 18 additions & 26 deletions core/src/components/router/router.tsx
Expand Up @@ -3,9 +3,9 @@ import { Config, QueueController } from '../../interface';
import { debounce } from '../../utils/helpers';
import { printRedirects, printRoutes } from './utils/debug';
import { readNavState, waitUntilNavNode, writeNavState } from './utils/dom';
import { RouteChain, RouteRedirect, RouterDirection, RouterEventDetail } from './utils/interface';
import { RouteChain, RouterDirection, RouterEventDetail } from './utils/interface';
import { routeRedirect, routerIDsToChain, routerPathToChain } from './utils/matching';
import { flattenRouterTree, readRedirects, readRoutes } from './utils/parser';
import { readRedirects, readRoutes } from './utils/parser';
import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path';


Expand All @@ -14,9 +14,7 @@ import { chainToPath, generatePath, parsePath, readPath, writePath } from './uti
})
export class Router {

private routes: RouteChain[] = [];
private previousPath: string|null = null;
private redirects: RouteRedirect[] = [];
private busy = false;
private state = 0;
private lastState = 0;
Expand Down Expand Up @@ -59,17 +57,11 @@ export class Router {
await waitUntilNavNode(this.win);
console.debug('[ion-router] found nav');

const tree = readRoutes(this.el);
this.routes = flattenRouterTree(tree);
this.redirects = readRedirects(this.el);
await this.onRoutesChanged();

this.win.addEventListener('ionRouteRedirectChanged', debounce(this.onRedirectChanged.bind(this), 10));
this.win.addEventListener('ionRouteDataChanged', debounce(this.onRoutesChanged.bind(this), 100));

const changed = await this.writeNavStateRoot(this.getPath(), RouterDirection.None);
if (!changed) {
console.error('[ion-router] did not change on will load');
}
this.onRedirectChanged();
}

@Listen('window:popstate')
Expand All @@ -81,17 +73,14 @@ export class Router {
}

private onRedirectChanged() {
this.redirects = readRedirects(this.el);
const path = this.getPath();
if (path && routeRedirect(path, this.redirects)) {
if (path && routeRedirect(path, readRedirects(this.el))) {
this.writeNavStateRoot(path, RouterDirection.None);
}
}

private onRoutesChanged() {
const tree = readRoutes(this.el);
this.routes = flattenRouterTree(tree);
this.writeNavStateRoot(this.getPath(), RouterDirection.None);
return this.writeNavStateRoot(this.getPath(), RouterDirection.None);
}

private historyDirection() {
Expand All @@ -117,8 +106,8 @@ export class Router {
printDebug() {
console.debug('CURRENT PATH', this.getPath());
console.debug('PREVIOUS PATH', this.previousPath);
printRoutes(this.routes);
printRedirects(this.redirects);
printRoutes(readRoutes(this.el));
printRedirects(readRedirects(this.el));
}

@Method()
Expand All @@ -127,7 +116,8 @@ export class Router {
return false;
}
const { ids, outlet } = readNavState(this.win.document.body);
const chain = routerIDsToChain(ids, this.routes);
const routes = readRoutes(this.el);
const chain = routerIDsToChain(ids, routes);
if (!chain) {
console.warn('[ion-router] no matching URL for ', ids.map(i => i.id));
return false;
Expand All @@ -149,9 +139,9 @@ export class Router {
@Method()
push(url: string, direction = RouterDirection.Forward) {
const path = parsePath(url);
this.setPath(path, direction);

console.debug('[ion-router] URL pushed -> updating nav', url, direction);

this.setPath(path, direction);
return this.writeNavStateRoot(path, direction);
}

Expand All @@ -165,16 +155,18 @@ export class Router {
}

// lookup redirect rule
const redirect = routeRedirect(path, this.redirects);
const redirects = readRedirects(this.el);
const redirect = routeRedirect(path, redirects);
let redirectFrom: string[]|null = null;
if (redirect) {
this.setPath(redirect.to!, direction);
this.setPath(redirect.to, direction);
redirectFrom = redirect.from;
path = redirect.to!;
path = redirect.to;
}

// lookup route chain
const chain = routerPathToChain(path, this.routes);
const routes = readRoutes(this.el);
const chain = routerPathToChain(path, routes);
if (!chain) {
console.error('[ion-router] the path does not match any route');
return false;
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/router/utils/interface.ts
Expand Up @@ -19,7 +19,7 @@ export const enum RouterDirection {

export interface RouteRedirect {
from: string[];
to: string[]|undefined;
to?: string[];
}

export interface RouteWrite {
Expand Down
11 changes: 3 additions & 8 deletions core/src/components/router/utils/matching.ts
@@ -1,7 +1,7 @@
import { RouteChain, RouteID, RouteRedirect } from './interface';


export function matchesRedirect(input: string[], route: RouteRedirect): boolean {
export function matchesRedirect(input: string[], route: RouteRedirect): route is Required<RouteRedirect> {
const {from, to} = route;
if (to === undefined) {
return false;
Expand All @@ -23,13 +23,8 @@ export function matchesRedirect(input: string[], route: RouteRedirect): boolean
return from.length === input.length;
}

export function routeRedirect(path: string[], routes: RouteRedirect[]): RouteRedirect|null {
for (const route of routes) {
if (matchesRedirect(path, route)) {
return route;
}
}
return null;
export function routeRedirect(path: string[], routes: RouteRedirect[]) {
return routes.find(route => matchesRedirect(path, route)) as Required<RouteRedirect> | undefined;
}


Expand Down
8 changes: 6 additions & 2 deletions core/src/components/router/utils/parser.ts
Expand Up @@ -14,7 +14,11 @@ export function readRedirects(root: Element): RouteRedirect[] {
});
}

export function readRoutes(root: Element, node = root): RouteTree {
export function readRoutes(root: Element): RouteChain[] {
return flattenRouterTree(readRouteNodes(root));
}

export function readRouteNodes(root: Element, node = root): RouteTree {
return (Array.from(node.children) as HTMLIonRouteElement[])
.filter(el => el.tagName === 'ION-ROUTE' && el.component)
.map(el => {
Expand All @@ -26,7 +30,7 @@ export function readRoutes(root: Element, node = root): RouteTree {
path: parsePath(readProp(el, 'url')),
id: component.toLowerCase(),
params: el.componentProps,
children: readRoutes(root, el)
children: readRouteNodes(root, el)
};
});
}
Expand Down

0 comments on commit 0f8477d

Please sign in to comment.