2015-11-29 08:26:55 +08:00
import { get } from '../util' ;
2015-12-02 03:33:08 +08:00
import { publishAngular1Service } from '../ng1' ;
2015-11-29 08:26:55 +08:00
declare var window ;
declare var Promise ;
2015-12-02 03:33:08 +08:00
declare var $q ;
2015-11-29 08:26:55 +08:00
2016-06-03 22:05:07 +08:00
import { Observable } from 'rxjs/Observable' ;
2015-12-01 02:34:54 +08:00
2016-03-13 07:52:25 +08:00
/ * *
* @private
* @param pluginRef
* @returns { null | * }
* /
2016-04-25 18:22:17 +08:00
export const getPlugin = function ( pluginRef : string ) : any {
2015-11-30 07:20:11 +08:00
return get ( window , pluginRef ) ;
2016-03-07 04:27:26 +08:00
} ;
2016-03-13 07:52:25 +08:00
/ * *
* @private
* @param pluginRef
* @returns { boolean }
* /
2016-04-25 18:22:17 +08:00
export const isInstalled = function ( pluginRef : string ) : boolean {
2015-11-30 07:20:11 +08:00
return ! ! getPlugin ( pluginRef ) ;
2016-03-07 04:27:26 +08:00
} ;
2016-03-13 07:52:25 +08:00
/ * *
* @private
* @param pluginObj
* @param method
* /
2016-04-25 18:22:17 +08:00
export const pluginWarn = function ( pluginObj : any , method : string ) {
2016-03-05 03:52:57 +08:00
var pluginName = pluginObj . name ;
var plugin = pluginObj . plugin ;
2016-04-30 11:56:49 +08:00
if ( method ) {
2016-03-05 03:52:57 +08:00
console . warn ( 'Native: tried calling ' + pluginName + '.' + method + ', but the ' + pluginName + ' plugin is not installed.' ) ;
2015-11-30 07:20:11 +08:00
} else {
2016-03-05 03:52:57 +08:00
console . warn ( 'Native: tried accessing the ' + pluginName + ' plugin but it\'s not installed.' ) ;
2015-11-30 07:20:11 +08:00
}
2016-03-05 03:52:57 +08:00
console . warn ( 'Install the ' + pluginName + ' plugin: \'cordova plugin add ' + plugin + '\'' ) ;
2016-03-07 04:27:26 +08:00
} ;
2016-03-13 07:52:25 +08:00
/ * *
* @private
* @param pluginName
* @param method
* /
2016-04-25 18:22:17 +08:00
export const cordovaWarn = function ( pluginName : string , method : string ) {
2016-04-30 11:56:49 +08:00
if ( method ) {
2015-11-30 07:20:11 +08:00
console . warn ( 'Native: tried calling ' + pluginName + '.' + method + ', but Cordova is not available. Make sure to include cordova.js or run in a device/simulator' ) ;
} else {
console . warn ( 'Native: tried accessing the ' + pluginName + ' plugin but Cordova is not available. Make sure to include cordova.js or run in a device/simulator' ) ;
}
2016-03-07 04:27:26 +08:00
} ;
2016-04-30 11:56:49 +08:00
function setIndex ( args : any [ ] , opts : any = { } , resolve? : Function , reject? : Function ) : any {
// If the plugin method expects myMethod(success, err, options)
if ( opts . callbackOrder === 'reverse' ) {
// Get those arguments in the order [resolve, reject, ...restOfArgs]
args . unshift ( reject ) ;
args . unshift ( resolve ) ;
} else if ( typeof opts . successIndex !== 'undefined' || typeof opts . errorIndex !== 'undefined' ) {
// If we've specified a success/error index
args . splice ( opts . successIndex , 0 , resolve ) ;
args . splice ( opts . errorIndex , 0 , reject ) ;
} else {
// Otherwise, let's tack them on to the end of the argument list
// which is 90% of cases
args . push ( resolve ) ;
args . push ( reject ) ;
}
2015-11-30 07:20:11 +08:00
2016-04-30 11:56:49 +08:00
return args ;
2016-03-29 18:50:03 +08:00
}
2016-03-30 05:53:51 +08:00
2016-04-30 11:56:49 +08:00
function callCordovaPlugin ( pluginObj : any , methodName : string , args : any [ ] , opts : any = { } , resolve? : Function , reject? : Function ) {
2015-12-01 02:34:54 +08:00
// Try to figure out where the success/error callbacks need to be bound
// to our promise resolve/reject handlers.
2016-04-30 11:56:49 +08:00
args = setIndex ( args , opts , resolve , reject ) ;
2015-12-01 02:34:54 +08:00
let pluginInstance = getPlugin ( pluginObj . pluginRef ) ;
2016-04-30 11:56:49 +08:00
if ( ! pluginInstance ) {
2016-04-30 09:46:35 +08:00
// Do this check in here in the case that the Web API for this plugin is available (for example, Geolocation).
2016-04-30 11:56:49 +08:00
if ( ! window . cordova ) {
2016-04-30 09:46:35 +08:00
cordovaWarn ( pluginObj . name , methodName ) ;
return {
error : 'cordova_not_available'
2016-04-30 11:56:49 +08:00
} ;
2016-04-30 09:46:35 +08:00
}
2015-12-01 02:34:54 +08:00
2016-04-30 09:46:35 +08:00
pluginWarn ( pluginObj , methodName ) ;
return {
error : 'plugin_not_installed'
} ;
}
2015-12-01 02:34:54 +08:00
2015-12-01 03:27:25 +08:00
// TODO: Illegal invocation needs window context
return get ( window , pluginObj . pluginRef ) [ methodName ] . apply ( pluginInstance , args ) ;
2015-12-01 02:34:54 +08:00
}
2015-12-02 03:33:08 +08:00
function getPromise ( cb ) {
2016-04-30 11:56:49 +08:00
if ( window . Promise ) {
2016-03-05 03:53:59 +08:00
// console.log('Native promises available...');
2015-12-02 03:33:08 +08:00
return new Promise ( ( resolve , reject ) = > {
cb ( resolve , reject ) ;
2016-04-30 11:56:49 +08:00
} ) ;
} else if ( window . angular ) {
2015-12-02 03:33:08 +08:00
let $q = window . angular . injector ( [ 'ng' ] ) . get ( '$q' ) ;
2016-03-05 03:53:59 +08:00
// console.log('Loaded $q', $q);
2015-12-02 03:33:08 +08:00
return $q ( ( resolve , reject ) = > {
cb ( resolve , reject ) ;
} ) ;
} else {
console . error ( 'No Promise support or polyfill found. To enable Ionic Native support, please add the es6-promise polyfill before this script, or run with a library like Angular 1/2 or on a recent browser.' ) ;
}
}
2016-04-30 11:56:49 +08:00
function wrapPromise ( pluginObj : any , methodName : string , args : any [ ] , opts : any = { } ) {
2016-04-28 02:00:57 +08:00
let pluginResult , rej ;
const p = getPromise ( ( resolve , reject ) = > {
pluginResult = callCordovaPlugin ( pluginObj , methodName , args , opts , resolve , reject ) ;
rej = reject ;
} ) ;
// Angular throws an error on unhandled rejection, but in this case we have already printed
// a warning that Cordova is undefined or the plugin is uninstalled, so there is no reason
// to error
if ( pluginResult && pluginResult . error ) {
p . catch ( ( ) = > { } ) ;
rej ( pluginResult . error ) ;
}
return p ;
2015-12-01 02:34:54 +08:00
}
2016-04-30 11:56:49 +08:00
function wrapObservable ( pluginObj : any , methodName : string , args : any [ ] , opts : any = { } ) {
2015-12-01 03:27:25 +08:00
return new Observable ( observer = > {
2015-12-01 04:38:52 +08:00
let pluginResult = callCordovaPlugin ( pluginObj , methodName , args , opts , observer . next . bind ( observer ) , observer . error . bind ( observer ) ) ;
2016-04-28 02:00:57 +08:00
if ( pluginResult && pluginResult . error ) {
observer . error ( pluginResult . error ) ;
}
2015-12-01 02:34:54 +08:00
return ( ) = > {
2015-12-01 04:38:52 +08:00
try {
2016-04-30 11:56:49 +08:00
if ( opts . clearWithArgs ) {
2016-02-09 02:42:42 +08:00
return get ( window , pluginObj . pluginRef ) [ opts . clearFunction ] . apply ( pluginObj , args ) ;
}
2016-02-09 03:07:26 +08:00
return get ( window , pluginObj . pluginRef ) [ opts . clearFunction ] . call ( pluginObj , pluginResult ) ;
2016-04-30 11:56:49 +08:00
} catch ( e ) {
2015-12-01 04:38:52 +08:00
console . warn ( 'Unable to clear the previous observable watch for' , pluginObj . name , methodName ) ;
2016-03-05 03:53:59 +08:00
console . error ( e ) ;
2015-12-01 04:38:52 +08:00
}
2016-04-30 11:56:49 +08:00
} ;
2015-12-01 02:34:54 +08:00
} ) ;
}
2016-04-30 11:56:49 +08:00
function callInstance ( pluginObj : any , methodName : string , args : any [ ] , opts : any = { } , resolve? : Function , reject? : Function ) {
args = setIndex ( args , opts , resolve , reject ) ;
return pluginObj . _objectInstance [ methodName ] . apply ( pluginObj . _objectInstance , args ) ;
2016-03-29 18:50:03 +08:00
}
2016-05-14 15:24:45 +08:00
function wrapInstance ( pluginObj : any , methodName : string , opts : any = { } ) {
2016-04-30 09:46:35 +08:00
return ( . . . args ) = > {
2016-04-25 18:22:17 +08:00
if ( opts . sync ) {
2016-04-30 09:46:35 +08:00
return callInstance ( pluginObj , methodName , args , opts ) ;
2016-04-25 18:22:17 +08:00
} else if ( opts . observable ) {
2016-04-30 09:46:35 +08:00
return new Observable ( observer = > {
2016-04-30 11:56:49 +08:00
let pluginResult = callInstance ( pluginObj , methodName , args , opts , observer . next . bind ( observer ) , observer . error . bind ( observer ) ) ;
2016-04-30 09:46:35 +08:00
return ( ) = > {
try {
2016-04-30 11:56:49 +08:00
if ( opts . clearWithArgs ) {
2016-04-30 09:46:35 +08:00
return pluginObj . _objectInstance [ opts . clearFunction ] . apply ( pluginObj . _objectInstance , args ) ;
2016-04-25 18:22:17 +08:00
}
2016-04-30 09:46:35 +08:00
return pluginObj . _objectInstance [ opts . clearFunction ] . call ( pluginObj , pluginResult ) ;
2016-04-30 11:56:49 +08:00
} catch ( e ) {
2016-04-30 09:46:35 +08:00
console . warn ( 'Unable to clear the previous observable watch for' , pluginObj . name , methodName ) ;
console . error ( e ) ;
2016-03-30 05:49:53 +08:00
}
2016-04-30 11:56:49 +08:00
} ;
2016-04-30 09:46:35 +08:00
} ) ;
2016-04-25 18:22:17 +08:00
} else {
2016-04-30 09:46:35 +08:00
return getPromise ( ( resolve , reject ) = > {
callInstance ( pluginObj , methodName , args , opts , resolve , reject ) ;
} ) ;
2016-04-25 18:22:17 +08:00
}
2016-04-30 11:56:49 +08:00
} ;
2016-03-29 18:50:03 +08:00
}
2016-03-14 03:30:21 +08:00
/ * *
* Wrap the event with an observable
* @param event
* @returns { Observable }
* /
2016-04-30 11:56:49 +08:00
function wrapEventObservable ( event : string ) : Observable < any > {
2016-03-14 03:30:21 +08:00
return new Observable ( observer = > {
2016-04-30 11:56:49 +08:00
let callback = ( status : any ) = > observer . next ( status ) ;
2016-03-14 03:30:21 +08:00
window . addEventListener ( event , callback , false ) ;
return ( ) = > window . removeEventListener ( event , callback , false ) ;
} ) ;
}
2016-03-13 07:52:25 +08:00
/ * *
* @private
* @param pluginObj
* @param methodName
* @param opts
* @returns { function ( . . . [ any ] ) : ( undefined | * | Observable | * | * ) }
* /
2016-04-30 11:56:49 +08:00
export const wrap = function ( pluginObj : any , methodName : string , opts : any = { } ) {
2015-12-01 02:34:54 +08:00
return ( . . . args ) = > {
2016-04-30 11:56:49 +08:00
if ( opts . sync )
2016-02-10 04:45:57 +08:00
return callCordovaPlugin ( pluginObj , methodName , args , opts ) ;
2016-03-14 03:30:21 +08:00
else if ( opts . observable )
2015-12-01 02:34:54 +08:00
return wrapObservable ( pluginObj , methodName , args , opts ) ;
2016-03-14 03:30:21 +08:00
else if ( opts . eventObservable && opts . event )
return wrapEventObservable ( opts . event ) ;
else
2015-12-01 02:34:54 +08:00
return wrapPromise ( pluginObj , methodName , args , opts ) ;
2016-04-30 11:56:49 +08:00
} ;
2016-03-07 04:27:26 +08:00
} ;
2015-11-29 08:26:55 +08:00
2015-11-30 09:54:45 +08:00
/ * *
2016-03-13 07:52:25 +08:00
* @private
*
2015-11-30 09:54:45 +08:00
* Class decorator specifying Plugin metadata . Required for all plugins .
2016-03-13 07:30:16 +08:00
*
* @usage
* ` ` ` ts
* @Plugin ( {
* name : 'MyPlugin' ,
* plugin : 'cordova-plugin-myplugin' ,
* pluginRef : 'window.myplugin'
* } )
* export class MyPlugin {
*
* // Plugin wrappers, properties, and functions go here ...
*
* }
* ` ` `
2015-11-30 09:54:45 +08:00
* /
2015-11-29 08:26:55 +08:00
export function Plugin ( config ) {
2016-04-25 18:22:17 +08:00
return function ( cls ) {
2015-11-29 08:26:55 +08:00
// Add these fields to the class
2016-02-10 04:45:57 +08:00
for ( let k in config ) {
2015-11-29 08:26:55 +08:00
cls [ k ] = config [ k ] ;
}
2016-04-25 18:22:17 +08:00
cls [ 'installed' ] = function ( ) {
2015-12-02 03:33:08 +08:00
return ! ! getPlugin ( config . pluginRef ) ;
2016-03-07 04:27:26 +08:00
} ;
2015-12-02 03:33:08 +08:00
2015-11-29 08:26:55 +08:00
return cls ;
2016-04-30 11:56:49 +08:00
} ;
2015-11-29 08:26:55 +08:00
}
2015-11-30 09:54:45 +08:00
/ * *
2016-03-13 07:52:25 +08:00
* @private
*
2015-11-30 09:54:45 +08:00
* Wrap a stub function in a call to a Cordova plugin , checking if both Cordova
* and the required plugin are installed .
* /
2016-04-30 11:56:49 +08:00
export function Cordova ( opts : any = { } ) {
2016-04-25 18:22:17 +08:00
return ( target : Object , methodName : string , descriptor : TypedPropertyDescriptor < any > ) = > {
2015-11-30 09:54:45 +08:00
let originalMethod = descriptor . value ;
return {
2016-04-25 18:22:17 +08:00
value : function ( . . . args : any [ ] ) {
2015-11-30 11:50:58 +08:00
return wrap ( this , methodName , opts ) . apply ( this , args ) ;
2015-11-30 09:54:45 +08:00
}
2016-04-30 11:56:49 +08:00
} ;
} ;
2015-11-29 08:26:55 +08:00
}
2015-11-30 07:20:11 +08:00
2016-03-30 05:49:53 +08:00
/ * *
* @private
*
* Wrap an instance method
* /
2016-04-30 11:56:49 +08:00
export function CordovaInstance ( opts : any = { } ) {
return ( target : Object , methodName : string ) = > {
return {
value : function ( . . . args : any [ ] ) {
return wrapInstance ( this , methodName , opts ) . apply ( this , args ) ;
}
} ;
} ;
2016-03-29 18:50:03 +08:00
}
2015-11-30 09:54:45 +08:00
/ * *
2016-03-13 07:52:25 +08:00
* @private
*
*
2015-11-30 09:54:45 +08:00
* Before calling the original method , ensure Cordova and the plugin are installed .
* /
2016-04-25 18:22:17 +08:00
export function CordovaProperty ( target : Function , key : string , descriptor : TypedPropertyDescriptor < any > ) {
2016-03-05 03:56:22 +08:00
let originalMethod = descriptor . get ;
2015-11-30 07:20:11 +08:00
2016-04-25 18:22:17 +08:00
descriptor . get = function ( . . . args : any [ ] ) {
2016-04-30 11:56:49 +08:00
if ( ! window . cordova ) {
2015-11-30 07:20:11 +08:00
cordovaWarn ( this . name , null ) ;
2016-03-05 03:56:22 +08:00
return { } ;
2015-11-30 07:20:11 +08:00
}
let pluginInstance = getPlugin ( this . pluginRef ) ;
2016-04-30 11:56:49 +08:00
if ( ! pluginInstance ) {
2016-03-05 03:52:57 +08:00
pluginWarn ( this , key ) ;
2016-04-30 11:56:49 +08:00
return { } ;
2015-11-30 07:20:11 +08:00
}
2016-02-17 07:40:54 +08:00
return originalMethod . apply ( this , args ) ;
2016-03-07 04:27:26 +08:00
} ;
2015-11-30 07:20:11 +08:00
return descriptor ;
}
2016-05-01 01:31:10 +08:00
/ * *
* @private
* @param target
* @param key
* @param descriptor
* @constructor
* /
export function InstanceProperty ( target : Function , key : string , descriptor : TypedPropertyDescriptor < any > ) {
descriptor . get = function ( ) {
return this . _objectInstance [ key ] ;
} ;
descriptor . get = function ( . . . args : any [ ] ) {
return this . _objectInstance [ key ] = args [ 0 ] ;
} ;
return descriptor ;
2016-05-21 04:59:18 +08:00
}