fix(router): fix push() public interface

This commit is contained in:
Manu Mtz.-Almeida
2018-05-11 19:15:26 +02:00
parent 93526617e0
commit 875b9d0950
11 changed files with 64 additions and 64 deletions

View File

@ -56,6 +56,9 @@ import {
PopoverOptions, PopoverOptions,
RangeInputChangeEvent, RangeInputChangeEvent,
RouteID, RouteID,
RouterDirection,
RouterEventDetail,
RouterIntent,
RouterOutletOptions, RouterOutletOptions,
RouteWrite, RouteWrite,
SelectInputChangeEvent, SelectInputChangeEvent,
@ -82,10 +85,6 @@ import {
import { import {
ViewController, ViewController,
} from './components/nav/view-controller'; } from './components/nav/view-controller';
import {
RouterDirection,
RouterEventDetail,
} from './components/router/utils/interface';
import { import {
ScrollBaseDetail, ScrollBaseDetail,
ScrollDetail, ScrollDetail,
@ -492,7 +491,7 @@ declare global {
/** /**
* When using a router, it specifies the transition direction when navigating to another page using `href`. * When using a router, it specifies the transition direction when navigating to another page using `href`.
*/ */
'routerDirection': 'forward' | 'back'; 'routerDirection': RouterDirection;
} }
} }
@ -522,7 +521,7 @@ declare global {
/** /**
* When using a router, it specifies the transition direction when navigating to another page using `href`. * When using a router, it specifies the transition direction when navigating to another page using `href`.
*/ */
'routerDirection'?: 'forward' | 'back'; 'routerDirection'?: RouterDirection;
} }
} }
} }
@ -839,7 +838,7 @@ declare global {
/** /**
* When using a router, it specifies the transition direction when navigating to another page using `href`. * When using a router, it specifies the transition direction when navigating to another page using `href`.
*/ */
'routerDirection': 'forward' | 'back'; 'routerDirection': RouterDirection;
/** /**
* The button shape. Possible values are: `"round"`. * The button shape. Possible values are: `"round"`.
*/ */
@ -917,7 +916,7 @@ declare global {
/** /**
* When using a router, it specifies the transition direction when navigating to another page using `href`. * When using a router, it specifies the transition direction when navigating to another page using `href`.
*/ */
'routerDirection'?: 'forward' | 'back'; 'routerDirection'?: RouterDirection;
/** /**
* The button shape. Possible values are: `"round"`. * The button shape. Possible values are: `"round"`.
*/ */
@ -2863,7 +2862,7 @@ declare global {
/** /**
* When using a router, it specifies the transition direction when navigating to another page using `href`. * When using a router, it specifies the transition direction when navigating to another page using `href`.
*/ */
'routerDirection': 'forward' | 'back'; 'routerDirection': RouterDirection;
} }
} }
@ -2917,7 +2916,7 @@ declare global {
/** /**
* When using a router, it specifies the transition direction when navigating to another page using `href`. * When using a router, it specifies the transition direction when navigating to another page using `href`.
*/ */
'routerDirection'?: 'forward' | 'back'; 'routerDirection'?: RouterDirection;
} }
} }
} }
@ -3862,7 +3861,7 @@ declare global {
'rootParams': ComponentProps; 'rootParams': ComponentProps;
'setPages': (views: any[], opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>; 'setPages': (views: any[], opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
'setRoot': (component: NavComponent, componentProps?: ComponentProps | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>; 'setRoot': (component: NavComponent, componentProps?: ComponentProps | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
'setRouteId': (id: string, params: any, direction: number) => Promise<RouteWrite>; 'setRouteId': (id: string, params: any, direction: RouterIntent) => Promise<RouteWrite>;
'swipeBackEnabled': boolean; 'swipeBackEnabled': boolean;
} }
} }
@ -5153,7 +5152,7 @@ declare global {
namespace StencilComponents { namespace StencilComponents {
interface IonRouter { interface IonRouter {
'navChanged': (direction: RouterDirection) => Promise<boolean>; 'navChanged': (intent: RouterIntent) => Promise<boolean>;
'printDebug': () => void; 'printDebug': () => void;
'push': (url: string, direction?: RouterDirection) => Promise<boolean>; 'push': (url: string, direction?: RouterDirection) => Promise<boolean>;
/** /**

View File

@ -1,5 +1,6 @@
import { Component, Prop } from '@stencil/core'; import { Component, Prop } from '@stencil/core';
import { RouterDirection, openURL } from '../../utils/theme'; import { RouterDirection } from '../../interface';
import { openURL } from '../../utils/theme';
@Component({ @Component({

View File

@ -1,6 +1,6 @@
import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
import { CssClassMap, Mode } from '../../interface'; import { CssClassMap, Mode, RouterDirection } from '../../interface';
import { RouterDirection, getButtonClassMap, getElementClassMap, openURL } from '../../utils/theme'; import { getButtonClassMap, getElementClassMap, openURL } from '../../utils/theme';
@Component({ @Component({

View File

@ -1,6 +1,6 @@
import { Component, Element, Listen, Prop } from '@stencil/core'; import { Component, Element, Listen, Prop } from '@stencil/core';
import { CssClassMap, Mode } from '../../interface'; import { CssClassMap, Mode, RouterDirection } from '../../interface';
import { RouterDirection, createThemedClasses, getElementClassMap, openURL } from '../../utils/theme'; import { createThemedClasses, getElementClassMap, openURL } from '../../utils/theme';
@Component({ @Component({

View File

@ -3,7 +3,7 @@ import { ViewLifecycle } from '../..';
import { import {
Animation, ComponentProps, Config, FrameworkDelegate, GestureDetail, Mode, Animation, ComponentProps, Config, FrameworkDelegate, GestureDetail, Mode,
NavComponent, NavOptions, NavOutlet, NavResult, QueueController, RouteID, NavComponent, NavOptions, NavOutlet, NavResult, QueueController, RouteID,
RouteWrite, RouterDirection, TransitionDoneFn, TransitionInstruction } from '../../interface'; RouteWrite, RouterIntent, TransitionDoneFn, TransitionInstruction } from '../../interface';
import { assert } from '../../utils/helpers'; import { assert } from '../../utils/helpers';
import { TransitionOptions, lifecycle, transition } from '../../utils/transition'; import { TransitionOptions, lifecycle, transition } from '../../utils/transition';
import { ViewController, ViewState, convertToViews, matches } from './view-controller'; import { ViewController, ViewState, convertToViews, matches } from './view-controller';
@ -172,7 +172,7 @@ export class Nav implements NavOutlet {
} }
@Method() @Method()
setRouteId(id: string, params: any, direction: number): Promise<RouteWrite> { setRouteId(id: string, params: any, direction: RouterIntent): Promise<RouteWrite> {
const active = this.getActive(); const active = this.getActive();
if (matches(active, id, params)) { if (matches(active, id, params)) {
return Promise.resolve({ return Promise.resolve({
@ -310,8 +310,8 @@ export class Nav implements NavOutlet {
const router = this.win.document.querySelector('ion-router'); const router = this.win.document.querySelector('ion-router');
if (router) { if (router) {
const direction = (result.direction === 'back') const direction = (result.direction === 'back')
? RouterDirection.Back ? RouterIntent.Back
: RouterDirection.Forward; : RouterIntent.Forward;
router.navChanged(direction); router.navChanged(direction);
} }

View File

@ -1,9 +1,8 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Config, QueueController } from '../../interface'; import { Config, QueueController, RouteChain, RouterDirection, RouterEventDetail, RouterIntent } from '../../interface';
import { debounce } from '../../utils/helpers'; import { debounce } from '../../utils/helpers';
import { printRedirects, printRoutes } from './utils/debug'; import { printRedirects, printRoutes } from './utils/debug';
import { readNavState, waitUntilNavNode, writeNavState } from './utils/dom'; import { readNavState, waitUntilNavNode, writeNavState } from './utils/dom';
import { RouteChain, RouterDirection, RouterEventDetail } from './utils/interface';
import { routeRedirect, routerIDsToChain, routerPathToChain } from './utils/matching'; import { routeRedirect, routerIDsToChain, routerPathToChain } from './utils/matching';
import { readRedirects, readRoutes } from './utils/parser'; import { readRedirects, readRoutes } from './utils/parser';
import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path'; import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path';
@ -73,12 +72,13 @@ export class Router {
} }
@Method() @Method()
push(url: string, direction = RouterDirection.Forward) { push(url: string, direction: RouterDirection = 'forward') {
const path = parsePath(url); const path = parsePath(url);
const intent = DIRECTION_TO_INTENT[direction];
console.debug('[ion-router] URL pushed -> updating nav', url, direction); console.debug('[ion-router] URL pushed -> updating nav', url, direction);
this.setPath(path, direction); this.setPath(path, intent);
return this.writeNavStateRoot(path, direction); return this.writeNavStateRoot(path, intent);
} }
@Method() @Method()
@ -90,7 +90,7 @@ export class Router {
} }
@Method() @Method()
async navChanged(direction: RouterDirection): Promise<boolean> { async navChanged(intent: RouterIntent): Promise<boolean> {
if (this.busy) { if (this.busy) {
return false; return false;
} }
@ -109,21 +109,21 @@ export class Router {
} }
console.debug('[ion-router] nav changed -> update URL', ids, path); console.debug('[ion-router] nav changed -> update URL', ids, path);
this.setPath(path, direction); this.setPath(path, intent);
await this.writeNavState(outlet, chain, RouterDirection.None, path, null, ids.length); await this.writeNavState(outlet, chain, RouterIntent.None, path, null, ids.length);
return true; return true;
} }
private onRedirectChanged() { private onRedirectChanged() {
const path = this.getPath(); const path = this.getPath();
if (path && routeRedirect(path, readRedirects(this.el))) { if (path && routeRedirect(path, readRedirects(this.el))) {
this.writeNavStateRoot(path, RouterDirection.None); this.writeNavStateRoot(path, RouterIntent.None);
} }
} }
private onRoutesChanged() { private onRoutesChanged() {
return this.writeNavStateRoot(this.getPath(), RouterDirection.None); return this.writeNavStateRoot(this.getPath(), RouterIntent.None);
} }
private historyDirection() { private historyDirection() {
@ -137,16 +137,16 @@ export class Router {
this.lastState = state; this.lastState = state;
if (state > lastState) { if (state > lastState) {
return RouterDirection.Forward; return RouterIntent.Forward;
} else if (state < lastState) { } else if (state < lastState) {
return RouterDirection.Back; return RouterIntent.Back;
} else { } else {
return RouterDirection.None; return RouterIntent.None;
} }
} }
private async writeNavStateRoot(path: string[]|null, direction: RouterDirection): Promise<boolean> { private async writeNavStateRoot(path: string[]|null, intent: RouterIntent): Promise<boolean> {
if (this.busy) { if (this.busy) {
return false; return false;
} }
@ -160,7 +160,7 @@ export class Router {
const redirect = routeRedirect(path, redirects); const redirect = routeRedirect(path, redirects);
let redirectFrom: string[]|null = null; let redirectFrom: string[]|null = null;
if (redirect) { if (redirect) {
this.setPath(redirect.to, direction); this.setPath(redirect.to, intent);
redirectFrom = redirect.from; redirectFrom = redirect.from;
path = redirect.to; path = redirect.to;
} }
@ -174,11 +174,11 @@ export class Router {
} }
// write DOM give // write DOM give
return this.writeNavState(this.win.document.body, chain, direction, path, redirectFrom); return this.writeNavState(this.win.document.body, chain, intent, path, redirectFrom);
} }
private async writeNavState( private async writeNavState(
node: HTMLElement|undefined, chain: RouteChain, direction: RouterDirection, node: HTMLElement|undefined, chain: RouteChain, intent: RouterIntent,
path: string[], redirectFrom: string[] | null, path: string[], redirectFrom: string[] | null,
index = 0 index = 0
): Promise<boolean> { ): Promise<boolean> {
@ -191,7 +191,7 @@ export class Router {
const routeEvent = this.routeChangeEvent(path, redirectFrom); const routeEvent = this.routeChangeEvent(path, redirectFrom);
routeEvent && this.ionRouteWillChange.emit(routeEvent); routeEvent && this.ionRouteWillChange.emit(routeEvent);
const changed = await writeNavState(node, chain, direction, index); const changed = await writeNavState(node, chain, intent, index);
this.busy = false; this.busy = false;
if (changed) { if (changed) {
@ -204,9 +204,9 @@ export class Router {
return changed; return changed;
} }
private setPath(path: string[], direction: RouterDirection) { private setPath(path: string[], intent: RouterIntent) {
this.state++; this.state++;
writePath(this.win.history, this.root, this.useHash, path, direction, this.state); writePath(this.win.history, this.root, this.useHash, path, intent, this.state);
} }
private getPath(): string[] | null { private getPath(): string[] | null {
@ -228,3 +228,9 @@ export class Router {
}; };
} }
} }
const DIRECTION_TO_INTENT = {
'back': RouterIntent.Back,
'root': RouterIntent.None,
'forward': RouterIntent.Forward
};

View File

@ -1,6 +1,6 @@
import { NavOutletElement, RouteChain, RouteID, RouterDirection } from './interface'; import { NavOutletElement, RouteChain, RouteID, RouterIntent } from '../../../interface';
export async function writeNavState(root: HTMLElement | undefined, chain: RouteChain, direction: RouterDirection, index: number, changed = false): Promise<boolean> { export async function writeNavState(root: HTMLElement | undefined, chain: RouteChain, intent: RouterIntent, index: number, changed = false): Promise<boolean> {
try { try {
// find next navigation outlet in the DOM // find next navigation outlet in the DOM
const outlet = searchNavNode(root); const outlet = searchNavNode(root);
@ -12,17 +12,17 @@ export async function writeNavState(root: HTMLElement | undefined, chain: RouteC
await outlet.componentOnReady(); await outlet.componentOnReady();
const route = chain[index]; const route = chain[index];
const result = await outlet.setRouteId(route.id, route.params, direction); const result = await outlet.setRouteId(route.id, route.params, intent);
// if the outlet changed the page, reset navigation to neutral (no direction) // if the outlet changed the page, reset navigation to neutral (no direction)
// this means nested outlets will not animate // this means nested outlets will not animate
if (result.changed) { if (result.changed) {
direction = RouterDirection.None; intent = RouterIntent.None;
changed = true; changed = true;
} }
// recursivelly set nested outlets // recursivelly set nested outlets
changed = await writeNavState(result.element, chain, direction, index + 1, changed); changed = await writeNavState(result.element, chain, intent, index + 1, changed);
// once all nested outlets are visible let's make the parent visible too, // once all nested outlets are visible let's make the parent visible too,
// using markVisible prevents flickering // using markVisible prevents flickering

View File

@ -1,6 +1,6 @@
export interface NavOutlet { export interface NavOutlet {
setRouteId(id: string, data: any, direction: number): Promise<RouteWrite>; setRouteId(id: string, data: any, direction: RouterIntent): Promise<RouteWrite>;
getRouteId(): RouteID|undefined; getRouteId(): RouteID|undefined;
} }
@ -10,7 +10,9 @@ export interface RouterEventDetail {
to: string; to: string;
} }
export const enum RouterDirection { export type RouterDirection = 'forward' | 'back' | 'root';
export const enum RouterIntent {
None = 0, None = 0,
Forward = 1, Forward = 1,
Back = -1, Back = -1,

View File

@ -1,4 +1,4 @@
import { RouteChain, RouterDirection } from './interface'; import { RouteChain, RouterIntent } from '../../../interface';
export function generatePath(segments: string[]): string { export function generatePath(segments: string[]): string {
const path = segments const path = segments
@ -26,7 +26,7 @@ export function chainToPath(chain: RouteChain): string[]|null {
return path; return path;
} }
export function writePath(history: History, root: string, useHash: boolean, path: string[], direction: RouterDirection, state: number) { export function writePath(history: History, root: string, useHash: boolean, path: string[], intent: RouterIntent, state: number) {
let url = generatePath([ let url = generatePath([
...parsePath(root), ...parsePath(root),
...path ...path
@ -34,7 +34,7 @@ export function writePath(history: History, root: string, useHash: boolean, path
if (useHash) { if (useHash) {
url = '#' + url; url = '#' + url;
} }
if (direction === RouterDirection.Forward) { if (intent === RouterIntent.Forward) {
history.pushState(state, '', url); history.pushState(state, '', url);
} else { } else {
history.replaceState(state, '', url); history.replaceState(state, '', url);

View File

@ -1,5 +1,5 @@
import { Build, Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core'; import { Build, Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
import { Config, NavOutlet, RouteID, RouteWrite, RouterDirection } from '../../interface'; import { Config, NavOutlet, RouteID, RouteWrite, RouterIntent } from '../../interface';
import { TabbarLayout, TabbarPlacement } from '../tabbar/tabbar'; import { TabbarLayout, TabbarPlacement } from '../tabbar/tabbar';
@ -262,7 +262,7 @@ export class Tabs implements NavOutlet {
if (this.useRouter) { if (this.useRouter) {
const router = this.doc.querySelector('ion-router'); const router = this.doc.querySelector('ion-router');
if (router) { if (router) {
return router.navChanged(RouterDirection.Forward); return router.navChanged(RouterIntent.Forward);
} }
} }
return Promise.resolve(false); return Promise.resolve(false);

View File

@ -1,4 +1,4 @@
import { CssClassMap, Mode } from '../interface'; import { CssClassMap, Mode, RouterDirection } from '../interface';
/** /**
* Create the mode and color classes for the component based on the classes passed in * Create the mode and color classes for the component based on the classes passed in
@ -64,22 +64,14 @@ export function getClassMap(classes: string | string[] | undefined): CssClassMap
return map; return map;
} }
export type RouterDirection = 'forward' | 'back' | 'root'; export async function openURL(win: Window, url: string|undefined, ev: Event, direction?: RouterDirection) {
export async function openURL(win: Window, url: string|undefined, ev: Event, direction: RouterDirection = 'forward') {
if (url && url[0] !== '#' && url.indexOf('://') === -1) { if (url && url[0] !== '#' && url.indexOf('://') === -1) {
const router = win.document.querySelector('ion-router'); const router = win.document.querySelector('ion-router');
if (router) { if (router) {
ev && ev.preventDefault(); ev && ev.preventDefault();
await router.componentOnReady(); await router.componentOnReady();
return router.push(url, DIRECTION_MAP[direction]); return router.push(url, direction);
} }
} }
return Promise.resolve(); return Promise.resolve();
} }
const DIRECTION_MAP = {
'back': -1,
'root': 0,
'forward': 1
};