Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add new 2.1 device.*

  • Loading branch information...
commit 963675781ee0c99783a46aa828681baa9ca1bfe5 1 parent 0c2afcd
@aconran aconran authored
View
50 device/Contacts.js
@@ -0,0 +1,50 @@
+/**
+ * This device API allows you to access a users contacts using a {@link Ext.data.Store}. This allows you to search, filter
+ * and sort through all the contacts using its methods.
+ *
+ * To use this API, all you need to do is require this class (`Ext.device.Contacts`) and then use `Ext.device.Contacts.getContacts()`
+ * to retrieve an array of contacts.
+ *
+ * **Please note that this will *only* work using the Sencha Native Packager.**
+ *
+ * # Example
+ *
+ * Ext.application({
+ * name: 'Sencha',
+ * requires: 'Ext.device.Contacts',
+ *
+ * launch: function() {
+ * Ext.Viewport.add({
+ * xtype: 'list',
+ * itemTpl: '{First} {Last}',
+ * store: {
+ * fields: ['First', 'Last'],
+ * data: Ext.device.Contacts.getContacts()
+ * }
+ * });
+ * }
+ * });
+ *
+ * @mixins Ext.device.contacts.Abstract
+ * @mixins Ext.device.contacts.Sencha
+ *
+ * @aside guide native_apis
+ */
+Ext.define('Ext.device.Contacts', {
+ singleton: true,
+
+ requires: [
+ 'Ext.device.Communicator',
+ 'Ext.device.contacts.Sencha'
+ ],
+
+ constructor: function() {
+ var browserEnv = Ext.browser.is;
+
+ if (browserEnv.WebView && !browserEnv.PhoneGap) {
+ return Ext.create('Ext.device.contacts.Sencha');
+ } else {
+ return Ext.create('Ext.device.contacts.Abstract');
+ }
+ }
+});
View
63 device/Device.js
@@ -2,9 +2,70 @@
* Provides a cross device way to get information about the device your application is running on. There are 3 different implementations:
*
* - Sencha Packager
- * - (PhoneGap)[http://docs.phonegap.com/en/1.4.1/phonegap_device_device.md.html]
+ * - [PhoneGap](http://docs.phonegap.com/en/1.4.1/phonegap_device_device.md.html)
* - Simulator
*
+ * ## Examples
+ *
+ * #### Device Information
+ *
+ * Getting the device information:
+ *
+ * Ext.application({
+ * name: 'Sencha',
+ *
+ * // Remember that the Ext.device.Device class *must* be required
+ * requires: ['Ext.device.Device'],
+ *
+ * launch: function() {
+ * alert([
+ * 'Device name: ' + Ext.device.Device.name,
+ * 'Device platform: ' + Ext.device.Device.platform,
+ * 'Device UUID: ' + Ext.device.Device.uuid
+ * ].join('\n'));
+ * }
+ * });
+ *
+ * ### Custom Scheme URLs
+ *
+ * Using custom scheme URLs to application your application from other applications:
+ *
+ * Ext.application({
+ * name: 'Sencha',
+ * requires: ['Ext.device.Device'],
+ * launch: function() {
+ * if (Ext.device.Device.scheme) {
+ * // the application was opened via another application. Do something:
+ * alert('Applicaton pened via another application: ' + Ext.device.Device.scheme.url);
+ * }
+ *
+ * // Listen for future changes
+ * Ext.device.Device.on('schemeupdate', function(device, scheme) {
+ * // the application was launched, closed, and then launched another from another application
+ * // this means onReady wont be called again ('cause the application is already running in the
+ * // background) - but this event will be fired
+ * alert('Applicated reopened via another application: ' + scheme.url);
+ * }, this);
+ * }
+ * });
+ *
+ * Of course, you must add add the custom URLs you would like to use when packaging your application. You can do this by adding
+ * the following code into the `rawConfig` property inside your `package.json` file (Sencha Native Packager configuration file):
+ *
+ * {
+ * ...
+ * "rawConfig": "<key>CFBundleURLTypes</key><array><dict><key>CFBundleURLSchemes</key><array><string>sencha</string></array><key>CFBundleURLName</key><string>com.sencha.example</string></dict></array>"
+ * ...
+ * }
+ *
+ * You can change the available URL schemes and the application identifier above.
+ *
+ * You can then test it by packaging and installing the application onto a device/iOS Simulator, opening Safari and typing: `sencha:testing`.
+ * The application will launch and it will `alert` the URL you specified.
+ *
+ * **PLEASE NOTE: This currently only works with the Sencha Native Packager. If you attempt to listen to this event when packaged with
+ * PhoneGap or simply in the browser, it will not function.**
+ *
* @mixins Ext.device.device.Abstract
*
* @aside guide native_apis
View
16 device/Geolocation.js
@@ -41,7 +41,6 @@ Ext.define('Ext.device.Geolocation', {
requires: [
'Ext.device.Communicator',
- // 'Ext.device.geolocation.PhoneGap',
'Ext.device.geolocation.Sencha',
'Ext.device.geolocation.Simulator'
],
@@ -49,12 +48,15 @@ Ext.define('Ext.device.Geolocation', {
constructor: function() {
var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.PhoneGap) {
- return Ext.create('Ext.device.geolocation.PhoneGap');
- }
- else {
- return Ext.create('Ext.device.geolocation.Sencha');
+ if (browserEnv.WebView && browserEnv.Sencha) {
+ return Ext.create('Ext.device.geolocation.Sencha');
+ }
+ else {
+ return Ext.create('Ext.device.geolocation.Simulator');
+ }
+ }
+});
+ return Ext.create('Ext.device.geolocation.Sencha');
}
}
else {
View
10 device/Notification.js
@@ -1,5 +1,5 @@
/**
- * Provides a cross device way to show notifications. There are 3 different implementations:
+ * Provides a cross device way to show notifications. There are three different implementations:
*
* - Sencha Packager
* - PhoneGap
@@ -16,18 +16,18 @@
*
* Ext.device.Notification.show({
* title: 'Verification',
- * message: 'Is your email address is: test@sencha.com',
+ * message: 'Is your email address: test@sencha.com',
* buttons: Ext.MessageBox.OKCANCEL,
* callback: function(button) {
- * if (button == "ok") {
+ * if (button === "ok") {
* console.log('Verified');
* } else {
- * console.log('Nope.');
+ * console.log('Nope');
* }
* }
* });
*
- * To make the device virbate:
+ * To make the device vibrate:
*
* Ext.device.Notification.vibrate();
*
View
18 device/Purchases.js
@@ -0,0 +1,18 @@
+/**
+ *
+ *
+ * @mixins Ext.device.purchases.Sencha
+ *
+ * @aside guide native_apis
+ */
+Ext.define('Ext.device.Purchases', {
+ singleton: true,
+
+ requires: [
+ 'Ext.device.purchases.Sencha'
+ ],
+
+ constructor: function() {
+ return Ext.create('Ext.device.purchases.Sencha');
+ }
+});
View
49 device/Push.js
@@ -0,0 +1,49 @@
+/**
+ * Provides a way to send push notifications to a device. Currently only available on iOS.
+ *
+ * # Example
+ *
+ * Ext.device.Push.register({
+ * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE|Ext.device.Push.SOUND,
+ * success: function(token) {
+ * console.log('# Push notification registration successful:');
+ * console.log(' token: ' + token);
+ * },
+ * failure: function(error) {
+ * console.log('# Push notification registration unsuccessful:');
+ * console.log(' error: ' + error);
+ * },
+ * received: function(notifications) {
+ * console.log('# Push notification received:');
+ * console.log(' ' + JSON.stringify(notifications));
+ * }
+ * });
+ *
+ * @mixins Ext.device.push.Abstract
+ *
+ * @aside guide native_apis
+ */
+Ext.define('Ext.device.Push', {
+ singleton: true,
+
+ requires: [
+ 'Ext.device.Communicator',
+ 'Ext.device.push.Sencha'
+ ],
+
+ constructor: function() {
+ var browserEnv = Ext.browser.is;
+
+ if (browserEnv.WebView) {
+ if (!browserEnv.PhoneGap) {
+ return Ext.create('Ext.device.push.Sencha');
+ }
+ else {
+ return Ext.create('Ext.device.push.Abstract');
+ }
+ }
+ else {
+ return Ext.create('Ext.device.push.Abstract');
+ }
+ }
+});
View
45 device/communicator/Default.js
@@ -14,7 +14,7 @@
* // Do something with the base64-encoded `dataUri` string
* },
* function(errorMessage) {
- *
+ *
* },
* callbackScope,
* {
@@ -23,41 +23,45 @@
* height: 500
* }
* );
- *
+ *
* Internally, `Ext.device.Communicator.send()` will then be invoked with the following argument:
- *
+ *
* Ext.device.Communicator.send({
* command: 'Camera#capture',
* callbacks: {
- * onSuccess: function() { ... },
- * onError: function() { ... },
+ * onSuccess: function() {
+ * // ...
+ * },
+ * onError: function() {
+ * // ...
+ * }
* },
* scope: callbackScope,
* quality: 75,
* width: 500,
* height: 500
* });
- *
+ *
* Which will then be transformed into a HTTP GET request, sent to native shell's local
* HTTP server with the following parameters:
- *
+ *
* ?quality=75&width=500&height=500&command=Camera%23capture&onSuccess=3&onError=5
- *
+ *
* Notice that `onSuccess` and `onError` have been converted into string ids (`3` and `5`
* respectively) and maintained by `Ext.device.Communicator`.
- *
+ *
* Whenever the requested operation finishes, `Ext.device.Communicator.invoke()` simply needs
* to be executed from the native shell with the corresponding ids given before. For example:
- *
+ *
* Ext.device.Communicator.invoke('3', ['DATA_URI_OF_THE_CAPTURED_IMAGE_HERE']);
- *
+ *
* will invoke the original `onSuccess` callback under the given scope. (`callbackScope`), with
* the first argument of 'DATA_URI_OF_THE_CAPTURED_IMAGE_HERE'
- *
+ *
* Note that `Ext.device.Communicator` maintains the uniqueness of each function callback and
* its scope object. If subsequent calls to `Ext.device.Communicator.send()` have the same
* callback references, the same old ids will simply be reused, which guarantee the best possible
- * performance for a large amount of repeative calls.
+ * performance for a large amount of repetitive calls.
*/
Ext.define('Ext.device.communicator.Default', {
@@ -160,8 +164,19 @@ Ext.define('Ext.device.communicator.Default', {
doSend: function(args) {
var xhr = new XMLHttpRequest();
- xhr.open('GET', this.SERVER_URL + '?' + Ext.Object.toQueryString(args), false);
- xhr.send(null);
+ xhr.open('GET', this.SERVER_URL + '?' + Ext.Object.toQueryString(args) + '&_dc=' + new Date().getTime(), false);
+
+ // wrap the request in a try/catch block so we can check if any errors are thrown and attempt to call any
+ // failure/callback functions if defined
+ try {
+ xhr.send(null);
+ } catch(e) {
+ if (args.failure) {
+ this.invoke(args.failure);
+ } else if (args.callback) {
+ this.invoke(args.callback);
+ }
+ }
}
});
View
59 device/contacts/Abstract.js
@@ -0,0 +1,59 @@
+/**
+ * @private
+ */
+Ext.define('Ext.device.contacts.Abstract', {
+ extend: 'Ext.Evented',
+
+ config: {
+ /**
+ * @cfg {Boolean} includeImages
+ * True to include images when you get the contacts store. Please beware that this can be very slow.
+ */
+ includeImages: false
+ },
+
+ /**
+ * Returns an Array of contact objects.
+ * @return {Object[]} An array of contact objects.
+ */
+ getContacts: function(config) {
+ if (!this._store) {
+ this._store = [
+ {
+ first: 'Robert',
+ last: 'Dougan',
+ emails: {
+ work: 'rob@sencha.com'
+ }
+ },
+ {
+ first: 'Jamie',
+ last: 'Avins',
+ emails: {
+ work: 'jamie@sencha.com'
+ }
+ }
+ ];
+ }
+
+ config.success.call(config.scope || this, this._store);
+ },
+
+ /**
+ * Returns base64 encoded image thumbnail for a contact specified in config.id
+ * @return {String} base64 string
+ */
+
+ getThumbnail: function(config) {
+ config.callback.call(config.scope || this, "");
+ },
+
+
+ /**
+ * Returns localized, user readable label for a contact field (i.e. "Mobile", "Home")
+ * @return {String} user readable string
+ */
+ getLocalizedLabel: function(config) {
+ config.callback.call(config.scope || this, config.label.toUpperCase(), config.label);
+ }
+});
View
89 device/contacts/Sencha.js
@@ -0,0 +1,89 @@
+/**
+ * @private
+ */
+Ext.define('Ext.device.contacts.Sencha', {
+ extend: 'Ext.device.contacts.Abstract',
+
+ getContacts: function(config) {
+ var includeImages = this.getIncludeImages();
+ if (typeof config.includeImages != "undefined") {
+ includeImages = config.includeImages;
+ }
+
+ if (!config) {
+ Ext.Logger.warn('Ext.device.Contacts#getContacts: You must specify a `config` object.');
+ return false;
+ }
+
+ if (!config.success) {
+ Ext.Logger.warn('Ext.device.Contacts#getContacts: You must specify a `success` method.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Contacts#all',
+ callbacks: {
+ success: function(contacts) {
+ config.success.call(config.scope || this, contacts);
+ },
+ failure: function() {
+ if (config.failure) {
+ config.failure.call(config.scope || this);
+ }
+ }
+ },
+ includeImages: includeImages,
+ scope: this
+ });
+ },
+
+ getThumbnail: function(config) {
+ if (!config || typeof config.id == "undefined") {
+ Ext.Logger.warn('Ext.device.Contacts#getThumbnail: You must specify an `id` of the contact.');
+ return false;
+ }
+
+ if (!config || !config.callback) {
+ Ext.Logger.warn('Ext.device.Contacts#getThumbnail: You must specify a `callback`.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Contacts#getThumbnail',
+ callbacks: {
+ success: function(src) {
+ this.set('thumbnail', src);
+
+ if (config.callback) {
+ config.callback.call(config.scope || this, this);
+ }
+ }
+ },
+ id: id,
+ scope: this
+ });
+ },
+
+ getLocalizedLabel: function(config) {
+ if (!config || typeof config.label == "undefined") {
+ Ext.Logger.warn('Ext.device.Contacts#getLocalizedLabel: You must specify an `label` to be localized.');
+ return false;
+ }
+
+ if (!config || !config.callback) {
+ Ext.Logger.warn('Ext.device.Contacts#getLocalizedLabel: You must specify a `callback`.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Contacts#getLocalizedLabel',
+ callbacks: {
+ callback: function(label) {
+ config.callback.call(config.scope || this, label, config.label);
+ }
+ },
+ label: config.label,
+ scope: this
+ });
+ }
+});
View
84 device/device/Abstract.js
@@ -2,10 +2,52 @@
* @private
*/
Ext.define('Ext.device.device.Abstract', {
+ extend: 'Ext.EventedBase',
+
+ /**
+ * @event schemeupdate
+ * Event which is fired when your Sencha Native packaged application is opened from another application using a custom URL scheme.
+ *
+ * This event will only fire if the application was already open (in other words; `onReady` was already fired). This means you should check
+ * if {@link Ext.device.Device#scheme} is set in your Application `launch`/`onReady` method, and perform any needed changes for that URL (if defined).
+ * Then listen to this event for future changed.
+ *
+ * ## Example
+ *
+ * Ext.application({
+ * name: 'Sencha',
+ * requires: ['Ext.device.Device'],
+ * launch: function() {
+ * if (Ext.device.Device.scheme) {
+ * // the application was opened via another application. Do something:
+ * console.log('Applicaton opened via another application: ' + Ext.device.Device.scheme.url);
+ * }
+ *
+ * // Listen for future changes
+ * Ext.device.Device.on('schemeupdate', function(device, scheme) {
+ * // the application was launched, closed, and then launched another from another application
+ * // this means onReady wont be called again ('cause the application is already running in the
+ * // background) - but this event will be fired
+ * console.log('Applicated reopened via another application: ' + scheme.url);
+ * }, this);
+ * }
+ * });
+ *
+ * __Note:__ This currently only works with the Sencha Native Packager. If you attempt to listen to this event when packaged with
+ * PhoneGap or simply in the browser, it will never fire.**
+ *
+ * @param {Ext.device.Device} this The instance of Ext.device.Device
+ * @param {Object/Boolean} scheme The scheme information, if opened via another application
+ * @param {String} scheme.url The URL that was opened, if this application was opened via another application. Example: `sencha:`
+ * @param {String} scheme.sourceApplication The source application that opened this application. Example: `com.apple.safari`.
+ */
+
/**
* @property {String} name
* Returns the name of the current device. If the current device does not have a name (for example, in a browser), it will
- * default to `Not available`.
+ * default to `not available`.
+ *
+ * alert('Device name: ' + Ext.device.Device.name);
*/
name: 'not available',
@@ -13,12 +55,50 @@ Ext.define('Ext.device.device.Abstract', {
* @property {String} uuid
* Returns a unique identifier for the current device. If the current device does not have a unique identifier (for example,
* in a browser), it will default to `anonymous`.
+ *
+ * alert('Device UUID: ' + Ext.device.Device.uuid);
*/
uuid: 'anonymous',
/**
* @property {String} platform
* The current platform the device is running on.
+ *
+ * alert('Device platform: ' + Ext.device.Device.platform);
+ */
+ platform: Ext.os.name,
+
+ /**
+ * @property {Object/Boolean} scheme
+ *
+ */
+ scheme: false,
+
+ /**
+ * Opens a specified URL. The URL can contain a custom URL Scheme for another app or service:
+ *
+ * // Safari
+ * Ext.device.Device.openURL('http://sencha.com');
+ *
+ * // Telephone
+ * Ext.device.Device.openURL('tel:6501231234');
+ *
+ * // SMS with a default number
+ * Ext.device.Device.openURL('sms:+12345678901');
+ *
+ * // Email client
+ * Ext.device.Device.openURL('mailto:rob@sencha.com');
+ *
+ * You can find a full list of available URL schemes here: [http://wiki.akosma.com/IPhone_URL_Schemes](http://wiki.akosma.com/IPhone_URL_Schemes).
+ *
+ * __Note:__ This currently only works on iOS using the Sencha Native Packager. Attempting to use this on PhoneGap, iOS Simulator
+ * or the browser will simply result in the current window location changing.**
+ *
+ * If successful, this will close the application (as another one opens).
+ *
+ * @param {String} url The URL to open
*/
- platform: Ext.os.name
+ openURL: function(url) {
+ window.location = url;
+ }
});
View
9 device/device/PhoneGap.js
@@ -5,6 +5,15 @@ Ext.define('Ext.device.device.PhoneGap', {
extend: 'Ext.device.device.Abstract',
constructor: function() {
+ // We can't get the device details until the device is ready, so lets wait.
+ if (Ext.Viewport.isReady) {
+ this.onReady();
+ } else {
+ Ext.Viewport.on('ready', this.onReady, this, {single: true});
+ }
+ },
+
+ onReady: function() {
this.name = device.name;
this.uuid = device.uuid;
this.platform = device.platformName || Ext.os.name;
View
30 device/device/Sencha.js
@@ -8,5 +8,35 @@ Ext.define('Ext.device.device.Sencha', {
this.name = device.name;
this.uuid = device.uuid;
this.platform = device.platformName || Ext.os.name;
+
+ this.initURL();
+ },
+
+ openURL: function(url) {
+ Ext.device.Communicator.send({
+ command: 'OpenURL#open',
+ url: url
+ });
+ },
+
+ /**
+ * @private
+ */
+ initURL: function() {
+ Ext.device.Communicator.send({
+ command: "OpenURL#watch",
+ callbacks: {
+ callback: this.updateURL
+ },
+ scope: this
+ });
+ },
+
+ /**
+ * @private
+ */
+ updateURL: function() {
+ this.scheme = device.scheme || false;
+ this.fireEvent('schemeupdate', this, this.scheme);
}
});
View
2  device/geolocation/Abstract.js
@@ -137,5 +137,5 @@ Ext.define('Ext.device.geolocation.Abstract', {
/**
* If you are currently watching for the current position, this will stop that task.
*/
- clearWatch: Ext.emptyFn
+ clearWatch: function() {}
});
View
8 device/geolocation/Sencha.js
@@ -51,10 +51,8 @@ Ext.define('Ext.device.geolocation.Sencha', {
},
clearWatch: function() {
- if (this.geolocation) {
- this.geolocation.destroy();
- }
-
- this.geolocation = null;
+ Ext.device.Communicator.send({
+ command: 'Geolocation#clearWatch'
+ });
}
});
View
23 device/notification/PhoneGap.js
@@ -10,15 +10,28 @@ Ext.define('Ext.device.notification.PhoneGap', {
buttons = (config.buttons) ? config.buttons.join(',') : null,
onShowCallback = function(index) {
if (config.callback) {
- config.callback.apply(config.scope, (config.buttons) ? [config.buttons[index - 1]] : []);
+ config.callback.apply(config.scope, (config.buttons) ? [config.buttons[index - 1]].toLowerCase() : []);
}
};
+ // change Ext.MessageBox buttons into normal arrays
+ var ln = butons.length;
+ if (ln && typeof buttons[0] != "string") {
+ var newButtons = [],
+ i;
+
+ for (i = 0; i < ln; i++) {
+ newButtons.push(buttons[i].text);
+ }
+
+ buttons = newButtons;
+ }
+
navigator.notification.confirm(
- config.message,
- onShowCallback,
- config.title,
- buttons
+ config.message, // message
+ onShowCallback, // callback
+ config.title, // title
+ buttons // array of button names
);
},
View
302 device/purchases/Sencha.js
@@ -0,0 +1,302 @@
+/**
+ * @private
+ */
+Ext.define('Ext.device.purchases.Sencha', {
+ /**
+ * Checks if the current user is able to make payments.
+ *
+ * ## Example
+ *
+ * Ext.device.Purchases.canMakePayments({
+ * success: function() {
+ * console.log('Yup! :)');
+ * },
+ * failure: function() {
+ * console.log('Nope! :(');
+ * }
+ * });
+ *
+ * @param {Object} config
+ * @param {Function} config.success
+ * @param {Function} config.failure
+ * @param {Object} config.scope
+ */
+ canMakePayments: function(config) {
+ if (!config.success) {
+ Ext.Logger.error('You must specify a `success` callback for `#canMakePayments` to work.');
+ return false;
+ }
+
+ if (!config.failure) {
+ Ext.Logger.error('You must specify a `failure` callback for `#canMakePayments` to work.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Purchase#canMakePayments',
+ callbacks: {
+ success: config.success,
+ failure: config.failure
+ },
+ scope: config.scope || this
+ });
+ },
+
+ /**
+ * Returns a {@link Ext.data.Store} instance of all the available products.
+ *
+ * ## Example
+ *
+ * Ext.device.Purchases.getProducts({
+ * success: function(store) {
+ * console.log('Got the store! You have ' + store.getCount() + ' products.');
+ * },
+ * failure: function() {
+ * console.log('Oops. Looks like something went wrong.');
+ * }
+ * });
+ *
+ * @param {Object} config
+ * @param {Function} config.success
+ * @param {Ext.data.Store} config.success.store A store of products available to purchase.
+ * @param {Function} config.failure
+ * @param {Object} config.scope
+ */
+ getProducts: function(config) {
+ if (!config.success) {
+ Ext.Logger.error('You must specify a `success` callback for `#getProducts` to work.');
+ return false;
+ }
+
+ if (!config.failure) {
+ Ext.Logger.error('You must specify a `failure` callback for `#getProducts` to work.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Purchase#getProducts',
+ callbacks: {
+ success: function(products) {
+ var store = Ext.create('Ext.data.Store', {
+ model: 'Ext.device.Purchases.Product',
+ data: products
+ });
+
+ config.success.call(config.scope || this, store);
+ },
+ failure: config.failure
+ },
+ scope: config.scope || this
+ });
+ },
+
+ /**
+ * Returns all purchases ever made by this user.
+ * @param {Object} config
+ * @param {Function} config.success
+ * @param {Array[]} config.success.purchases
+ * @param {Function} config.failure
+ * @param {Object} config.scope
+ */
+ getPurchases: function(config) {
+ if (!config.success) {
+ Ext.Logger.error('You must specify a `success` callback for `#getPurchases` to work.');
+ return false;
+ }
+
+ if (!config.failure) {
+ Ext.Logger.error('You must specify a `failure` callback for `#getPurchases` to work.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Purchase#getPurchases',
+ callbacks: {
+ success: function(purchases) {
+ var array = [],
+ ln = purchases.length,
+ i;
+
+ for (i = 0; i < ln; i++) {
+ array.push({
+ productIdentifier: purchases[i]
+ });
+ }
+
+ var store = Ext.create('Ext.data.Store', {
+ model: 'Ext.device.Purchases.Purchase',
+ data: array
+ });
+
+ config.success.call(config.scope || this, store);
+ },
+ failure: function() {
+ config.failure.call(config.scope || this);
+ }
+ },
+ scope: config.scope || this
+ });
+ },
+
+ /**
+ * Returns all purchases that are currently pending.
+ * @param {Object} config
+ * @param {Function} config.success
+ * @param {Ext.data.Store} config.success.purchases
+ * @param {Function} config.failure
+ * @param {Object} config.scope
+ */
+ getPendingPurchases: function(config) {
+ if (!config.success) {
+ Ext.Logger.error('You must specify a `success` callback for `#getPendingPurchases` to work.');
+ return false;
+ }
+
+ if (!config.failure) {
+ Ext.Logger.error('You must specify a `failure` callback for `#getPendingPurchases` to work.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Purchase#getPendingPurchases',
+ callbacks: {
+ success: function(purchases) {
+ var array = [],
+ ln = purchases.length,
+ i;
+
+ for (i = 0; i < ln; i++) {
+ array.push({
+ productIdentifier: purchases[i],
+ state: 'pending'
+ });
+ }
+
+ var store = Ext.create('Ext.data.Store', {
+ model: 'Ext.device.Purchases.Purchase',
+ data: array
+ });
+
+ config.success.call(config.scope || this, store);
+ },
+ failure: function() {
+ config.failure.call(config.scope || this);
+ }
+ },
+ scope: config.scope || this
+ });
+ }
+}, function() {
+ /**
+ * The product model class which is uses when fetching available products using {@link Ext.device.Purchases#getProducts}.
+ */
+ Ext.define('Ext.device.Purchases.Product', {
+ extend: 'Ext.data.Model',
+
+ config: {
+ fields: [
+ 'localizeTitle',
+ 'price',
+ 'priceLocale',
+ 'localizedDescription',
+ 'productIdentifier'
+ ]
+ },
+
+ /**
+ * Will attempt to purchase this product.
+ *
+ * ## Example
+ *
+ * product.purchase({
+ * success: function() {
+ * console.log(product.get('title') + ' purchased!');
+ * },
+ * failure: function() {
+ * console.log('Something went wrong while trying to purchase ' + product.get('title'));
+ * }
+ * });
+ *
+ * @param {Object} config
+ * @param {Ext.data.Model/String} config.product
+ * @param {Function} config.success
+ * @param {Function} config.failure
+ */
+ purchase: function(config) {
+ if (!config.success) {
+ Ext.Logger.error('You must specify a `success` callback for `#product` to work.');
+ return false;
+ }
+
+ if (!config.failure) {
+ Ext.Logger.error('You must specify a `failure` callback for `#product` to work.');
+ return false;
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Purchase#purchase',
+ callbacks: {
+ success: config.success,
+ failure: config.failure
+ },
+ identifier: this.get('productIdentifier'),
+ scope: config.scope || this
+ });
+ }
+ });
+
+ /**
+ *
+ */
+ Ext.define('Ext.device.Purchases.Purchase', {
+ extend: 'Ext.data.Model',
+
+ config: {
+ fields: [
+ 'productIdentifier',
+ 'state'
+ ]
+ },
+
+ /**
+ * Attempts to mark this purchase as complete
+ * @param {Object} config
+ * @param {Function} config.success
+ * @param {Function} config.failure
+ * @param {Object} config.scope
+ */
+ complete: function(config) {
+ var me = this;
+
+ if (!config.success) {
+ Ext.Logger.error('You must specify a `success` callback for `#complete` to work.');
+ return false;
+ }
+
+ if (!config.failure) {
+ Ext.Logger.error('You must specify a `failure` callback for `#complete` to work.');
+ return false;
+ }
+
+ if (this.get('state') != "pending") {
+ config.failure.call(config.scope || this, "purchase is not pending");
+ }
+
+ Ext.device.Communicator.send({
+ command: 'Purchase#completePurchase',
+ identifier: me.get('productIdentifier'),
+ callbacks: {
+ success: function() {
+ me.set('state', 'complete');
+ config.success.call(config.scope || this);
+ },
+ failure: function() {
+ me.set('state', 'pending');
+ config.failure.call(config.scope || this);
+ }
+ },
+ scope: config.scope || this
+ });
+ }
+ });
+});
View
138 device/push/Abstract.js
@@ -0,0 +1,138 @@
+/**
+ * @private
+ */
+Ext.define('Ext.device.push.Abstract', {
+ /**
+ * @property
+ * Notification type: alert.
+ */
+ ALERT: 1,
+ /**
+ * @property
+ * Notification type: badge.
+ */
+ BADGE: 2,
+ /**
+ * @property
+ * Notification type: sound.
+ */
+ SOUND: 4,
+
+ /**
+ * @method getInitialConfig
+ * @hide
+ */
+
+ /**
+ * Registers a push notification.
+ *
+ * Ext.device.Push.register({
+ * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE|Ext.device.Push.SOUND,
+ * success: function(token) {
+ * console.log('# Push notification registration successful:');
+ * console.log(' token: ' + token);
+ * },
+ * failure: function(error) {
+ * console.log('# Push notification registration unsuccessful:');
+ * console.log(' error: ' + error);
+ * },
+ * received: function(notifications) {
+ * console.log('# Push notification received:');
+ * console.log(' ' + JSON.stringify(notifications));
+ * }
+ * });
+ *
+ * @param {Object} config
+ * The configuration for to pass when registering this push notification service.
+ *
+ * @param {Number} config.type
+ * The type(s) of notifications to enable. Available options are:
+ *
+ * - {@link Ext.device.Push#ALERT}
+ * - {@link Ext.device.Push#BADGE}
+ * - {@link Ext.device.Push#SOUND}
+ *
+ * **Usage**
+ *
+ * Enable alerts and badges:
+ *
+ * Ext.device.Push.register({
+ * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE
+ * // ...
+ * });
+ *
+ * Enable alerts, badges and sounds:
+ *
+ * Ext.device.Push.register({
+ * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE|Ext.device.Push.SOUND
+ * // ...
+ * });
+ *
+ * Enable only sounds:
+ *
+ * Ext.device.Push.register({
+ * type: Ext.device.Push.SOUND
+ * // ...
+ * });
+ *
+ * @param {Function} config.success
+ * The callback to be called when registration is complete.
+ *
+ * @param {String} config.success.token
+ * A unique token for this push notification service.
+ *
+ * @param {Function} config.failure
+ * The callback to be called when registration fails.
+ *
+ * @param {String} config.failure.error
+ * The error message.
+ *
+ * @param {Function} config.received
+ * The callback to be called when a push notification is received on this device.
+ *
+ * @param {Object} config.received.notifications
+ * The notifications that have been received.
+ */
+ register: function(config) {
+ var me = this;
+
+ if (!config.received) {
+ Ext.Logger.error('Failed to pass a received callback. This is required.');
+ }
+
+ if (!config.type) {
+ Ext.Logger.error('Failed to pass a type. This is required.');
+ }
+
+ return {
+ success: function(token) {
+ me.onSuccess(token, config.success, config.scope || me);
+ },
+ failure: function(error) {
+ me.onFailure(error, config.failure, config.scope || me);
+ },
+ received: function(notifications) {
+ me.onReceived(notifications, config.received, config.scope || me);
+ },
+ type: config.type
+ };
+ },
+
+ onSuccess: function(token, callback, scope) {
+ if (callback) {
+ callback.call(scope, token);
+ }
+ },
+
+ onFailure: function(error, callback, scope) {
+ if (callback) {
+ callback.call(scope, error);
+ }
+ },
+
+ onReceived: function(notifications, callback, scope) {
+ if (callback) {
+ callback.call(scope, notifications);
+ }
+ }
+});
View
22 device/push/Sencha.js
@@ -0,0 +1,22 @@
+/**
+ * @private
+ */
+Ext.define('Ext.device.push.Sencha', {
+ extend: 'Ext.device.push.Abstract',
+
+ register: function() {
+ var config = this.callParent(arguments);
+
+ Ext.apply(config, {
+ command: 'PushNotification#Register',
+ callbacks: {
+ success: config.success,
+ failure: config.failure,
+ received: config.received
+ },
+ type: config.type
+ });
+
+ Ext.device.Communicator.send(config);
+ }
+});
Please sign in to comment.
Something went wrong with that request. Please try again.