MOBILE-2261 init: Implement init delegate
parent
a4eb66062a
commit
8196c79954
|
@ -1,6 +1,6 @@
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { ErrorHandler, NgModule } from '@angular/core';
|
import { ErrorHandler, NgModule } from '@angular/core';
|
||||||
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
|
import { IonicApp, IonicErrorHandler, IonicModule, Platform } from 'ionic-angular';
|
||||||
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
import { HttpClient, HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
import { SplashScreen } from '@ionic-native/splash-screen';
|
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||||
|
@ -23,6 +23,7 @@ import { CoreTimeUtilsProvider } from '../providers/utils/time';
|
||||||
import { CoreUrlUtilsProvider } from '../providers/utils/url';
|
import { CoreUrlUtilsProvider } from '../providers/utils/url';
|
||||||
import { CoreUtilsProvider } from '../providers/utils/utils';
|
import { CoreUtilsProvider } from '../providers/utils/utils';
|
||||||
import { CoreMimetypeUtilsProvider } from '../providers/utils/mimetype';
|
import { CoreMimetypeUtilsProvider } from '../providers/utils/mimetype';
|
||||||
|
import { CoreInitDelegate } from '../providers/init';
|
||||||
|
|
||||||
// For translate loader. AoT requires an exported function for factories.
|
// For translate loader. AoT requires an exported function for factories.
|
||||||
export function createTranslateLoader(http: HttpClient) {
|
export function createTranslateLoader(http: HttpClient) {
|
||||||
|
@ -66,7 +67,22 @@ export function createTranslateLoader(http: HttpClient) {
|
||||||
CoreTimeUtilsProvider,
|
CoreTimeUtilsProvider,
|
||||||
CoreUrlUtilsProvider,
|
CoreUrlUtilsProvider,
|
||||||
CoreUtilsProvider,
|
CoreUtilsProvider,
|
||||||
CoreMimetypeUtilsProvider
|
CoreMimetypeUtilsProvider,
|
||||||
|
CoreInitDelegate
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {
|
||||||
|
constructor(platform: Platform, initDelegate: CoreInitDelegate) {
|
||||||
|
// Create a handler for platform ready and register it in the init delegate.
|
||||||
|
let handler = {
|
||||||
|
name: 'CorePlatformReady',
|
||||||
|
priority: initDelegate.MAX_RECOMMENDED_PRIORITY + 400,
|
||||||
|
blocking: true,
|
||||||
|
load: platform.ready
|
||||||
|
};
|
||||||
|
initDelegate.registerProcess(handler);
|
||||||
|
|
||||||
|
// Execute the init processes.
|
||||||
|
initDelegate.executeInitProcesses();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -91,22 +91,6 @@ export class CoreAppProvider {
|
||||||
return this.db;
|
return this.db;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Core init process for the app.
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* This should be the first init process of all, no other process should run until we are certain that the cordova plugins
|
|
||||||
* are loaded, which is what platform.ready tells us.
|
|
||||||
*
|
|
||||||
* Reserved for core use, do not call directly.
|
|
||||||
*
|
|
||||||
* @protected
|
|
||||||
* @return Promise resolved when ready.
|
|
||||||
*/
|
|
||||||
initProcess() : Promise<any> {
|
|
||||||
return this.platform.ready();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the app is running in a desktop environment (not browser).
|
* Checks if the app is running in a desktop environment (not browser).
|
||||||
*
|
*
|
||||||
|
@ -165,19 +149,6 @@ export class CoreAppProvider {
|
||||||
return limited.indexOf(type) > -1;
|
return limited.indexOf(type) > -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantly returns if the app is ready.
|
|
||||||
*
|
|
||||||
* To be notified when the app is ready, refer to {@link $mmApp#ready}.
|
|
||||||
*
|
|
||||||
* @return {Boolean} True when it is, false when not.
|
|
||||||
* @todo
|
|
||||||
*/
|
|
||||||
isReady() {
|
|
||||||
// var promise = $injector.get('$mmInitDelegate').ready();
|
|
||||||
// return promise.$$state.status === 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the keyboard.
|
* Open the keyboard.
|
||||||
*/
|
*/
|
||||||
|
@ -188,23 +159,6 @@ export class CoreAppProvider {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves when the app is ready.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
*
|
|
||||||
* $mmApp.ready().then(function() {
|
|
||||||
* // What you want to do.
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* @return {Promise} Resolved when the app is initialised. Never rejected.
|
|
||||||
* @todo
|
|
||||||
*/
|
|
||||||
ready() {
|
|
||||||
// Injects to prevent circular dependencies.
|
|
||||||
// return $injector.get('$mmInitDelegate').ready();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an SSO authentication process.
|
* Start an SSO authentication process.
|
||||||
* Please notice that this function should be called when the app receives the new token from the browser,
|
* Please notice that this function should be called when the app receives the new token from the browser,
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
// (C) Copyright 2015 Martin Dougiamas
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Platform } from 'ionic-angular';
|
||||||
|
import { CoreLoggerProvider } from './logger';
|
||||||
|
import { CoreUtilsProvider } from './utils/utils';
|
||||||
|
|
||||||
|
export interface CoreInitHandler {
|
||||||
|
name: string; // Name of the handler.
|
||||||
|
load(): Promise<any>; // Function to execute during the init process.
|
||||||
|
priority?: number; // The highest priority is executed first. You should use values lower than MAX_RECOMMENDED_PRIORITY.
|
||||||
|
blocking?: boolean; // Set this to true when this process should be resolved before any following one.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Provider for initialisation mechanisms.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class CoreInitDelegate {
|
||||||
|
DEFAULT_PRIORITY = 100; // Default priority for init processes.
|
||||||
|
MAX_RECOMMENDED_PRIORITY = 600;
|
||||||
|
initProcesses = {};
|
||||||
|
logger;
|
||||||
|
readiness;
|
||||||
|
|
||||||
|
constructor(logger: CoreLoggerProvider, platform: Platform, private utils: CoreUtilsProvider) {
|
||||||
|
this.logger = logger.getInstance('CoreInitDelegate');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the registered init processes.
|
||||||
|
*
|
||||||
|
* Reserved for core use, do not call directly.
|
||||||
|
*/
|
||||||
|
executeInitProcesses() : void {
|
||||||
|
let ordered = [];
|
||||||
|
|
||||||
|
if (typeof this.readiness == 'undefined') {
|
||||||
|
this.initReadiness();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-ordering by priority.
|
||||||
|
for (let name in this.initProcesses) {
|
||||||
|
ordered.push(this.initProcesses[name]);
|
||||||
|
}
|
||||||
|
ordered.sort((a, b) => {
|
||||||
|
return b.priority - a.priority;
|
||||||
|
});
|
||||||
|
|
||||||
|
ordered = ordered.map((data: CoreInitHandler) => {
|
||||||
|
return {
|
||||||
|
context: this,
|
||||||
|
func: this.prepareProcess,
|
||||||
|
params: [data],
|
||||||
|
blocking: !!data.blocking
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Execute all the processes in order to solve dependencies.
|
||||||
|
this.utils.executeOrderedPromises(ordered).finally(this.readiness.resolve);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init the readiness promise.
|
||||||
|
*/
|
||||||
|
protected initReadiness() : void {
|
||||||
|
this.readiness = this.utils.promiseDefer();
|
||||||
|
this.readiness.promise.then(() => this.readiness.resolved = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantly returns if the app is ready.
|
||||||
|
*
|
||||||
|
* To be notified when the app is ready, refer to {@link $mmApp#ready}.
|
||||||
|
*
|
||||||
|
* @return {boolean} Whether it's ready.
|
||||||
|
*/
|
||||||
|
isReady(): boolean {
|
||||||
|
return this.readiness.resolved;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience function to return a function that executes the process.
|
||||||
|
*
|
||||||
|
* @param {CoreInitHandler} data The data of the process.
|
||||||
|
* @return {Promise<any>} Promise of the process.
|
||||||
|
*/
|
||||||
|
protected prepareProcess(data: CoreInitHandler) : Promise<any> {
|
||||||
|
let promise;
|
||||||
|
|
||||||
|
this.logger.debug(`Executing init process '${data.name}'`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
promise = data.load();
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error('Error while calling the init process \'' + data.name + '\'. ' + e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies when the app is ready. This returns a promise that is resolved when the app is initialised.
|
||||||
|
*
|
||||||
|
* @return {Promise<any>} Resolved when the app is initialised. Never rejected.
|
||||||
|
*/
|
||||||
|
ready() : Promise<any> {
|
||||||
|
if (typeof this.readiness === 'undefined') {
|
||||||
|
// Prevent race conditions if this is called before executeInitProcesses.
|
||||||
|
this.initReadiness();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.readiness.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an initialisation process.
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Init processes can be used to add initialisation logic to the app. Anything that should block the user interface while
|
||||||
|
* some processes are done should be an init process. It is recommended to use a priority lower than MAX_RECOMMENDED_PRIORITY
|
||||||
|
* to make sure that your process does not happen before some essential other core processes.
|
||||||
|
*
|
||||||
|
* An init process should never change state or prompt user interaction.
|
||||||
|
*
|
||||||
|
* This delegate cannot be used in remote addons.
|
||||||
|
*
|
||||||
|
* @param {CoreInitHandler} instance The instance of the handler.
|
||||||
|
*/
|
||||||
|
registerProcess(handler: CoreInitHandler) : void {
|
||||||
|
if (typeof handler.priority == 'undefined') {
|
||||||
|
handler.priority = this.DEFAULT_PRIORITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.initProcesses[handler.name] != 'undefined') {
|
||||||
|
this.logger.log(`Process '${handler.name}' already registered.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(`Registering process '${handler.name}'.`);
|
||||||
|
this.initProcesses[handler.name] = handler;
|
||||||
|
}
|
||||||
|
}
|
|
@ -916,6 +916,20 @@ export class CoreUtilsProvider {
|
||||||
return mapped;
|
return mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to AngularJS $q.defer(). It will return an object containing the promise, and the resolve and reject functions.
|
||||||
|
*
|
||||||
|
* @return {any} Object containing the promise, and the resolve and reject functions.
|
||||||
|
*/
|
||||||
|
promiseDefer() : any {
|
||||||
|
let deferred: any = {};
|
||||||
|
deferred.promise = new Promise((resolve, reject) => {
|
||||||
|
deferred.resolve = resolve;
|
||||||
|
deferred.reject = reject;
|
||||||
|
});
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a promise, returns true if it's rejected or false if it's resolved.
|
* Given a promise, returns true if it's rejected or false if it's resolved.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue