From 0cc1a2b2ff4114dd067f70372e4411ae39cdbdb6 Mon Sep 17 00:00:00 2001 From: Ibby Hadeed Date: Fri, 29 Dec 2017 10:15:44 -0500 Subject: [PATCH] Use AngularJS promise if available --- src/@ionic-native/core/decorators/common.ts | 17 ++++++- .../plugins/email-composer/index.ts | 4 +- src/@ionic-native/plugins/file/index.ts | 28 ++++++------ .../plugins/google-maps/index.ts | 45 ++++++++++--------- src/@ionic-native/plugins/printer/index.ts | 4 +- src/@ionic-native/plugins/screenshot/index.ts | 6 +-- .../plugins/secure-storage/index.ts | 4 +- src/@ionic-native/plugins/sqlite/index.ts | 5 ++- 8 files changed, 64 insertions(+), 49 deletions(-) diff --git a/src/@ionic-native/core/decorators/common.ts b/src/@ionic-native/core/decorators/common.ts index de095a27f..fb2f42f40 100644 --- a/src/@ionic-native/core/decorators/common.ts +++ b/src/@ionic-native/core/decorators/common.ts @@ -2,13 +2,15 @@ import { CordovaOptions } from './interfaces'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/fromEvent'; +declare const window: any; + export const ERR_CORDOVA_NOT_AVAILABLE = { error: 'cordova_not_available' }; export const ERR_PLUGIN_NOT_INSTALLED = { error: 'plugin_not_installed' }; -export function getPromise(callback: Function) { +export function getPromise(callback: (resolve: Function, reject?: Function) => any): Promise { const tryNativePromise = () => { if (Promise) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { callback(resolve, reject); }); } else { @@ -16,6 +18,17 @@ export function getPromise(callback: Function) { } }; + if (window.angular) { + const injector = window.angular.element(document.querySelector('[ng-app]') || document.body).injector(); + if (injector) { + let $q = injector.get('$q'); + return $q((resolve: Function, reject: Function) => { + callback(resolve, reject); + }); + } + console.warn('Angular 1 was detected but $q couldn\'t be retrieved. This is usually when the app is not bootstrapped on the html or body tag. Falling back to native promises which won\'t trigger an automatic digest when promises resolve.'); + } + return tryNativePromise(); } diff --git a/src/@ionic-native/plugins/email-composer/index.ts b/src/@ionic-native/plugins/email-composer/index.ts index 121ab215c..302e0ce01 100644 --- a/src/@ionic-native/plugins/email-composer/index.ts +++ b/src/@ionic-native/plugins/email-composer/index.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Cordova, CordovaCheck, IonicNativePlugin, Plugin } from '@ionic-native/core'; +import { Cordova, CordovaCheck, IonicNativePlugin, Plugin, getPromise } from '@ionic-native/core'; export interface EmailComposerOptions { @@ -119,7 +119,7 @@ export class EmailComposer extends IonicNativePlugin { */ @CordovaCheck() isAvailable(app?: string): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { if (app) { EmailComposer.getPlugin().isAvailable(app, (isAvailable: boolean) => { if (isAvailable) { diff --git a/src/@ionic-native/plugins/file/index.ts b/src/@ionic-native/plugins/file/index.ts index 77101c0da..e097a01fb 100644 --- a/src/@ionic-native/plugins/file/index.ts +++ b/src/@ionic-native/plugins/file/index.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { CordovaCheck, CordovaProperty, IonicNativePlugin, Plugin } from '@ionic-native/core'; +import { CordovaCheck, CordovaProperty, IonicNativePlugin, Plugin, getPromise } from '@ionic-native/core'; export interface IFile extends Blob { /** @@ -715,7 +715,7 @@ export class File extends IonicNativePlugin { */ @CordovaCheck() getFreeDiskSpace(): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { cordova.exec(resolve, reject, 'File', 'getFreeDiskSpace', []); }); } @@ -1150,7 +1150,7 @@ export class File extends IonicNativePlugin { */ @CordovaCheck() resolveLocalFilesystemUrl(fileUrl: string): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { try { window.resolveLocalFileSystemURL(fileUrl, (entry: Entry) => { resolve(entry); @@ -1193,7 +1193,7 @@ export class File extends IonicNativePlugin { */ @CordovaCheck() getDirectory(directoryEntry: DirectoryEntry, directoryName: string, flags: Flags): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { try { directoryEntry.getDirectory(directoryName, flags, (de) => { resolve(de); @@ -1217,7 +1217,7 @@ export class File extends IonicNativePlugin { */ @CordovaCheck() getFile(directoryEntry: DirectoryEntry, fileName: string, flags: Flags): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { try { directoryEntry.getFile(fileName, flags, resolve, (err) => { this.fillErrorMessage(err); @@ -1267,7 +1267,7 @@ export class File extends IonicNativePlugin { }) .then((fileEntry: FileEntry) => { const reader = new FileReader(); - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { reader.onloadend = () => { if (reader.result !== undefined || reader.result !== null) { resolve(reader.result); @@ -1302,7 +1302,7 @@ export class File extends IonicNativePlugin { * @hidden */ private remove(fe: Entry): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { fe.remove(() => { resolve({ success: true, fileRemoved: fe }); }, (err) => { @@ -1316,7 +1316,7 @@ export class File extends IonicNativePlugin { * @hidden */ private move(srce: Entry, destdir: DirectoryEntry, newName: string): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { srce.moveTo(destdir, newName, (deste) => { resolve(deste); }, (err) => { @@ -1330,7 +1330,7 @@ export class File extends IonicNativePlugin { * @hidden */ private copy(srce: Entry, destdir: DirectoryEntry, newName: string): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { srce.copyTo(destdir, newName, (deste) => { resolve(deste); }, (err) => { @@ -1344,7 +1344,7 @@ export class File extends IonicNativePlugin { * @hidden */ private readEntries(dr: DirectoryReader): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { dr.readEntries((entries) => { resolve(entries); }, (err) => { @@ -1358,7 +1358,7 @@ export class File extends IonicNativePlugin { * @hidden */ private rimraf(de: DirectoryEntry): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { de.removeRecursively(() => { resolve({ success: true, fileRemoved: de }); }, (err) => { @@ -1372,7 +1372,7 @@ export class File extends IonicNativePlugin { * @hidden */ private createWriter(fe: FileEntry): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { fe.createWriter((writer) => { resolve(writer); }, (err) => { @@ -1390,7 +1390,7 @@ export class File extends IonicNativePlugin { return this.writeFileInChunks(writer, gu); } - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { writer.onwriteend = (evt) => { if (writer.error) { reject(writer.error); @@ -1417,7 +1417,7 @@ export class File extends IonicNativePlugin { writer.write(chunk); } - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { writer.onerror = reject; writer.onwrite = () => { if (writtenSize < file.size) { diff --git a/src/@ionic-native/plugins/google-maps/index.ts b/src/@ionic-native/plugins/google-maps/index.ts index 160b049a2..75b8180fa 100644 --- a/src/@ionic-native/plugins/google-maps/index.ts +++ b/src/@ionic-native/plugins/google-maps/index.ts @@ -6,7 +6,8 @@ import { InstanceCheck, InstanceProperty, IonicNativePlugin, - Plugin + Plugin, + getPromise } from '@ionic-native/core'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/fromEvent'; @@ -1013,7 +1014,7 @@ export class BaseClass { */ @InstanceCheck() addListenerOnce(eventName: string): Promise { - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.one(eventName, (...args: any[]) => { if (args[args.length - 1] instanceof GoogleMaps.getPlugin().BaseClass) { if (args[args.length - 1].type === 'Map') { @@ -1110,7 +1111,7 @@ export class BaseClass { */ @InstanceCheck() one(eventName: string): Promise { - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.one(eventName, (...args: any[]) => { if (args[args.length - 1] instanceof GoogleMaps.getPlugin().BaseClass) { if (args[args.length - 1].type === 'Map') { @@ -1210,7 +1211,7 @@ export class BaseArrayClass extends BaseClass { */ @CordovaCheck() forEachAsync(fn: ((element: T, callback: () => void) => void)): Promise { - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.forEach(fn, resolve); }); } @@ -1236,7 +1237,7 @@ export class BaseArrayClass extends BaseClass { */ @CordovaCheck() mapAsync(fn: ((element: T, callback: (newElement: any) => void) => void)): Promise { - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.map(fn, resolve); }); } @@ -1260,7 +1261,7 @@ export class BaseArrayClass extends BaseClass { */ @CordovaCheck() filterAsync(fn: (element: T, callback: (result: boolean) => void) => void): Promise { - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.filter(fn, resolve); }); } @@ -1566,7 +1567,7 @@ export class Environment { * @return {Promise} */ static getLicenseInfo(): Promise { - return new Promise((resolve) => { + return getPromise((resolve) => { GoogleMaps.getPlugin().environment.getLicenseInfo((text: string) => resolve(text)); }); } @@ -1626,7 +1627,7 @@ export class Geocoder { // ] // }) // ------------------------- - return new Promise>((resolve, reject) => { + return getPromise>((resolve, reject) => { GoogleMaps.getPlugin().Geocoder.geocode(request, (mvcArray: any) => { if (mvcArray) { resolve(new BaseArrayClass(mvcArray)); @@ -1641,7 +1642,7 @@ export class Geocoder { // address: "Kyoto, Japan" // }) // ------------------------- - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { GoogleMaps.getPlugin().Geocoder.geocode(request, (results: GeocoderResult[]) => { if (results) { resolve(results); @@ -1945,7 +1946,7 @@ export class GoogleMap extends BaseClass { } }; this._objectInstance.one = this._objectInstance.addEventListenerOnce; - (new Promise((resolve, reject) => { + (getPromise((resolve, reject) => { let count: number = 0; let timer: any = setInterval(() => { let target = document.querySelector('.show-page #' + element); @@ -2193,7 +2194,7 @@ export class GoogleMap extends BaseClass { delete this.get('_overlays')[overlayId]; }); } - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.remove(() => resolve()); }); } @@ -2210,7 +2211,7 @@ export class GoogleMap extends BaseClass { delete this.get('_overlays')[overlayId]; }); } - return new Promise((resolve) => { + return getPromise((resolve) => { this._objectInstance.clear(() => resolve()); }); } @@ -2315,7 +2316,7 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() addMarker(options: MarkerOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addMarker(options, (marker: any) => { if (marker) { let overlayId: string = marker.getId(); @@ -2337,7 +2338,7 @@ export class GoogleMap extends BaseClass { @InstanceCheck() addMarkerCluster(options: MarkerClusterOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addMarkerCluster(options, (markerCluster: any) => { if (markerCluster) { let overlayId = markerCluster.getId(); @@ -2364,7 +2365,7 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() addCircle(options: CircleOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addCircle(options, (circle: any) => { if (circle) { let overlayId: string = circle.getId(); @@ -2390,7 +2391,7 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() addPolygon(options: PolygonOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addPolygon(options, (polygon: any) => { if (polygon) { let overlayId: string = polygon.getId(); @@ -2416,7 +2417,7 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() addPolyline(options: PolylineOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addPolyline(options, (polyline: any) => { if (polyline) { let overlayId: string = polyline.getId(); @@ -2441,7 +2442,7 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() addTileOverlay(options: TileOverlayOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addTileOverlay(options, (tileOverlay: any) => { if (tileOverlay) { let overlayId: string = tileOverlay.getId(); @@ -2466,7 +2467,7 @@ export class GoogleMap extends BaseClass { */ @InstanceCheck() addGroundOverlay(options: GroundOverlayOptions): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { this._objectInstance.addGroundOverlay(options, (groundOverlay: any) => { if (groundOverlay) { let overlayId: string = groundOverlay.getId(); @@ -2507,7 +2508,7 @@ export class GoogleMap extends BaseClass { // */ // @InstanceCheck() // addKmlOverlay(options: KmlOverlayOptions): Promise { - // return new Promise((resolve, reject) => { + // return getPromise((resolve, reject) => { // this._objectInstance.addKmlOverlay(options, (kmlOverlay: any) => { // if (kmlOverlay) { // resolve(new KmlOverlay(kmlOverlay)); @@ -3530,7 +3531,7 @@ export class TileOverlay extends BaseClass { // if (!this._objectInstance) { // return Promise.reject({ error: 'plugin_not_installed' }); // } -// return new Promise( +// return getPromise( // resolve => this._objectInstance.addListenerOnce(eventName, resolve) // ); // } @@ -3579,7 +3580,7 @@ export class TileOverlay extends BaseClass { // if (!this._objectInstance) { // return Promise.reject({ error: 'plugin_not_installed' }); // } -// return new Promise( +// return getPromise( // resolve => this._objectInstance.one(eventName, resolve) // ); // } diff --git a/src/@ionic-native/plugins/printer/index.ts b/src/@ionic-native/plugins/printer/index.ts index b978f1396..052ba1c5c 100644 --- a/src/@ionic-native/plugins/printer/index.ts +++ b/src/@ionic-native/plugins/printer/index.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Cordova, CordovaCheck, IonicNativePlugin, Plugin } from '@ionic-native/core'; +import { Cordova, CordovaCheck, IonicNativePlugin, Plugin, getPromise } from '@ionic-native/core'; export interface PrintOptions { /** @@ -90,7 +90,7 @@ export class Printer extends IonicNativePlugin { */ @CordovaCheck() check(): Promise { - return new Promise((resolve: Function) => { + return getPromise((resolve: Function) => { Printer.getPlugin() .check((avail: boolean, count: any) => { resolve({ avail, count }); diff --git a/src/@ionic-native/plugins/screenshot/index.ts b/src/@ionic-native/plugins/screenshot/index.ts index c874463cd..c745cb793 100644 --- a/src/@ionic-native/plugins/screenshot/index.ts +++ b/src/@ionic-native/plugins/screenshot/index.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { IonicNativePlugin, Plugin } from '@ionic-native/core'; +import { IonicNativePlugin, Plugin, getPromise } from '@ionic-native/core'; declare const navigator: any; @@ -42,7 +42,7 @@ export class Screenshot extends IonicNativePlugin { * @returns {Promise} */ save(format?: string, quality?: number, filename?: string): Promise { - return new Promise( + return getPromise( (resolve, reject) => { navigator.screenshot.save( (error: any, result: any) => { @@ -68,7 +68,7 @@ export class Screenshot extends IonicNativePlugin { * @returns {Promise} */ URI(quality?: number): Promise { - return new Promise( + return getPromise( (resolve, reject) => { navigator.screenshot.URI( (error: any, result: any) => { diff --git a/src/@ionic-native/plugins/secure-storage/index.ts b/src/@ionic-native/plugins/secure-storage/index.ts index 6c99cb50f..f19ae68cf 100644 --- a/src/@ionic-native/plugins/secure-storage/index.ts +++ b/src/@ionic-native/plugins/secure-storage/index.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { CordovaCheck, CordovaInstance, IonicNativePlugin, Plugin } from '@ionic-native/core'; +import { CordovaCheck, CordovaInstance, IonicNativePlugin, Plugin, getPromise } from '@ionic-native/core'; /** * @hidden @@ -142,7 +142,7 @@ export class SecureStorage extends IonicNativePlugin { */ @CordovaCheck() create(store: string): Promise { - return new Promise((res: Function, rej: Function) => { + return getPromise((res: Function, rej: Function) => { const instance = new (SecureStorage.getPlugin())(() => res(new SecureStorageObject(instance)), rej, store); }); } diff --git a/src/@ionic-native/plugins/sqlite/index.ts b/src/@ionic-native/plugins/sqlite/index.ts index 588391962..20ce161e2 100644 --- a/src/@ionic-native/plugins/sqlite/index.ts +++ b/src/@ionic-native/plugins/sqlite/index.ts @@ -5,7 +5,8 @@ import { CordovaInstance, InstanceProperty, IonicNativePlugin, - Plugin + Plugin, + getPromise } from '@ionic-native/core'; declare const sqlitePlugin: any; @@ -192,7 +193,7 @@ export class SQLite extends IonicNativePlugin { */ @CordovaCheck() create(config: SQLiteDatabaseConfig): Promise { - return new Promise((resolve, reject) => { + return getPromise((resolve, reject) => { sqlitePlugin.openDatabase(config, (db: any) => resolve(new SQLiteObject(db)), reject); }); }