chore(cleanup): remove unused code

This commit is contained in:
Adam Bradley
2018-03-06 19:56:53 -06:00
parent 7b264f983b
commit a1f942d45e
18 changed files with 6 additions and 1320 deletions

View File

@ -1,37 +0,0 @@
import { InjectionToken } from '@angular/core';
import { NavController } from '../providers/nav-controller';
import { NavParams } from '../providers/nav-params';
export const NavControllerToken = new InjectionToken<any>('NavControllerToken');
export const NavParamsToken = new InjectionToken<any>('NavParamsToken');
export function getProviders(element: HTMLElement, data: any) {
const nearestNavElement = (element.tagName.toLowerCase() === 'ion-nav' ? element : element.closest('ion-nav')) as HTMLIonNavElement;
return [
{
provide: NavControllerToken, useValue: nearestNavElement
},
{
provide: NavController, useFactory: provideNavControllerInjectable, deps: [NavControllerToken]
},
{
provide: NavParamsToken, useValue: data
},
{
provide: NavParams, useFactory: provideNavParamsInjectable, deps: [NavParamsToken]
},
];
}
export function provideNavControllerInjectable(element: HTMLIonNavElement) {
return new NavController(element);
}
export function provideNavParamsInjectable(data: any) {
return new NavParams(data);
}

View File

@ -1,45 +0,0 @@
import {
ComponentFactoryResolver,
Directive,
ElementRef,
Injector,
Type,
} from '@angular/core';
import { FrameworkDelegate } from '@ionic/core';
import { AngularComponentMounter, AngularEscapeHatch } from '..';
@Directive({
selector: 'ion-nav',
})
export class IonNav implements FrameworkDelegate {
constructor(
public elementRef: ElementRef,
protected angularComponentMounter: AngularComponentMounter,
protected cfr: ComponentFactoryResolver,
protected injector: Injector
) {
this.elementRef.nativeElement.delegate = this;
}
attachViewToDom(elementOrContainerToMountTo: HTMLIonNavElement,
elementOrComponentToMount: Type<any>,
data?: any,
classesToAdd?: string[],
escapeHatch: AngularEscapeHatch = {}): Promise<any> {
// wrap whatever the user provides in an ion-page
const cfr = escapeHatch.cfr || this.cfr;
const injector = escapeHatch.injector || this.injector;
return this.angularComponentMounter.attachViewToDom(elementOrContainerToMountTo,
null, elementOrComponentToMount, cfr, injector, data, classesToAdd);
}
removeViewFromDom(parentElement: HTMLElement, childElement: HTMLElement) {
return this.angularComponentMounter.removeViewFromDom(parentElement, childElement);
}
}

View File

@ -1,84 +0,0 @@
import {
ApplicationRef,
ComponentFactoryResolver,
Injectable,
Injector,
NgZone,
Type
} from '@angular/core';
import { getProviders } from '../di/di';
import { AngularMountingData } from '../types/interfaces';
const elementToComponentRefMap = new Map<HTMLElement, AngularMountingData>();
@Injectable()
export class AngularComponentMounter {
constructor(private defaultCfr: ComponentFactoryResolver, private zone: NgZone, private appRef: ApplicationRef) {
}
attachViewToDom(parentElement: HTMLElement, hostElement: HTMLElement, componentToMount: Type<any>, componentResolveFactory: ComponentFactoryResolver, injector: Injector, data: any, classesToAdd: string[]): Promise<AngularMountingData> {
return new Promise((resolve) => {
this.zone.run(() => {
const crf = componentResolveFactory ? componentResolveFactory : this.defaultCfr;
const mountingData = this.attachViewToDomImpl(crf, parentElement, hostElement, componentToMount, injector, this.appRef, data, classesToAdd);
resolve(mountingData);
});
});
}
removeViewFromDom(parentElement: HTMLElement, childElement: HTMLElement): Promise<any> {
return new Promise((resolve) => {
this.zone.run(() => {
removeViewFromDom(parentElement, childElement);
resolve();
});
});
}
attachViewToDomImpl(crf: ComponentFactoryResolver, parentElement: HTMLElement, hostElement: HTMLElement, componentToMount: Type<any>, injector: Injector, appRef: ApplicationRef, data: any, classesToAdd: string[]): AngularMountingData {
const componentFactory = crf.resolveComponentFactory(componentToMount);
if (!hostElement) {
hostElement = document.createElement(componentFactory.selector);
}
const childInjector = Injector.create(getProviders(parentElement, data), injector);
const componentRef = componentFactory.create(childInjector, [], hostElement);
for (const clazz of classesToAdd) {
hostElement.classList.add(clazz);
}
parentElement.appendChild(hostElement);
appRef.attachView(componentRef.hostView);
const mountingData = {
component: componentToMount,
componentFactory,
childInjector,
componentRef,
instance: componentRef.instance,
angularHostElement: componentRef.location.nativeElement,
element: hostElement,
data
};
elementToComponentRefMap.set(hostElement, mountingData);
return mountingData;
}
}
export function removeViewFromDom(_parentElement: HTMLElement, childElement: HTMLElement) {
const mountingData = elementToComponentRefMap.get(childElement);
if (mountingData) {
mountingData.componentRef.destroy();
}
}

View File

@ -1,82 +0,0 @@
import { PublicNav } from '@ionic/core';
export class App {
_element: HTMLIonAppElement;
constructor() {
this._element = document.querySelector('ion-app');
}
setTitle(title: string) {
document.title = title;
}
getRootNavs(): PublicNav[] {
return getRootNavsImpl(this);
}
getRootNavsAsync(): Promise<PublicNav[]> {
return getRootNavsAsyncImpl(this);
}
getTopNavs(rootNavId?: number): PublicNav[] {
return getTopNavsImpl(this, rootNavId);
}
getTopNavsAsync(rootNavId?: number): Promise<PublicNav[]> {
return getTopNavsAsyncImpl(this, rootNavId);
}
getNavByIdOrName(nameOrId: number | string): PublicNav {
return getNavByIdOrNameImpl(this, nameOrId);
}
getNavByIdOrNameAsync(nameOrId: number | string): Promise<PublicNav> {
return getNavByIdOrNameAsyncImpl(this, nameOrId);
}
registerBackButtonAction(fn: Function, priority = 0): Promise<() => void> {
return this._element.componentOnReady().then(() => {
return this._element.registerBackButtonAction(fn, priority);
});
}
}
export function getRootNavsImpl(app: App) {
if (app._element && app._element.getRootNavs) {
return app._element.getRootNavs();
}
return [];
}
export function getRootNavsAsyncImpl(app: App) {
return app._element.componentOnReady().then(() => {
return app._element.getRootNavs();
});
}
export function getTopNavsImpl(app: App, rootNavId?: number): PublicNav[] {
if (app._element && app._element.getTopNavs) {
return app._element.getTopNavs(rootNavId);
}
return [];
}
export function getTopNavsAsyncImpl(app: App, rootNavId?: number): Promise<PublicNav[]> {
return app._element.componentOnReady().then(() => {
return app._element.getTopNavs(rootNavId);
});
}
export function getNavByIdOrNameImpl(app: App, nameOrId: number | string): PublicNav {
if (app._element && app._element.getNavByIdOrName) {
return app._element.getNavByIdOrName(nameOrId);
}
return null;
}
export function getNavByIdOrNameAsyncImpl(app: App, nameOrId: number | string): Promise<PublicNav> {
return app._element.componentOnReady().then(() => {
return app._element.getNavByIdOrName(nameOrId);
});
}

View File

@ -1,31 +1,20 @@
import {
ComponentFactoryResolver,
Injectable,
Injector,
Type,
} from '@angular/core';
import {
FrameworkDelegate,
ModalDismissEvent,
ModalOptions
} from '@ionic/core';
import { AngularComponentMounter } from '../providers/angular-component-mounter';
import { AngularMountingData } from '../types/interfaces';
import { ensureElementInBody, hydrateElement } from '../util/util';
let modalId = 0;
@Injectable()
export class ModalController implements FrameworkDelegate {
constructor(private angularComponentMounter: AngularComponentMounter, private componentResolveFactory: ComponentFactoryResolver, private injector: Injector) {
}
export class ModalController {
create(opts?: ModalOptions): ModalProxy {
opts.delegate = this;
return getModalProxy(opts);
}
@ -36,14 +25,6 @@ export class ModalController implements FrameworkDelegate {
});
}
attachViewToDom(elementOrContainerToMountTo: HTMLElement, elementOrComponentToMount: Type<any>, data?: any, classesToAdd?: string[]): Promise<AngularMountingData> {
return this.angularComponentMounter.attachViewToDom(elementOrContainerToMountTo, null, elementOrComponentToMount, this.componentResolveFactory, this.injector, data, classesToAdd);
}
removeViewFromDom(parentElement: HTMLElement, childElement: HTMLElement) {
return this.angularComponentMounter.removeViewFromDom(parentElement, childElement);
}
}
export function getModalProxy(opts: ModalOptions) {

View File

@ -1,123 +0,0 @@
import { NavOptions, PublicNav, PublicViewController } from '@ionic/core';
import { hydrateElement } from '../util/util';
export class NavController implements PublicNav {
constructor(public element: HTMLIonNavElement) {
}
push(component: any, data?: any, opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.push(component, data, opts);
});
}
pop(opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.pop(opts);
});
}
setRoot(component: any, data?: any, opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.setRoot(component, data, opts);
});
}
insert(insertIndex: number, page: any, params?: any, opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.insert(insertIndex, page, params, opts);
});
}
insertPages(insertIndex: number, insertPages: any[], opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.insertPages(insertIndex, insertPages, opts);
});
}
popToRoot(opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.popToRoot(opts);
});
}
popTo(indexOrViewCtrl: any, opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.popTo(indexOrViewCtrl, opts);
});
}
removeIndex(startIndex: number, removeCount?: number, opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.removeIndex(startIndex, removeCount, opts);
});
}
removeView(viewController: PublicViewController, opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.removeView(viewController, opts);
});
}
setPages(componentDataPairs: any[], opts?: NavOptions): Promise<any> {
return hydrateElement(this.element).then((navElement: HTMLIonNavElement) => {
return navElement.setPages(componentDataPairs, opts);
});
}
getActive(): PublicViewController {
if (this.element.getActive) {
return this.element.getActive();
}
return null;
}
getPrevious(view?: PublicViewController): PublicViewController {
if (this.element.getPrevious) {
return this.element.getPrevious(view);
}
return null;
}
canGoBack(): boolean {
if (this.element.canGoBack) {
return this.element.canGoBack();
}
return false;
}
canSwipeBack(): boolean {
if (this.element.canSwipeBack) {
return this.element.canSwipeBack();
}
return false;
}
first(): PublicViewController {
if (this.element.first) {
return this.element.first();
}
return null;
}
last(): PublicViewController {
if (this.element.last) {
return this.element.last();
}
return null;
}
getViews(): PublicViewController[] {
if (this.element.getViews) {
return this.element.getViews();
}
return [];
}
getChildNavs(): PublicNav[] {
if (this.element.getChildNavs) {
return this.element.getChildNavs();
}
return [];
}
}

View File

@ -1,10 +0,0 @@
export class NavParams {
constructor(public data: any = {}) {
}
get(param: string): any {
return this.data[param];
}
}

View File

@ -1,31 +1,20 @@
import {
ComponentFactoryResolver,
Injectable,
Injector,
Type,
} from '@angular/core';
import {
FrameworkDelegate,
PopoverDismissEvent,
PopoverOptions
} from '@ionic/core';
import { AngularComponentMounter } from '../providers/angular-component-mounter';
import { AngularMountingData } from '../types/interfaces';
import { ensureElementInBody, hydrateElement } from '../util/util';
let popoverId = 0;
@Injectable()
export class PopoverController implements FrameworkDelegate {
constructor(private angularComponentMounter: AngularComponentMounter, private componentResolveFactory: ComponentFactoryResolver, private injector: Injector) {
}
export class PopoverController {
create(opts?: PopoverOptions): PopoverProxy {
opts.delegate = this;
return getPopoverProxy(opts);
}
@ -35,15 +24,6 @@ export class PopoverController implements FrameworkDelegate {
return popoverController.dismiss(data, role, id);
});
}
attachViewToDom(elementOrContainerToMountTo: HTMLElement, elementOrComponentToMount: Type<any>, data?: any, classesToAdd?: string[]): Promise<AngularMountingData> {
return this.angularComponentMounter.attachViewToDom(elementOrContainerToMountTo, null, elementOrComponentToMount, this.componentResolveFactory, this.injector, data, classesToAdd);
}
removeViewFromDom(parentElement: HTMLElement, childElement: HTMLElement) {
return this.angularComponentMounter.removeViewFromDom(parentElement, childElement);
}
}
export function getPopoverProxy(opts: PopoverOptions) {

View File

@ -1,276 +0,0 @@
import {
ComponentRef
} from '@angular/core';
import {
ActivatedRoute,
ActivatedRouteSnapshot,
ActivationEnd,
ChildActivationEnd,
ChildrenOutletContexts,
Event,
RouteReuseStrategy,
RouterState,
} from '@angular/router';
import {
TreeNode,
advanceActivatedRoute,
forEach,
nodeChildrenAsMap
} from './router-utils';
export class AsyncActivateRoutes {
constructor(
protected routeReuseStrategy: RouteReuseStrategy, protected futureState: RouterState,
protected currState: RouterState, protected forwardEvent: (evt: Event) => void) {}
activate(parentContexts: ChildrenOutletContexts): void | Promise<void> {
const futureRoot = (this.futureState as any)._root;
const currRoot = this.currState ? (this.currState as any)._root : null;
const result = this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
return Promise.resolve(result)
.then(
() => {
advanceActivatedRoute(this.futureState.root);
return this.activateChildRoutes(futureRoot, currRoot, parentContexts);
}
);
}
// De-activate the child route that are not re-used for the future state
protected deactivateChildRoutes(
futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>|null,
contexts: ChildrenOutletContexts): Promise<any> {
const children: {[outletName: string]: TreeNode<ActivatedRoute>} = nodeChildrenAsMap(currNode);
const promises = futureNode.children.map((futureChild: TreeNode<ActivatedRoute>) => {
const childOutletName = futureChild.value.outlet;
const promise = this.deactivateRoutes(futureChild, children[childOutletName], contexts);
promise
.then(
() => {
delete children[childOutletName];
}
);
return promise;
});
return Promise.all(promises)
.then(
() => {
const promises: Promise<void>[] = [];
// De-activate the routes that will not be re-used
forEach(children, (v: TreeNode<ActivatedRoute>) => {
promises.push(this.deactivateRouteAndItsChildren(v, contexts));
});
return Promise.all(promises);
}
);
}
protected deactivateRoutes(
futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>,
parentContext: ChildrenOutletContexts): Promise<void> {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
if (future === curr) {
// Reusing the node, check to see if the children need to be de-activated
if (future.component) {
// If we have a normal route, we need to go through an outlet.
const context = parentContext.getContext(future.outlet);
if (context) {
return this.deactivateChildRoutes(futureNode, currNode, context.children);
}
return Promise.resolve();
} else {
// if we have a componentless route, we recurse but keep the same outlet map.
return this.deactivateChildRoutes(futureNode, currNode, parentContext);
}
} else {
if (curr) {
// Deactivate the current route which will not be re-used
return this.deactivateRouteAndItsChildren(currNode, parentContext);
}
return Promise.resolve();
}
}
protected deactivateRouteAndItsChildren(
route: TreeNode<ActivatedRoute>, parentContexts: ChildrenOutletContexts): Promise<void> {
if (this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
return this.detachAndStoreRouteSubtree(route, parentContexts);
} else {
return this.deactivateRouteAndOutlet(route, parentContexts);
}
}
protected detachAndStoreRouteSubtree(
route: TreeNode<ActivatedRoute>, parentContexts: ChildrenOutletContexts): Promise<void> {
const context = parentContexts.getContext(route.value.outlet);
if (context && context.outlet) {
const componentRefOrPromise = context.outlet.detach();
return Promise.resolve(componentRefOrPromise)
.then(
(componentRef: ComponentRef<any>) => {
const contexts = context.children.onOutletDeactivated();
this.routeReuseStrategy.store(route.value.snapshot, {componentRef, route, contexts});
}
);
}
return Promise.resolve();
}
protected deactivateRouteAndOutlet(
route: TreeNode<ActivatedRoute>, parentContexts: ChildrenOutletContexts): Promise<void> {
const context = parentContexts.getContext(route.value.outlet);
if (context) {
const children: {[outletName: string]: any} = nodeChildrenAsMap(route);
const contexts = route.value.component ? context.children : parentContexts;
const promises: Promise<void>[] = [];
forEach(children, (v: any) => {
promises.push(this.deactivateRouteAndItsChildren(v, contexts));
});
return Promise.all(promises)
.then(
() => {
if (context.outlet) {
// Destroy the component
const result = context.outlet.deactivate();
return Promise.resolve(result);
}
return Promise.resolve();
}
)
.then(
() => {
context.children.onOutletDeactivated();
}
);
}
return Promise.resolve();
}
protected activateChildRoutes(
futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>|null,
contexts: ChildrenOutletContexts): Promise<void> {
const children: {[outlet: string]: any} = nodeChildrenAsMap(currNode);
const promises = futureNode.children.map((c: TreeNode<ActivatedRoute>) => {
const promise = this.activateRoutes(c, children[c.value.outlet], contexts);
promise
.then(
() => {
this.forwardEvent(new ActivationEnd(c.value.snapshot));
}
);
return promise;
});
return Promise.all(promises)
.then(
() => {
if (futureNode.children.length) {
this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot));
}
}
);
}
protected activateRoutes(
futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>,
parentContexts: ChildrenOutletContexts): Promise<void> {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
advanceActivatedRoute(future);
// reusing the node
if (future === curr) {
if (future.component) {
// If we have a normal route, we need to go through an outlet.
const context = parentContexts.getOrCreateContext(future.outlet);
return this.activateChildRoutes(futureNode, currNode, context.children);
} else {
// if we have a componentless route, we recurse but keep the same outlet map.
return this.activateChildRoutes(futureNode, currNode, parentContexts);
}
} else {
if (future.component) {
// if we have a normal route, we need to place the component into the outlet and recurse.
const context = parentContexts.getOrCreateContext(future.outlet);
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
const stored =
(<any>this.routeReuseStrategy.retrieve(future.snapshot));
this.routeReuseStrategy.store(future.snapshot, null);
context.children.onOutletReAttached(stored.contexts);
context.attachRef = stored.componentRef;
context.route = stored.route.value;
if (context.outlet) {
// Attach right away when the outlet has already been instantiated
// Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated
const result = context.outlet.attach(stored.componentRef, stored.route.value);
return Promise.resolve(result)
.then(
() => {
return this.advanceActivatedRouteNodeAndItsChildren(stored.route);
}
);
}
return Promise.resolve(this.advanceActivatedRouteNodeAndItsChildren(stored.route));
} else {
const config = this.parentLoadedConfig(future.snapshot);
const cmpFactoryResolver = config ? config.module.componentFactoryResolver : null;
context.route = future;
context.resolver = cmpFactoryResolver;
if (context.outlet) {
// Activate the outlet when it has already been instantiated
// Otherwise it will get activated from its `ngOnInit` when instantiated
const result = context.outlet.activateWith(future, cmpFactoryResolver);
return Promise.resolve(result)
.then(
() => {
return this.activateChildRoutes(futureNode, null, context.children);
}
);
}
return this.activateChildRoutes(futureNode, null, context.children);
}
} else {
// if we have a componentless route, we recurse but keep the same outlet map.
return this.activateChildRoutes(futureNode, null, parentContexts);
}
}
}
advanceActivatedRouteNodeAndItsChildren(node: TreeNode<ActivatedRoute>): void {
advanceActivatedRoute(node.value);
node.children.forEach(this.advanceActivatedRouteNodeAndItsChildren);
}
parentLoadedConfig(snapshot: ActivatedRouteSnapshot): any|null {
for (let s = snapshot.parent; s; s = s.parent) {
const route = s.routeConfig as any;
if (route && route._loadedConfig) return route._loadedConfig;
if (route && route.component) return null;
}
return null;
}
}

View File

@ -1,103 +0,0 @@
import {
Event,
NavigationCancel,
NavigationEnd,
NavigationError,
RouterState,
UrlTree
} from '@angular/router';
import { Observable } from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import { AsyncActivateRoutes } from './async-activated-routes';
export function monkeyPatchRouter(router: any) {
router.activateRoutes = (state: Observable<{appliedUrl: string, state: RouterState, shouldActivate: boolean}>, storedState: RouterState,
storedUrl: UrlTree, id: number, url: UrlTree, rawUrl: UrlTree, skipLocationChange: boolean, replaceUrl: boolean, resolvePromise: any, rejectPromise: any) => {
// applied the new router state
// this operation has side effects
let navigationIsSuccessful: boolean;
const routes: AsyncActivateRoutes[] = [];
state
.forEach(({appliedUrl, state, shouldActivate}: any) => {
if (!shouldActivate || id !== router.navigationId) {
navigationIsSuccessful = false;
return;
}
router.currentUrlTree = appliedUrl;
router.rawUrlTree = router.urlHandlingStrategy.merge(router.currentUrlTree, rawUrl);
(router as{routerState: RouterState}).routerState = state;
if (!skipLocationChange) {
const path = router.urlSerializer.serialize(router.rawUrlTree);
if (router.location.isCurrentPathEqualTo(path) || replaceUrl) {
router.location.replaceState(path, '');
} else {
router.location.go(path, '');
}
}
routes.push(new AsyncActivateRoutes(router.routeReuseStrategy, state, storedState, (evt: Event) => router.triggerEvent(evt)));
})
.then(
() => {
const promises = routes.map(activatedRoute => activatedRoute.activate(router.rootContexts));
return Promise.all(promises)
.then(
() => {
navigationIsSuccessful = true;
}
);
}
)
.then(
() => {
if (navigationIsSuccessful) {
router.navigated = true;
router.lastSuccessfulId = id;
(router.events as Subject<Event>)
.next(new NavigationEnd(
id, router.serializeUrl(url), router.serializeUrl(router.currentUrlTree)));
resolvePromise(true);
} else {
router.resetUrlToCurrentUrlTree();
(router.events as Subject<Event>)
.next(new NavigationCancel(id, router.serializeUrl(url), ''));
resolvePromise(false);
}
},
(e: any) => {
if (isNavigationCancelingError(e)) {
router.navigated = true;
router.resetStateAndUrl(storedState, storedUrl, rawUrl);
(router.events as Subject<Event>)
.next(new NavigationCancel(id, router.serializeUrl(url), e.message));
resolvePromise(false);
} else {
router.resetStateAndUrl(storedState, storedUrl, rawUrl);
(router.events as Subject<Event>)
.next(new NavigationError(id, router.serializeUrl(url), e));
try {
resolvePromise(router.errorHandler(e));
} catch (ee) {
rejectPromise(ee);
}
}
});
};
}
function isNavigationCancelingError(error: any) {
return error && (/** @type {?} */ (error))[NAVIGATION_CANCELING_ERROR];
}
const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';

View File

@ -1,23 +0,0 @@
import { Injector } from '@angular/core';
import {
ActivatedRoute,
ChildrenOutletContexts
} from '@angular/router';
export class OutletInjector implements Injector {
constructor(private route: ActivatedRoute, private childContexts: ChildrenOutletContexts, private parent: Injector) {
}
get(token: any, notFoundValue?: any): any {
if (token === ActivatedRoute) {
return this.route;
}
if (token === ChildrenOutletContexts) {
return this.childContexts;
}
return this.parent.get(token, notFoundValue);
}
}

View File

@ -1,201 +0,0 @@
import {
Attribute,
ChangeDetectorRef,
ComponentFactoryResolver,
ComponentRef,
Directive,
ElementRef,
EventEmitter,
Injector,
OnDestroy,
OnInit,
Output,
Type,
ViewContainerRef,
} from '@angular/core';
import {
ActivatedRoute,
ChildrenOutletContexts,
PRIMARY_OUTLET,
Router
} from '@angular/router';
import { RouterDelegate } from '@ionic/core';
import { OutletInjector } from './outlet-injector';
import { RouteEventHandler } from './route-event-handler';
import { AngularComponentMounter, AngularEscapeHatch } from '..';
import { getIonApp } from '../util/util';
let id = 0;
@Directive({
selector: 'ion-nav',
})
export class RouterOutlet implements OnDestroy, OnInit, RouterDelegate {
public name: string;
public activationStatus = NOT_ACTIVATED;
public componentConstructor: Type<any> = null;
public componentInstance: any = null;
public activatedRoute: ActivatedRoute = null;
public activatedRouteData: any = {};
public activeComponentRef: ComponentRef<any> = null;
private id: number = id++;
@Output('activate') activateEvents = new EventEmitter<any>();
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
constructor(
public location: ViewContainerRef,
public changeDetector: ChangeDetectorRef,
public elementRef: ElementRef,
protected angularComponentMounter: AngularComponentMounter,
protected parentContexts: ChildrenOutletContexts,
protected cfr: ComponentFactoryResolver,
protected injector: Injector,
protected router: Router,
private routeEventHandler: RouteEventHandler,
@Attribute('name') name: string) {
(this.elementRef.nativeElement as HTMLIonNavElement).routerDelegate = this;
this.name = name || PRIMARY_OUTLET;
parentContexts.onChildOutletCreated(this.name, this as any);
}
pushUrlState(urlSegment: string): Promise<any> {
return this.router.navigateByUrl(urlSegment);
}
popUrlState(): Promise<any> {
window.history.back();
return Promise.resolve();
}
ngOnDestroy(): void {
console.debug(`Nav ${this.id} ngOnDestroy`);
this.parentContexts.onChildOutletDestroyed(this.name);
}
get isActivated(): boolean {
return this.activationStatus === ACTIVATION_IN_PROGRESS
|| this.activationStatus === ACTIVATED;
}
ngOnInit(): void {
if (!this.isActivated) {
// If the outlet was not instantiated at the time the route got activated we need to populate
// the outlet when it is initialized (ie inside a NgIf)
const context = this.parentContexts.getContext(this.name);
if (context && context.route) {
// the component defined in the configuration is created
// otherwise the component defined in the configuration is created
this.activateWith(context.route, context.resolver || null);
}
}
}
get component(): Object {
return this.componentInstance;
}
deactivate(): void {
console.debug(`outlet ${this.id} is being deactivated`);
this.activationStatus = NOT_ACTIVATED;
this.deactivateEvents.emit(this.componentConstructor);
}
activateWith(activatedRoute: ActivatedRoute, cfr: ComponentFactoryResolver): Promise<void> {
if (this.activationStatus !== NOT_ACTIVATED) {
return Promise.resolve();
}
this.activationStatus = ACTIVATION_IN_PROGRESS;
this.activatedRoute = activatedRoute;
const snapshot = (activatedRoute as any)._futureSnapshot;
const component = snapshot.routeConfig ? snapshot.routeConfig.component : null;
cfr = cfr || this.cfr;
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
const isTopLevel = !hasChildComponent(activatedRoute);
return this.routeEventHandler.externalNavStart().then(() => {
return getDataFromRoute(activatedRoute);
}).then((dataObj: any) => {
return activateRoute(this.elementRef.nativeElement, component, dataObj, cfr, injector, isTopLevel).then(() => {
this.changeDetector.markForCheck();
this.activateEvents.emit(null);
this.activationStatus = ACTIVATED;
});
});
}
}
export function activateRoute(navElement: HTMLIonNavElement,
component: Type<any>, data: any = {}, cfr: ComponentFactoryResolver, injector: Injector, isTopLevel: boolean): Promise<any> {
return getIonApp().then((ionApp) => {
if (!ionApp) {
return Promise.reject(new Error(`<ion-app> element is required for angular router integration`));
}
const escapeHatch = getEscapeHatch(cfr, injector);
return navElement.componentOnReady().then(() => {
return navElement.reconcileFromExternalRouter(component, data, escapeHatch, isTopLevel);
});
});
}
export const NOT_ACTIVATED = 0;
export const ACTIVATION_IN_PROGRESS = 1;
export const ACTIVATED = 2;
export function hasChildComponent(activatedRoute: ActivatedRoute): boolean {
// don't worry about recursion for now, that's a future problem that may or may not manifest itself
for (const childRoute of activatedRoute.children) {
if (childRoute.component) {
return true;
}
}
return false;
}
export function getEscapeHatch(cfr: ComponentFactoryResolver, injector: Injector): AngularEscapeHatch {
return {
cfr,
injector,
fromExternalRouter: true,
url: location.pathname
};
}
export function getDataFromRoute(activatedRoute: ActivatedRoute): Promise<any> {
const promises: Promise<any>[] = [];
promises.push(getDataFromObservable(activatedRoute));
promises.push(getDataFromParams(activatedRoute));
return Promise.all(promises).then(([data, params]: any[]) => {
const combined = {};
Object.assign(combined, data, params);
return combined;
});
}
export function getDataFromObservable(activatedRoute: ActivatedRoute) {
return new Promise((resolve) => {
activatedRoute.data.subscribe((data: any) => {
resolve(data || {});
});
});
}
export function getDataFromParams(activatedRoute: ActivatedRoute) {
return new Promise((resolve) => {
activatedRoute.params.subscribe((data: any) => {
resolve(data || {});
});
});
}

View File

@ -1,41 +0,0 @@
import {
ComponentFactoryResolver,
ComponentRef
} from '@angular/core';
import {
ActivatedRoute,
ChildrenOutletContexts,
OutletContext,
RouterOutlet
} from '@angular/router';
export class PushPopOutletContexts extends ChildrenOutletContexts {
// this method is a public api, but the members in the ChildrenOutletContexts are private
// so we're gonna cheat, 'cause we play to win
onOutletDeactivated(): Map<string, OutletContext> {
return (this as any).contexts;
}
getOrCreateContext(childName: string): OutletContext {
let context = this.getContext(childName) as any;
if (!context) {
context = {
children: new PushPopOutletContexts()
};
(this as any).contexts.set(childName, context);
}
return context;
}
}
export interface PushPopOutletContext {
outlet?: RouterOutlet;
route?: ActivatedRoute;
resolver?: ComponentFactoryResolver;
children?: PushPopOutletContexts;
attachRef: ComponentRef<any>;
}

View File

@ -1,30 +0,0 @@
import { Injectable } from '@angular/core';
import {
Event,
NavigationEnd,
Router
} from '@angular/router';
import { getIonApp } from '../util/util';
@Injectable()
export class RouteEventHandler {
constructor(public router: Router) {
router.events.subscribe((event: Event) => {
if (event instanceof NavigationEnd) {
getIonApp().then((appElement) => {
appElement.updateExternalNavOccuring(false);
});
}
});
}
externalNavStart() {
return getIonApp().then((appElement) => {
appElement.updateExternalNavOccuring(true);
});
}
}

View File

@ -1,115 +0,0 @@
import {
Location
} from '@angular/common';
import {
ApplicationRef,
Compiler,
Injector,
ModuleWithProviders,
NgModule,
NgModuleFactoryLoader,
Optional,
} from '@angular/core';
import {ɵgetDOM as getDOM} from '@angular/platform-browser';
import {
ChildrenOutletContexts,
ExtraOptions,
ROUTER_CONFIGURATION,
ROUTES,
Route,
RouteReuseStrategy,
Router,
UrlHandlingStrategy,
UrlSerializer
} from '@angular/router';
import { IonicAngularModule } from '../module';
import { PushPopOutletContexts } from './push-pop-outlet-contexts';
import { monkeyPatchRouter } from './monkey-patch-router';
import { RouteEventHandler } from './route-event-handler';
import { RouterOutlet } from './outlet';
import { flatten } from './router-utils';
@NgModule({
declarations: [
RouterOutlet
],
imports: [
IonicAngularModule
],
exports: [
RouterOutlet
]
})
export class IonicRouterModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: IonicRouterModule,
providers: [
{
provide: ChildrenOutletContexts,
useClass: PushPopOutletContexts
},
{
provide: Router,
useFactory: setupRouter,
deps: [
ApplicationRef, UrlSerializer, ChildrenOutletContexts, Location, Injector,
NgModuleFactoryLoader, Compiler, ROUTES, ROUTER_CONFIGURATION,
[UrlHandlingStrategy, new Optional()], [RouteReuseStrategy, new Optional()]
]
},
RouteEventHandler
]
};
}
}
export function setupRouter(
_ref: ApplicationRef, urlSerializer: UrlSerializer, contexts: ChildrenOutletContexts,
location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler,
config: Route[][], opts: ExtraOptions = {}, urlHandlingStrategy?: UrlHandlingStrategy,
routeReuseStrategy?: RouteReuseStrategy) {
const router = new Router(
null, urlSerializer, contexts, location, injector, loader, compiler, flatten(config));
monkeyPatchRouter(router);
if (urlHandlingStrategy) {
router.urlHandlingStrategy = urlHandlingStrategy;
}
if (routeReuseStrategy) {
router.routeReuseStrategy = routeReuseStrategy;
}
if (opts.errorHandler) {
router.errorHandler = opts.errorHandler;
}
if (opts.enableTracing) {
const dom = getDOM();
router.events.subscribe((e: any) => {
dom.logGroup(`Router Event: ${(e.constructor).name}`);
dom.log(e.toString());
dom.log(e);
dom.logGroupEnd();
});
}
if (opts.onSameUrlNavigation) {
router.onSameUrlNavigation = opts.onSameUrlNavigation;
}
if (opts.paramsInheritanceStrategy) {
router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy;
}
return router;
}

View File

@ -1,85 +0,0 @@
export function nodeChildrenAsMap<T extends{outlet: string}>(node: TreeNode<T>| null) {
const map: {[outlet: string]: TreeNode<T>} = {};
if (node) {
node.children.forEach(child => map[child.value.outlet] = child);
}
return map;
}
export function forEach<_K, V>(map: {[key: string]: V}, callback: (v: V, k: string) => void): void {
for (const prop in map) {
if (map.hasOwnProperty(prop)) {
callback(map[prop], prop);
}
}
}
export class TreeNode<T> {
constructor(public value: T, public children: TreeNode<T>[]) {}
toString(): string { return `TreeNode(${this.value})`; }
}
/**
* The expectation is that the activate route is created with the right set of parameters.
* So we push new values into the observables only when they are not the initial values.
* And we detect that by checking if the snapshot field is set.
*/
export function advanceActivatedRoute(route: any): void {
if (route.snapshot) {
const currentSnapshot = route.snapshot;
const nextSnapshot = (route)._futureSnapshot;
route.snapshot = nextSnapshot;
if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
(route.queryParams).next(nextSnapshot.queryParams);
}
if (currentSnapshot.fragment !== nextSnapshot.fragment) {
(route.fragment).next(nextSnapshot.fragment);
}
if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
(route.params).next(nextSnapshot.params);
}
if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
(route.url).next(nextSnapshot.url);
}
if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
(route.data).next(nextSnapshot.data);
}
} else {
route.snapshot = (route)._futureSnapshot;
// this is for resolved data
(route.data).next((route)._futureSnapshot.data);
}
}
export function shallowEqualArrays(a: any[], b: any[]): boolean {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; ++i) {
if (!shallowEqual(a[i], b[i])) return false;
}
return true;
}
export function shallowEqual(a: {[x: string]: any}, b: {[x: string]: any}): boolean {
const k1 = Object.keys(a);
const k2 = Object.keys(b);
/*tslint:disable*/
if (k1.length != k2.length) {
return false;
}
let key: string;
for (let i = 0; i < k1.length; i++) {
key = k1[i];
if (a[key] !== b[key]) {
return false;
}
}
return true;
}
export function flatten<T>(arr: T[][]): T[] {
return Array.prototype.concat.apply([], arr);
}

View File

@ -1,26 +1,3 @@
import {
ComponentFactory,
ComponentFactoryResolver,
ComponentRef,
Injector
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EscapeHatch, FrameworkMountingData} from '@ionic/core';
export interface AngularMountingData extends FrameworkMountingData {
componentFactory?: ComponentFactory<any>;
childInjector?: Injector;
componentRef?: ComponentRef<any>;
instance?: any;
angularHostElement?: HTMLElement;
}
export interface AngularEscapeHatch extends EscapeHatch {
activatedRoute?: ActivatedRoute;
cfr?: ComponentFactoryResolver;
injector?: Injector;
}
export interface IonicGlobal {
config: any;