Source: app.js

/**
 * @module  app
 * @author 	Flavio De Stefano <flavio.destefano@caffeinalab.com>
 */

/**
 * @property config
 * @property {Boolean} [config.enqueueRouteWithUniversalLink=true] 	Auto enqueue route with Universal link
 * @property {Boolean} [config.enqueueRouteWithDeepLink=true] 			Auto enqueue route with deep link
 */
exports.config = _.extend({
	enqueueRouteWithUniversalLink: true,
	enqueueRouteWithDeepLink: true,
}, Alloy.CFG.T ? Alloy.CFG.T.app : {});

var Util = require('T/util');
var Router = require('T/router');

/**
 * A static method used to convert a Universal link to a route
 * With its default implementation, the original incoming string is return.
 * You can override this function to get a different behaviour
 * @param  {String} url The URL
 * @return {String} The route
 */
exports.universalLinkToRoute = function(url) { return url; };

/**
 * A static method used to convert a Deep link to a route
 * With its default implementation, the original incoming string is return
 * You can override this function to get a different behaviour
 * @param  {String} url The URL
 * @return {String} The route
 */
exports.deepLinkToRoute = function(url) { return url; };

/**
 * Check if the first opening of the app.  
 * Call {@link setFirstUse} to set the first use of the app.
 * @param {String} [prefix=""] A prefix to apply
 * @return {Boolean}
 */
exports.isFirstUse = function(prefix) {
	prefix = prefix || '';
	return !Ti.App.Properties.hasProperty('app.firstuse' + prefix);
};

/**
 * Set the app first usage date.
 * @param {String} [prefix=""] A prefix to apply
 * Use in conjunction with {@link isFirstUse}
 */
exports.setFirstUse = function(prefix) {
	prefix = prefix || '';
	Ti.App.Properties.setString('app.firstuse' + prefix, Util.now());
};

/**
 * Check on the App/Play store (or on a your distributed URL) if new version of this app has been released.
 * If it is, a dialog is shown to prompt the user for the update.
 * On iOS, all three parameters are auto-generated based on the app ID to check against the App Store.
 * On Android, there's no a reliable method to check this on the Play Store, so you have to 
 * specify it manually the URL (maybe on a server where you handle the current version) and the other two parameters.
 * For In-House applications or Development application, you have to do the same.
 * @param  {String} 		[url=null]					The URL to use to check for the update.
 * @param  {Function} 	[version_cb=null]			The function to call that handle the parsing of the response: it must returns the version.
 * @param  {Function} 	[success_cb=null]			The function to call when the user click: "Update"
 */
exports.notifyUpdate = function(url, version_cb, success_cb) {
	if (!Ti.Network.online) return;

	var HTTP = require('T/http');
	var Dialog = require('T/dialog');
	var GA = require('T/ga');

	if (url == null) {
		if (OS_IOS) {
			url = 'https://itunes.apple.com/lookup?bundleId=' + Ti.App.id;
		} else {
			return null;
		}
	}

	version_cb = version_cb || function(response) {
		if (OS_IOS) {
			return (response.results && response.results[0]) ? response.results[0].version : null;
		} else {
			return null;
		}
	};

	success_cb = success_cb || function(response) {
		Util.openInStore((function() {
			if (OS_IOS) return response.results[0].trackId;
			else return null;
		})() );
	};

	HTTP.send({
		url: url,
		cache: false,
		format: 'json',
		success: function(response) {
			if (response == null || !_.isObject(response)) return;

			var new_version = version_cb(response);
			var version_compare = Util.compareVersions(new_version, Ti.App.version);

			Ti.API.info('Util: App store version is ' + new_version);
			Ti.API.info('Util: Current version is ' + Ti.App.version);

			if (version_compare > 0) {
				var title = L('app_new_version_title', 'Update available');
				var message = String.format(L('app_new_version_message', 'A new version of %s is available: %s'), Ti.App.name, new_version);

				Dialog.confirm(title, message, [
				{
					title: L('app_new_version_button_later', 'Later'),
					callback: function() {
						GA.trackEvent('updatedialog', 'later');
					}
				},
				{
					title: L('app_new_version_button_update', 'Update'),
					preferred: true,
					callback: function() {
						GA.trackEvent('updatedialog', 'doit');
						success_cb(response);
					}
				}
				]);
			}
		}
	});
};


//////////
// Init //
//////////

if (OS_IOS) {

	if (exports.config.enqueueRouteWithDeepLink) {
		// The "resume" event is to handle all incoming deep links
		Ti.App.addEventListener('resumed', function() {
			var url = Util.parseSchema();
			Ti.API.info('App: Resumed with schema <' + url + '>');
			
			if (url != null) {
				Router.enqueue( exports.deepLinkToRoute(url) );
			}
		});
	}

	if (exports.config.enqueueRouteWithUniversalLink) {
		// This one "continueactivity.NSUserActivityTypeBrowsingWeb", handle Universal Links
		Ti.App.iOS.addEventListener('continueactivity', function(e) {
			if (e.activityType !== 'NSUserActivityTypeBrowsingWeb') return;
			
			if (e.webpageURL != null) {
				Router.enqueue( exports.universalLinkToRoute(e.webpageURL) );
			}
		});
	}

}

var url = Util.parseSchema();

if (url != null) {
	Ti.API.info('App: Started with schema <' + url + '>');

	if (exports.config.enqueueRouteWithDeepLink) {
		Router.enqueue( exports.deepLinkToRoute(url) );
	}
}