mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
Merge branch 'master' into v4
This commit is contained in:
@ -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.
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {}
|
|
9
src/components/app/test/typography/app/app.component.ts
Normal file
9
src/components/app/test/typography/app/app.component.ts
Normal 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;
|
||||||
|
}
|
21
src/components/app/test/typography/app/app.module.ts
Normal file
21
src/components/app/test/typography/app/app.module.ts
Normal 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 {}
|
@ -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>
|
@ -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 {}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { IonicPage } from '../../../../../..';
|
||||||
|
|
||||||
|
@IonicPage({
|
||||||
|
name: 'page-one'
|
||||||
|
})
|
||||||
|
@Component({
|
||||||
|
templateUrl: 'page-one.html'
|
||||||
|
})
|
||||||
|
export class PageOne { }
|
@ -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());
|
||||||
|
@ -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.
|
||||||
|
@ -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(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user