MOBILE-3565 core: Fix some ESLint of CoreAppProvider

main
Dani Palou 2020-10-14 08:29:01 +02:00
parent 02a67d88d2
commit 7a1342885b
1 changed files with 71 additions and 79 deletions

View File

@ -17,12 +17,16 @@ import { Connection } from '@ionic-native/network/ngx';
import { CoreDB } from '@services/db'; import { CoreDB } from '@services/db';
import { CoreEvents, CoreEventsProvider } from '@services/events'; import { CoreEvents, CoreEventsProvider } from '@services/events';
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb';
import CoreConfigConstants from '@app/config.json'; import CoreConfigConstants from '@app/config.json';
import { makeSingleton, Keyboard, Network, StatusBar, Platform } from '@singletons/core.singletons'; import { makeSingleton, Keyboard, Network, StatusBar, Platform } from '@singletons/core.singletons';
import { CoreLogger } from '@singletons/logger'; import { CoreLogger } from '@singletons/logger';
const DBNAME = 'MoodleMobile';
const SCHEMA_VERSIONS_TABLE = 'schema_versions';
/** /**
* Factory to provide some global functionalities, like access to the global app database. * Factory to provide some global functionalities, like access to the global app database.
* *
@ -38,23 +42,22 @@ import { CoreLogger } from '@singletons/logger';
*/ */
@Injectable() @Injectable()
export class CoreAppProvider { export class CoreAppProvider {
protected DBNAME = 'MoodleMobile';
protected db: SQLiteDB; protected db: SQLiteDB;
protected logger: CoreLogger; protected logger: CoreLogger;
protected ssoAuthenticationPromise: Promise<any>; protected ssoAuthenticationDeferred: PromiseDefer<void>;
protected isKeyboardShown = false; protected isKeyboardShown = false;
protected _isKeyboardOpening = false; protected keyboardOpening = false;
protected _isKeyboardClosing = false; protected keyboardClosing = false;
protected backActions = []; protected backActions: {callback: () => boolean; priority: number}[] = [];
protected mainMenuId = 0; protected mainMenuId = 0;
protected mainMenuOpen: number; protected mainMenuOpen: number;
protected forceOffline = false; protected forceOffline = false;
// Variables for DB. // Variables for DB.
protected createVersionsTableReady: Promise<any>; protected createVersionsTableReady: Promise<void>;
protected SCHEMA_VERSIONS_TABLE = 'schema_versions';
protected versionsTableSchema: SQLiteDBTableSchema = { protected versionsTableSchema: SQLiteDBTableSchema = {
name: this.SCHEMA_VERSIONS_TABLE, name: SCHEMA_VERSIONS_TABLE,
columns: [ columns: [
{ {
name: 'name', name: 'name',
@ -68,11 +71,9 @@ export class CoreAppProvider {
], ],
}; };
constructor(appRef: ApplicationRef, constructor(appRef: ApplicationRef, zone: NgZone) {
zone: NgZone) {
this.logger = CoreLogger.getInstance('CoreAppProvider'); this.logger = CoreLogger.getInstance('CoreAppProvider');
this.db = CoreDB.instance.getDB(this.DBNAME); this.db = CoreDB.instance.getDB(DBNAME);
// Create the schema versions table. // Create the schema versions table.
this.createVersionsTableReady = this.db.createTableFromSchema(this.versionsTableSchema); this.createVersionsTableReady = this.db.createTableFromSchema(this.versionsTableSchema);
@ -87,7 +88,7 @@ export class CoreAppProvider {
CoreEvents.instance.trigger(CoreEventsProvider.KEYBOARD_CHANGE, data.keyboardHeight); CoreEvents.instance.trigger(CoreEventsProvider.KEYBOARD_CHANGE, data.keyboardHeight);
}); });
}); });
Keyboard.instance.onKeyboardHide().subscribe((data) => { Keyboard.instance.onKeyboardHide().subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working. // Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => { zone.run(() => {
document.body.classList.remove('keyboard-is-open'); document.body.classList.remove('keyboard-is-open');
@ -95,18 +96,18 @@ export class CoreAppProvider {
CoreEvents.instance.trigger(CoreEventsProvider.KEYBOARD_CHANGE, 0); CoreEvents.instance.trigger(CoreEventsProvider.KEYBOARD_CHANGE, 0);
}); });
}); });
Keyboard.instance.onKeyboardWillShow().subscribe((data) => { Keyboard.instance.onKeyboardWillShow().subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working. // Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => { zone.run(() => {
this._isKeyboardOpening = true; this.keyboardOpening = true;
this._isKeyboardClosing = false; this.keyboardClosing = false;
}); });
}); });
Keyboard.instance.onKeyboardWillHide().subscribe((data) => { Keyboard.instance.onKeyboardWillHide().subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working. // Execute the callback in the Angular zone, so change detection doesn't stop working.
zone.run(() => { zone.run(() => {
this._isKeyboardOpening = false; this.keyboardOpening = false;
this._isKeyboardClosing = true; this.keyboardClosing = true;
}); });
}); });
@ -116,8 +117,8 @@ export class CoreAppProvider {
// Export the app provider and appRef to control the application in Behat tests. // Export the app provider and appRef to control the application in Behat tests.
if (CoreAppProvider.isAutomated()) { if (CoreAppProvider.isAutomated()) {
(<any> window).appProvider = this; (<WindowForAutomatedTests> window).appProvider = this;
(<any> window).appRef = appRef; (<WindowForAutomatedTests> window).appRef = appRef;
} }
} }
@ -145,7 +146,7 @@ export class CoreAppProvider {
* @return Whether the function is supported. * @return Whether the function is supported.
*/ */
canRecordMedia(): boolean { canRecordMedia(): boolean {
return !!(<any> window).MediaRecorder; return !!window.MediaRecorder;
} }
/** /**
@ -163,7 +164,7 @@ export class CoreAppProvider {
* @param schema The schema to create. * @param schema The schema to create.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async createTablesFromSchema(schema: CoreAppSchema): Promise<any> { async createTablesFromSchema(schema: CoreAppSchema): Promise<void> {
this.logger.debug(`Apply schema to app DB: ${schema.name}`); this.logger.debug(`Apply schema to app DB: ${schema.name}`);
let oldVersion; let oldVersion;
@ -173,7 +174,7 @@ export class CoreAppProvider {
await this.createVersionsTableReady; await this.createVersionsTableReady;
// Fetch installed version of the schema. // Fetch installed version of the schema.
const entry = await this.db.getRecord(this.SCHEMA_VERSIONS_TABLE, {name: schema.name}); const entry = await this.db.getRecord(SCHEMA_VERSIONS_TABLE, { name: schema.name });
oldVersion = entry.version; oldVersion = entry.version;
} catch (error) { } catch (error) {
// No installed version yet. // No installed version yet.
@ -195,7 +196,7 @@ export class CoreAppProvider {
} }
// Set installed version. // Set installed version.
await this.db.insertRecord(this.SCHEMA_VERSIONS_TABLE, {name: schema.name, version: schema.version}); await this.db.insertRecord(SCHEMA_VERSIONS_TABLE, { name: schema.name, version: schema.version });
} }
/** /**
@ -260,9 +261,7 @@ export class CoreAppProvider {
* @return Whether the app is running in a 64 bits desktop environment (not browser). * @return Whether the app is running in a 64 bits desktop environment (not browser).
*/ */
is64Bits(): boolean { is64Bits(): boolean {
const process = (<any> window).process; return this.isDesktop() && window.process.arch == 'x64';
return this.isDesktop() && process.arch == 'x64';
} }
/** /**
@ -280,9 +279,8 @@ export class CoreAppProvider {
* @return Whether the app is running in a desktop environment (not browser). * @return Whether the app is running in a desktop environment (not browser).
*/ */
isDesktop(): boolean { isDesktop(): boolean {
const process = (<any> window).process; // @todo
return false;
return !!(process && process.versions && typeof process.versions.electron != 'undefined');
} }
/** /**
@ -300,7 +298,7 @@ export class CoreAppProvider {
* @return Whether keyboard is closing (animating). * @return Whether keyboard is closing (animating).
*/ */
isKeyboardClosing(): boolean { isKeyboardClosing(): boolean {
return this._isKeyboardClosing; return this.keyboardClosing;
} }
/** /**
@ -309,7 +307,7 @@ export class CoreAppProvider {
* @return Whether keyboard is opening (animating). * @return Whether keyboard is opening (animating).
*/ */
isKeyboardOpening(): boolean { isKeyboardOpening(): boolean {
return this._isKeyboardOpening; return this.keyboardOpening;
} }
/** /**
@ -462,8 +460,8 @@ export class CoreAppProvider {
*/ */
protected setKeyboardShown(shown: boolean): void { protected setKeyboardShown(shown: boolean): void {
this.isKeyboardShown = shown; this.isKeyboardShown = shown;
this._isKeyboardOpening = false; this.keyboardOpening = false;
this._isKeyboardClosing = false; this.keyboardClosing = false;
} }
/** /**
@ -487,23 +485,15 @@ export class CoreAppProvider {
* NOT when the browser is opened. * NOT when the browser is opened.
*/ */
startSSOAuthentication(): void { startSSOAuthentication(): void {
let cancelTimeout; this.ssoAuthenticationDeferred = CoreUtils.instance.promiseDefer<void>();
let resolvePromise;
this.ssoAuthenticationPromise = new Promise((resolve, reject): void => {
resolvePromise = resolve;
// Resolve it automatically after 10 seconds (it should never take that long). // Resolve it automatically after 10 seconds (it should never take that long).
cancelTimeout = setTimeout(() => { const cancelTimeout = setTimeout(() => {
this.finishSSOAuthentication(); this.finishSSOAuthentication();
}, 10000); }, 10000);
});
// Store the resolve function in the promise itself.
(<any> this.ssoAuthenticationPromise).resolve = resolvePromise;
// If the promise is resolved because finishSSOAuthentication is called, stop the cancel promise. // If the promise is resolved because finishSSOAuthentication is called, stop the cancel promise.
this.ssoAuthenticationPromise.then(() => { this.ssoAuthenticationDeferred.promise.then(() => {
clearTimeout(cancelTimeout); clearTimeout(cancelTimeout);
}); });
} }
@ -512,9 +502,9 @@ export class CoreAppProvider {
* Finish an SSO authentication process. * Finish an SSO authentication process.
*/ */
finishSSOAuthentication(): void { finishSSOAuthentication(): void {
if (this.ssoAuthenticationPromise) { if (this.ssoAuthenticationDeferred) {
(<any> this.ssoAuthenticationPromise).resolve && (<any> this.ssoAuthenticationPromise).resolve(); this.ssoAuthenticationDeferred.resolve();
this.ssoAuthenticationPromise = undefined; this.ssoAuthenticationDeferred = undefined;
} }
} }
@ -524,7 +514,7 @@ export class CoreAppProvider {
* @return Whether there's a SSO authentication ongoing. * @return Whether there's a SSO authentication ongoing.
*/ */
isSSOAuthenticationOngoing(): boolean { isSSOAuthenticationOngoing(): boolean {
return !!this.ssoAuthenticationPromise; return !!this.ssoAuthenticationDeferred;
} }
/** /**
@ -532,8 +522,8 @@ export class CoreAppProvider {
* *
* @return Promise resolved once SSO authentication finishes. * @return Promise resolved once SSO authentication finishes.
*/ */
waitForSSOAuthentication(): Promise<any> { async waitForSSOAuthentication(): Promise<void> {
return this.ssoAuthenticationPromise || Promise.resolve(); await this.ssoAuthenticationDeferred && this.ssoAuthenticationDeferred.promise;
} }
/** /**
@ -542,27 +532,24 @@ export class CoreAppProvider {
* @param timeout Maximum time to wait, use null to wait forever. * @param timeout Maximum time to wait, use null to wait forever.
*/ */
async waitForResume(timeout: number | null = null): Promise<void> { async waitForResume(timeout: number | null = null): Promise<void> {
let resolve: (value?: any) => void; let deferred = CoreUtils.instance.promiseDefer<void>();
let resumeSubscription: any;
let timeoutId: NodeJS.Timer | false;
const promise = new Promise((r): any => resolve = r); const stopWaiting = () => {
const stopWaiting = (): any => { if (!deferred) {
if (!resolve) {
return; return;
} }
resolve(); deferred.resolve();
resumeSubscription.unsubscribe(); resumeSubscription.unsubscribe();
timeoutId && clearTimeout(timeoutId); timeoutId && clearTimeout(timeoutId);
resolve = null; deferred = null;
}; };
resumeSubscription = Platform.instance.resume.subscribe(stopWaiting); const resumeSubscription = Platform.instance.resume.subscribe(stopWaiting);
timeoutId = timeout ? setTimeout(stopWaiting, timeout) : false; const timeoutId = timeout ? setTimeout(stopWaiting, timeout) : false;
await promise; await deferred.promise;
} }
/** /**
@ -626,23 +613,19 @@ export class CoreAppProvider {
* button is pressed. This method decides which of the registered back button * button is pressed. This method decides which of the registered back button
* actions has the highest priority and should be called. * actions has the highest priority and should be called.
* *
* @param fn Called when the back button is pressed, * @param callback Called when the back button is pressed, if this registered action has the highest priority.
* if this registered action has the highest priority.
* @param priority Set the priority for this action. All actions sorted by priority will be executed since one of * @param priority Set the priority for this action. All actions sorted by priority will be executed since one of
* them returns true. * them returns true.
* * Priorities higher or equal than 1000 will go before closing modals * - Priorities higher or equal than 1000 will go before closing modals
* * Priorities lower than 500 will only be executed if you are in the first state of the app (before exit). * - Priorities lower than 500 will only be executed if you are in the first state of the app (before exit).
* @return A function that, when called, will unregister * @return A function that, when called, will unregister the back button action.
* the back button action.
*/ */
registerBackButtonAction(fn: any, priority: number = 0): any { registerBackButtonAction(callback: () => boolean, priority: number = 0): () => boolean {
const action = { fn, priority }; const action = { callback, priority };
this.backActions.push(action); this.backActions.push(action);
this.backActions.sort((a, b) => { this.backActions.sort((a, b) => b.priority - a.priority);
return b.priority - a.priority;
});
return (): boolean => { return (): boolean => {
const index = this.backActions.indexOf(action); const index = this.backActions.indexOf(action);
@ -700,6 +683,7 @@ export class CoreAppProvider {
setForceOffline(value: boolean): void { setForceOffline(value: boolean): void {
this.forceOffline = !!value; this.forceOffline = !!value;
} }
} }
export class CoreApp extends makeSingleton(CoreAppProvider) {} export class CoreApp extends makeSingleton(CoreAppProvider) {}
@ -802,5 +786,13 @@ export type CoreAppSchema = {
* @param oldVersion Old version of the schema or 0 if not installed. * @param oldVersion Old version of the schema or 0 if not installed.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
migrate?(db: SQLiteDB, oldVersion: number): Promise<any>; migrate?(db: SQLiteDB, oldVersion: number): Promise<void>;
};
/**
* Extended window type for automated tests.
*/
export type WindowForAutomatedTests = Window & {
appProvider?: CoreAppProvider;
appRef?: ApplicationRef;
}; };