Resources/js/d/dascyllus.js
author Mahlon E. Smith <mahlon@martini.nu>
Mon, 02 Sep 2013 02:22:21 -0700
changeset 0 80c32ef237c6
child 1 b3419d05eabb
permissions -rw-r--r--
Initial commit.


/*######################################################################
### D A S C Y L L U S   N A M E S P A C E
######################################################################*/
var D = {

	// Versions
	platform:     Ti.getPlatform(),
	name:         Ti.API.Application.getName(),
	version:      Ti.API.Application.getVersion(),
	ti_version:   Ti.getVersion(),
	architecture: Ti.Platform.getArchitecture(),

	// Declared windows, for easy referencing
	window: {},

	// Very first run of Dasycllus?
	firstrun: false,

	// Persistent storage DB handle.
	db: null,

	// The current TF server we'll be connected to;
	//     uri: http://localhost:8080/
	//     version: Thingfish 0.5.0 (build ...)
	//
	tf: null,


	// Open a handle to the local database, initializing it
	// if necessary and performing rudamentary upwards migrations.
	//
	initDB: function() {
		this.db = Ti.Database.openFile(
			Ti.Filesystem.getFile(
				Ti.Filesystem.getApplicationDataDirectory(), 'dascyllus.db'
			)
		);

		var rv = this.db.execute( 'PRAGMA user_version' );
		var schema_version = parseInt( rv.fieldByName('user_version') );

		var schemas_dir = Ti.Filesystem.getFile(
				Ti.Filesystem.getApplicationDirectory(), 'sql' );
		var current_version = schemas_dir.getDirectoryListing().length;

		if ( schema_version == 0 ) {
			this.notify( 'Welcome!', 'Dascyllus defaults installed.' );
			this.firstrun = true;
		}

		if ( schema_version != current_version ) {
			console.log( 'Dascyllus DB at version ' + schema_version +
					', needs to be upgraded to ' + current_version + '.' );

			while ( schema_version != current_version ) {
				var update_version = schema_version + 1;
				console.log( '  updating to version ' + update_version );

				var line;
				var schema_file = Ti.Filesystem.getFileStream(
						Ti.Filesystem.getApplicationDirectory(), 'sql', update_version + '.sql' );
				schema_file.open();

				this.db.execute( 'BEGIN' );
				while ( line = schema_file.readLine() ) this.db.execute( line.toString() );

				this.db.execute( 'PRAGMA user_version = ' + update_version  );
				this.db.execute( 'COMMIT' );

				schema_version = update_version;
				schema_file.close();
			}
		}

		return this.db;
	},


	// Return a preference's current value, or null if nonexistent.
	//
	getPref: function( pref ) {
		var row = this.db.execute( "SELECT val FROM prefs WHERE key=?", pref );
		if ( ! row.isValidRow() ) return null;

		var value = row.fieldByName( 'val' );
		row.close();

		return value;
	},


	// Return a preference's current value as a boolean.
	//
	getBoolPref: function( pref ) {
		return this.getPref( pref ) == '1'
	},


	// Insert or update a preference value.
	//
	setPref: function( pref, value ) {
		this.db.execute( 'BEGIN' );

		// Row already exists, remove it first.
		if ( this.getPref( pref ) != null )
			this.db.execute( 'DELETE FROM prefs WHERE key=?', pref );

		this.db.execute( 'INSERT INTO prefs VALUES ( ?, ? )', pref, value );
		this.db.execute( 'COMMIT' );
	},


	// Set a bool preference value.
	//
	setBoolPref: function( pref, value ) {
		this.setPref( pref, (value ? '1' : '0') );
	},


	// Generic delayed callback that returns the timer handle.
	//
	delay: (function() {
		var timer = null;
		return function( callback, ms, clear_previous ) {
			if ( clear_previous) clearTimeout( timer );
			timer = setTimeout( callback, ms );
			return timer;
		};
	})(),


	// Create and show a new notification.
	//
	notify: function( title, message, callback ) {
		if ( ! callback ) callback = function(){};

		var notification = Ti.Notification.createNotification({
			'title' : title,
			'message' : message,
			'timeout' : 10,
			'callback' : callback,
		});

		notification.show();
		return notification;
	},


	// Attempt a connection to a remote Thingfish server, and
	// populate the D.tf variable.
	//
	checkServer: function( uri ) {
		this.tf = null;

		var serverOk = function( data, status, xhr ) {
			var info = xhr.getResponseHeader( 'x-thingfish' );
			if ( info ) {
				D.tf = {
					uri: uri,
					version: data.version
				};
				D.notify( 'Connected.', info );
			}
			else {
				D.notify( 'Unable to connect.', 'Not a Thingfish server?' );
			}
		};

		$.ajax({
			url:      uri,
			sync:     false,
			success:  serverOk,
			error:    function( xhr, status, err ) {
				D.notify( 'Unable to connect.', err );
			},
			dataType: 'json'
		});
	},


	// Build the main menu.
	//
	setupMenu: function() {
		var menu  = Ti.UI.createMenu();
		var yep   = Ti.UI.createMenuItem( 'Yep' );

		yep.addItem( 'About', function() {
			if ( D.window.about && D.window.about.isVisible() ) {
				D.window.about.focus();
			}
			else {
				D.window.about = D.window.main.createWindow( 'app://window/about.html' );
				D.window.about.setTopMost( true );
				D.window.about.open();
			}
		});

		yep.addItem( 'Preferences', function() {
			if ( D.window.prefs && D.window.prefs.isVisible() ) {
				D.window.prefs.focus();
			}
			else {
				D.window.prefs = D.window.main.createWindow( 'app://window/prefs.html' );
				D.window.prefs.open();
			}
		});

		yep.addItem( 'Toggle Full Screen', function() {
			D.window.main.setFullscreen( ! D.window.main.isFullscreen() );
		});

		menu.appendItem( yep );
		Ti.UI.setMenu( menu );
	},


	/*######################################################################
	### M O D E L S
	######################################################################*/

	// A Thingfish asset.
	//
	initModel: function() {
		D.Asset = can.Model({
			id     : 'oid',
			findAll: 'GET '    + D.tf.uri + '/',
			findOne: 'GET '    + D.tf.uri + '/{oid}',
			create : 'POST '   + D.tf.uri + '/',
			update : 'PUT '    + D.tf.uri + '/{oid}',
			destroy: 'DELETE ' + D.tf.uri + '/{oid}',

			// TODO: other metadata hooks?  diff model?
			metadata: 'GET ' + D.tf.uri + '/{oid}/metadata',

		}, {}).
			bind( 'created', function( ev, asset ) {
				console.debug( "Created a new asset " + asset.id );
			}).
			bind( 'updated', function( ev, asset ) {
				console.debug( "Updated asset " + asset.id );
			}).
			bind( 'destroyed', function( ev, asset ) {
				console.debug( "Removed asset " + asset.id );
			}
		);
	},
};


// Initialization.
//
D.window.main = Ti.UI.getMainWindow();
D.setupMenu();
D.initDB();