Skip to content

Commit

Permalink
feature(navigation): modify urls to support multiple root level navs/…
Browse files Browse the repository at this point in the history
…tabs

* wip

* wip

* progress

* wippy skippy

* getting there

* all tests passing except goBack

* unit tests pass again boi

* goBack tests pass

* great success

* the good stuff
  • Loading branch information
danbucholtz authored Jun 19, 2017
1 parent e3a8d27 commit 5cad965
Show file tree
Hide file tree
Showing 132 changed files with 3,035 additions and 1,245 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"scripts": {
"test": "gulp validate",
"test:generators": "jasmine-node ./tooling/spec",
"link": "gulp release.prepareReleasePackage && cd dist/ionic-angular && npm link"
"link": "gulp release.prepareReleasePackage && cd dist/ionic-angular && npm link",
"tsc": "tsc --outdir .tmp"
},
"dependencies": {
"@angular/common": "4.1.3",
Expand Down
91 changes: 59 additions & 32 deletions src/components/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import * as Constants from './app-constants';
import { ClickBlock } from './click-block';
import { runInDev, assert } from '../../util/util';
import { Config } from '../../config/config';
import { isNav, NavOptions, DIRECTION_FORWARD, DIRECTION_BACK } from '../../navigation/nav-util';
import { NavOptions, DIRECTION_FORWARD, DIRECTION_BACK, isTabs } from '../../navigation/nav-util';
import { MenuController } from './menu-controller';
import { NavController } from '../../navigation/nav-controller';
import { NavigationContainer } from '../../navigation/navigation-container';
import { NavControllerBase } from '../../navigation/nav-controller-base';
import { Platform } from '../../platform/platform';
import { ViewController } from '../../navigation/view-controller';
import { IOSTransition } from '../../transitions/transition-ios';
Expand All @@ -28,7 +29,7 @@ export class App {
private _scrollTime: number = 0;
private _title: string = '';
private _titleSrv: Title = new Title(DOCUMENT);
private _rootNav: NavController = null;
private _rootNavs = new Map<string, NavigationContainer>();
private _disableScrollAssist: boolean;
private _didScroll = false;

Expand Down Expand Up @@ -207,26 +208,38 @@ export class App {
/**
* @return {NavController} Returns the active NavController. Using this method is preferred when we need access to the top-level navigation controller while on the outside views and handlers like `registerBackButtonAction()`
*/
getActiveNav(): NavController {
getActiveNav(navId: string): NavControllerBase {
const portal = this._appRoot._getPortal(Constants.PORTAL_MODAL);
if (portal.length() > 0) {
return findTopNav(portal);
return <NavControllerBase> findTopNav(portal);
}
return findTopNav(this._rootNav || null);
if (!this._rootNavs || !this._rootNavs.size || !this._rootNavs.has(navId)) {
return null;
}
return <NavControllerBase> findTopNav(this.getRootNavById(navId));
}

/**
* @return {NavController} Returns the root NavController
*/
getRootNav(): NavController {
return this._rootNav;
getRootNavById(navId: string): NavigationContainer {
return this._rootNavs.get(navId);
}

/**
* @hidden
*/
_setRootNav(nav: any) {
this._rootNav = nav;
registerRootNav(nav: NavigationContainer) {
this._rootNavs.set(nav.id, nav);
}

getActiveNavContainers(): NavigationContainer[] {
// for each root nav container, get it's active nav
const list: NavigationContainer[] = [];
this._rootNavs.forEach((container: NavigationContainer) => {
list.push(findTopNav(container));
});
return list;
}

/**
Expand Down Expand Up @@ -266,7 +279,7 @@ export class App {
}

const navPromise = this.navPop();
if (navPromise === null) {
if (!navPromise) {
// no views to go back to
// let's exit the app
if (this._config.getBoolean('navExitApp', true)) {
Expand All @@ -281,7 +294,7 @@ export class App {
* @hidden
*/
navPop(): Promise<any> {
if (!this._rootNav || !this.isEnabled()) {
if (!this._rootNavs || this._rootNavs.size === 0 || !this.isEnabled()) {
return Promise.resolve();
}

Expand All @@ -290,9 +303,23 @@ export class App {
if (portal.length() > 0) {
return Promise.resolve();
}
// next get the active nav, check itself and climb up all
// of its parent navs until it finds a nav that can pop
return recursivePop(this.getActiveNav());

let navToPop: NavControllerBase = null;
let mostRecentVC: ViewController = null;
this._rootNavs.forEach((navContainer: NavigationContainer) => {
const activeNav = this.getActiveNav(navContainer.id);
const poppable = getPoppableNav(activeNav);
if (poppable) {
const topViewController = poppable.last();
if (poppable._isPortal || (topViewController && poppable.length() > 1 && (!mostRecentVC || topViewController._ts >= mostRecentVC._ts))) {
mostRecentVC = topViewController;
navToPop = poppable;
}
}
});
if (navToPop) {
return navToPop.pop();
}
}

/**
Expand Down Expand Up @@ -351,34 +378,34 @@ export class App {

}

function recursivePop(nav: any): Promise<any> {

function getPoppableNav(nav: NavControllerBase): NavControllerBase {
if (!nav) {
return null;
}
if (isNav(nav)) {
var len = nav.length();
if (len > 1 || (nav._isPortal && len > 0)) {
// this nav controller has more than one view
// pop the current view on this nav and we're done here
console.debug('app, goBack pop nav');
return nav.pop();
}

if (isTabs(nav)) {
// tabs aren't a nav, so just call this function again immediately on the parent on tabs
return getPoppableNav(nav.parent);
}
const len = nav.length();
if (len > 1 || (nav._isPortal && len > 0)) {
// this nav controller has more than one view
// use this nav!
return nav;
}
// try again using the parent nav (if there is one)
return recursivePop(nav.parent);
return getPoppableNav(nav.parent);
}

function findTopNav(nav: NavController) {
var activeChildNav: any;

function findTopNav(nav: NavigationContainer): NavigationContainer {
while (nav) {
activeChildNav = nav.getActiveChildNav();
if (!activeChildNav) {
const childNav = nav.getActiveChildNav();
if (!childNav) {
break;
}
nav = activeChildNav;
nav = childNav;
}

return nav;
}

Expand Down
16 changes: 15 additions & 1 deletion src/components/app/overlay-portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DeepLinker } from '../../navigation/deep-linker';
import { DomController } from '../../platform/dom-controller';
import { GestureController } from '../../gestures/gesture-controller';
import { NavControllerBase } from '../../navigation/nav-controller-base';
import { NavigationContainer } from '../../navigation/navigation-container';
import { Platform } from '../../platform/platform';
import { TransitionController } from '../../transitions/transition-controller';
import { ViewController } from '../../navigation/view-controller';
Expand All @@ -16,7 +17,7 @@ import { ViewController } from '../../navigation/view-controller';
@Directive({
selector: '[overlay-portal]',
})
export class OverlayPortal extends NavControllerBase {
export class OverlayPortal extends NavControllerBase implements NavigationContainer {
constructor(
@Inject(forwardRef(() => App)) app: App,
config: Config,
Expand Down Expand Up @@ -55,4 +56,17 @@ export class OverlayPortal extends NavControllerBase {
this.destroy();
}

/*
* @private
*/
getType() {
return 'portal';
}

/*
* @private
*/
getSecondaryIdentifier(): string {
return null;
}
}
Loading

0 comments on commit 5cad965

Please sign in to comment.