Merge branch 'master' into v4

This commit is contained in:
Adam Bradley
2017-05-01 10:17:51 -05:00
15 changed files with 226 additions and 65 deletions

View File

@ -4,7 +4,7 @@ import { Title, DOCUMENT } from '@angular/platform-browser';
import { IonicApp } from './app-root'; import { IonicApp } from './app-root';
import * as Constants from './app-constants'; import * as Constants from './app-constants';
import { ClickBlock } from './click-block'; import { ClickBlock } from './click-block';
import { runInDev } from '../../util/util'; import { runInDev, assert } from '../../util/util';
import { Config } from '../../config/config'; import { Config } from '../../config/config';
import { isNav, NavOptions, DIRECTION_FORWARD, DIRECTION_BACK } from '../../navigation/nav-util'; import { isNav, NavOptions, DIRECTION_FORWARD, DIRECTION_BACK } from '../../navigation/nav-util';
import { MenuController } from './menu-controller'; import { MenuController } from './menu-controller';
@ -226,6 +226,8 @@ export class App {
* @hidden * @hidden
*/ */
present(enteringView: ViewController, opts: NavOptions, appPortal?: number): Promise<any> { present(enteringView: ViewController, opts: NavOptions, appPortal?: number): Promise<any> {
assert(enteringView.isOverlay, 'presented view controller needs to be an overlay');
const portal = this._appRoot._getPortal(appPortal); const portal = this._appRoot._getPortal(appPortal);
// Set Nav must be set here in order to dimiss() work synchnously. // Set Nav must be set here in order to dimiss() work synchnously.

View File

@ -9,6 +9,7 @@ import { Keyboard } from '../../platform/keyboard';
import { NavControllerBase } from '../../navigation/nav-controller-base'; import { NavControllerBase } from '../../navigation/nav-controller-base';
import { Platform } from '../../platform/platform'; import { Platform } from '../../platform/platform';
import { TransitionController } from '../../transitions/transition-controller'; import { TransitionController } from '../../transitions/transition-controller';
import { ViewController } from '../../navigation/view-controller';
/** /**
* @hidden * @hidden
@ -40,8 +41,10 @@ export class OverlayPortal extends NavControllerBase {
// on every page change make sure the portal has // on every page change make sure the portal has
// dismissed any views that should be auto dismissed on page change // dismissed any views that should be auto dismissed on page change
app.viewDidLeave.subscribe((ev: any) => { app.viewDidLeave.subscribe((view: ViewController) => {
!ev.isOverlay && this.dismissPageChangeViews(); if (!view.isOverlay) {
this.dismissPageChangeViews();
}
}); });
} }

View File

@ -1,25 +0,0 @@
import { Component, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IonicApp, IonicModule, App } from '../../../..';
@Component({
templateUrl: 'main.html'
})
export class AppComponent {
constructor(app: App) {
app.setTitle('Basic Buttons');
}
}
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
IonicModule.forRoot(AppComponent)
],
bootstrap: [IonicApp]
})
export class AppModule {}

View File

@ -0,0 +1,9 @@
import { Component } from '@angular/core';
import { PageOne } from '../pages/page-one/page-one';
@Component({
template: '<ion-nav [root]="rootPage"></ion-nav>'
})
export class AppComponent {
rootPage = PageOne;
}

View File

@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IonicApp, IonicModule } from '../../../../..';
import { AppComponent } from './app.component';
import { PageOneModule } from '../pages/page-one/page-one.module';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
IonicModule.forRoot(AppComponent, {}),
PageOneModule
],
bootstrap: [IonicApp],
entryComponents: [
]
})
export class AppModule {}

View File

@ -11,11 +11,11 @@
<h1>H1: The quick brown fox jumps over the lazy dog</h1> <h1>H1: The quick brown fox jumps over the lazy dog</h1>
<h2 primary>H2: The quick brown fox jumps over the lazy dog</h2> <h2 ion-text color="primary">H2: The quick brown fox jumps over the lazy dog</h2>
<h3>H3: The quick brown fox jumps over the lazy dog</h3> <h3>H3: The quick brown fox jumps over the lazy dog</h3>
<h4 danger>H4: The quick brown fox jumps over the lazy dog</h4> <h4 ion-text color="danger">H4: The quick brown fox jumps over the lazy dog</h4>
<h5>H5: The quick brown fox jumps over the lazy dog</h5> <h5>H5: The quick brown fox jumps over the lazy dog</h5>
@ -23,9 +23,9 @@
<p> <p>
I saw a werewolf with a Chinese menu in his hand. I saw a werewolf with a Chinese menu in his hand.
Walking through the <sub danger>streets</sub> of Soho in the rain. Walking through the <sub ion-text color="danger">streets</sub> of Soho in the rain.
He <i primary>was</i> looking for a place called Lee Ho Fook's. He <i ion-text color="primary">was</i> looking for a place called Lee Ho Fook's.
Gonna get a <a secondary>big dish of beef chow mein.</a> Gonna get a <a ion-text color="secondary">big dish of beef chow mein.</a>
</p> </p>
<p> <p>
@ -34,7 +34,7 @@
Better stay away from him. Better stay away from him.
He'll rip your lungs out, Jim. He'll rip your lungs out, Jim.
I'd like to meet his tailor. I'd like to meet his tailor.
<ion-icon danger name="cut"></ion-icon> <ion-icon ion-text color="danger" name="cut"></ion-icon>
</p> </p>
</ion-content> </ion-content>

View File

@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { IonicPageModule } from '../../../../../..';
import { PageOne } from './page-one';
@NgModule({
declarations: [
PageOne,
],
imports: [
IonicPageModule.forChild(PageOne),
],
entryComponents: [
PageOne,
]
})
export class PageOneModule {}

View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
import { IonicPage } from '../../../../../..';
@IonicPage({
name: 'page-one'
})
@Component({
templateUrl: 'page-one.html'
})
export class PageOne { }

View File

@ -134,7 +134,8 @@ export class ItemReorderGesture {
} }
private itemForCoord(coord: PointerCoordinates): HTMLElement { private itemForCoord(coord: PointerCoordinates): HTMLElement {
const x = this.offset.x - 100; const sideOffset = this.plt.isRTL ? 100 : -100;
const x = this.offset.x + sideOffset;
const y = coord.y; const y = coord.y;
const element = this.plt.getElementFromPoint(x, y); const element = this.plt.getElementFromPoint(x, y);
return findReorderItem(element, this.reorderList.getNativeElement()); return findReorderItem(element, this.reorderList.getNativeElement());

View File

@ -151,6 +151,7 @@ export class Select extends BaseInput<any> implements OnDestroy {
_multi: boolean = false; _multi: boolean = false;
_options: QueryList<Option>; _options: QueryList<Option>;
_overlay: ActionSheet | Alert | Popover;
_texts: string[] = []; _texts: string[] = [];
_text: string = ''; _text: string = '';
@ -364,6 +365,7 @@ export class Select extends BaseInput<any> implements OnDestroy {
overlay.present(selectOptions); overlay.present(selectOptions);
this._fireFocus(); this._fireFocus();
overlay.onDidDismiss((value: any) => { overlay.onDidDismiss((value: any) => {
this._fireBlur(); this._fireBlur();
@ -371,9 +373,23 @@ export class Select extends BaseInput<any> implements OnDestroy {
this.value = value; this.value = value;
this.ionChange.emit(value); this.ionChange.emit(value);
} }
this._overlay = undefined;
}); });
this._overlay = overlay;
} }
/**
* Close the select interface.
*/
close() {
if (!this._overlay || !this.isFocus()) {
return;
}
return this._overlay.dismiss();
}
/** /**
* @input {boolean} If true, the element can accept multiple values. * @input {boolean} If true, the element can accept multiple values.

View File

@ -1117,7 +1117,7 @@ export class NavControllerBase extends Ion implements NavController {
dismissPageChangeViews() { dismissPageChangeViews() {
for (let view of this._views) { for (let view of this._views) {
if (view.data && view.data.dismissOnPageChange) { if (view.data && view.data.dismissOnPageChange) {
view.dismiss().catch(null); view.dismiss().catch(() => {});
} }
} }
} }

View File

@ -2,30 +2,30 @@ import { NavOptions } from './nav-util';
export interface Nav { export interface Nav {
goToRoot(opts: NavOptions): Promise<any>; goToRoot(opts: NavOptions): Promise<any>;
}; }
export interface Tabs { export interface Tabs {
_tabs: Tab[]; _tabs: Tab[];
select(tabOrIndex: number | Tab, opts: NavOptions): void; select(tabOrIndex: number | Tab, opts: NavOptions): void;
_top: number; _top: number;
setTabbarPosition(top: number, bottom: number): void; setTabbarPosition(top: number, bottom: number): void;
}; }
export interface Tab { export interface Tab {
tabUrlPath: string; tabUrlPath: string;
tabTitle: string; tabTitle: string;
index: number; index: number;
}; }
export interface Content { export interface Content {
resize(): void; resize(): void;
}; }
export interface Footer { export interface Footer {
}; }
export interface Header { export interface Header {
}; }
export interface Navbar { export interface Navbar {
setBackButtonText(backButtonText: string): void; setBackButtonText(backButtonText: string): void;

View File

@ -74,29 +74,27 @@ export interface LoadedModule {
/** /**
* @hidden * @hidden
*/ */
export function setupPreloadingImplementation(config: Config, deepLinkConfig: DeepLinkConfig, moduleLoader: ModuleLoader) { export function setupPreloadingImplementation(config: Config, deepLinkConfig: DeepLinkConfig, moduleLoader: ModuleLoader): Promise<any> {
if (config.getBoolean('preloadModules')) { if (!deepLinkConfig || !deepLinkConfig.links || !config.getBoolean('preloadModules')) {
const linksToLoad = deepLinkConfig.links.filter(link => !!link.loadChildren && link.priority !== 'off'); return Promise.resolve();
}
const linksToLoad = deepLinkConfig.links.filter(link => !!link.loadChildren && link.priority !== 'off');
// Load the high priority modules first // Load the high priority modules first
const highPriorityPromises = linksToLoad.map(link => { const highPriorityPromises = linksToLoad
if (link.priority === 'high') { .filter(link => link.priority === 'high')
return moduleLoader.load(link.loadChildren); .map(link => moduleLoader.load(link.loadChildren));
}
});
Promise.all(highPriorityPromises).then(() => { return Promise.all(highPriorityPromises).then(() => {
// Load the low priority modules after the high priority are done // Load the low priority modules after the high priority are done
const lowPriorityPromises = linksToLoad.map(link => { const lowPriorityPromises = linksToLoad
if (link.priority === 'low') { .filter(link => link.priority === 'low')
return moduleLoader.load(link.loadChildren); .map(link => moduleLoader.load(link.loadChildren));
}
}); return Promise.all(lowPriorityPromises);
return Promise.all(lowPriorityPromises); }).catch(err => {
}).catch(err => { console.error(err.message);
console.error(err.message); });
});
}
} }
/** /**

View File

@ -1,6 +1,8 @@
import { ModuleLoader, LAZY_LOADED_TOKEN } from '../module-loader'; import { ModuleLoader, LAZY_LOADED_TOKEN, setupPreloadingImplementation } from '../module-loader';
import { mockModuleLoader, mockNgModuleLoader } from '../mock-providers'; import { mockModuleLoader, mockNgModuleLoader, mockConfig } from '../mock-providers';
import { NgModuleLoader } from '../ng-module-loader'; import { NgModuleLoader } from '../ng-module-loader';
import { Config } from '../../config/config';
import { DeepLinkConfig } from '../../navigation/nav-util';
describe('module-loader', () => { describe('module-loader', () => {
@ -115,12 +117,119 @@ describe('module-loader', () => {
}); });
describe('setupPreloadingImplementation', () => {
it('should return a promise', (done: Function) => {
let promise = setupPreloadingImplementation(config, null, moduleLoader);
promise.then((response) => {
done();
}).catch((err: Error) => {
fail(err);
done(err);
});
});
it('should not call ModuleLoader when preloading disabled', (done: Function) => {
spyOn(moduleLoader, 'load').and.returnValue(Promise.resolve());
config.set('preloadModules', false);
const deepLinkConfig: DeepLinkConfig = {
links: []
};
let promise = setupPreloadingImplementation(config, deepLinkConfig, moduleLoader);
promise.then((response) => {
expect(moduleLoader.load).not.toHaveBeenCalled();
done();
}).catch((err: Error) => {
fail(err);
done(err);
});
});
it('should not call ModuleLoader when deepLinkConfig missing', (done: Function) => {
spyOn(moduleLoader, 'load').and.returnValue(Promise.resolve());
config.set('preloadModules', true);
let promise = setupPreloadingImplementation(config, null, moduleLoader);
promise.then((response) => {
expect(moduleLoader.load).not.toHaveBeenCalled();
done();
}).catch((err: Error) => {
fail(err);
done(err);
});
});
it('should not call ModuleLoader when no low or high priority links', (done: Function) => {
spyOn(moduleLoader, 'load').and.returnValue(Promise.resolve());
config.set('preloadModules', true);
const deepLinkConfig: DeepLinkConfig = {
links: [{
loadChildren: 'offString',
priority: 'off'
}]
};
let promise = setupPreloadingImplementation(config, deepLinkConfig, moduleLoader);
promise.then((response) => {
expect(moduleLoader.load).not.toHaveBeenCalled();
done();
}).catch((err: Error) => {
fail(err);
done(err);
});
});
it('should call ModuleLoader when has low priority links', (done: Function) => {
spyOn(moduleLoader, 'load').and.returnValue(Promise.resolve());
config.set('preloadModules', true);
const deepLinkConfig: DeepLinkConfig = {
links: [{
loadChildren: 'lowString',
priority: 'low'
}]
};
let promise = setupPreloadingImplementation(config, deepLinkConfig, moduleLoader);
promise.then((response) => {
expect(moduleLoader.load).toHaveBeenCalledWith('lowString');
done();
}).catch((err: Error) => {
fail(err);
done(err);
});
});
it('should call ModuleLoader when has high priority links', (done: Function) => {
spyOn(moduleLoader, 'load').and.returnValue(Promise.resolve());
config.set('preloadModules', true);
const deepLinkConfig: DeepLinkConfig = {
links: [{
loadChildren: 'highString',
priority: 'high'
}]
};
let promise = setupPreloadingImplementation(config, deepLinkConfig, moduleLoader);
promise.then((response) => {
expect(moduleLoader.load).toHaveBeenCalledWith('highString');
done();
}).catch((err: Error) => {
fail(err);
done(err);
});
});
});
var moduleLoader: ModuleLoader; var moduleLoader: ModuleLoader;
var ngModuleLoader: NgModuleLoader; var ngModuleLoader: NgModuleLoader;
var config: Config;
beforeEach(() => { beforeEach(() => {
ngModuleLoader = mockNgModuleLoader(); ngModuleLoader = mockNgModuleLoader();
moduleLoader = mockModuleLoader(ngModuleLoader); moduleLoader = mockModuleLoader(ngModuleLoader);
config = mockConfig();
}); });
}); });