|
1 |
|
2 /*###################################################################### |
|
3 ### D A S C Y L L U S N A M E S P A C E |
|
4 ######################################################################*/ |
|
5 var D = { |
|
6 |
|
7 // Versions |
|
8 platform: Ti.getPlatform(), |
|
9 name: Ti.API.Application.getName(), |
|
10 version: Ti.API.Application.getVersion(), |
|
11 ti_version: Ti.getVersion(), |
|
12 architecture: Ti.Platform.getArchitecture(), |
|
13 |
|
14 // Declared windows, for easy referencing |
|
15 window: {}, |
|
16 |
|
17 // Very first run of Dasycllus? |
|
18 firstrun: false, |
|
19 |
|
20 // Persistent storage DB handle. |
|
21 db: null, |
|
22 |
|
23 // The current TF server we'll be connected to; |
|
24 // uri: http://localhost:8080/ |
|
25 // version: Thingfish 0.5.0 (build ...) |
|
26 // |
|
27 tf: null, |
|
28 |
|
29 |
|
30 // Open a handle to the local database, initializing it |
|
31 // if necessary and performing rudamentary upwards migrations. |
|
32 // |
|
33 initDB: function() { |
|
34 this.db = Ti.Database.openFile( |
|
35 Ti.Filesystem.getFile( |
|
36 Ti.Filesystem.getApplicationDataDirectory(), 'dascyllus.db' |
|
37 ) |
|
38 ); |
|
39 |
|
40 var rv = this.db.execute( 'PRAGMA user_version' ); |
|
41 var schema_version = parseInt( rv.fieldByName('user_version') ); |
|
42 |
|
43 var schemas_dir = Ti.Filesystem.getFile( |
|
44 Ti.Filesystem.getApplicationDirectory(), 'sql' ); |
|
45 var current_version = schemas_dir.getDirectoryListing().length; |
|
46 |
|
47 if ( schema_version == 0 ) { |
|
48 this.notify( 'Welcome!', 'Dascyllus defaults installed.' ); |
|
49 this.firstrun = true; |
|
50 } |
|
51 |
|
52 if ( schema_version != current_version ) { |
|
53 console.log( 'Dascyllus DB at version ' + schema_version + |
|
54 ', needs to be upgraded to ' + current_version + '.' ); |
|
55 |
|
56 while ( schema_version != current_version ) { |
|
57 var update_version = schema_version + 1; |
|
58 console.log( ' updating to version ' + update_version ); |
|
59 |
|
60 var line; |
|
61 var schema_file = Ti.Filesystem.getFileStream( |
|
62 Ti.Filesystem.getApplicationDirectory(), 'sql', update_version + '.sql' ); |
|
63 schema_file.open(); |
|
64 |
|
65 this.db.execute( 'BEGIN' ); |
|
66 while ( line = schema_file.readLine() ) this.db.execute( line.toString() ); |
|
67 |
|
68 this.db.execute( 'PRAGMA user_version = ' + update_version ); |
|
69 this.db.execute( 'COMMIT' ); |
|
70 |
|
71 schema_version = update_version; |
|
72 schema_file.close(); |
|
73 } |
|
74 } |
|
75 |
|
76 return this.db; |
|
77 }, |
|
78 |
|
79 |
|
80 // Return a preference's current value, or null if nonexistent. |
|
81 // |
|
82 getPref: function( pref ) { |
|
83 var row = this.db.execute( "SELECT val FROM prefs WHERE key=?", pref ); |
|
84 if ( ! row.isValidRow() ) return null; |
|
85 |
|
86 var value = row.fieldByName( 'val' ); |
|
87 row.close(); |
|
88 |
|
89 return value; |
|
90 }, |
|
91 |
|
92 |
|
93 // Return a preference's current value as a boolean. |
|
94 // |
|
95 getBoolPref: function( pref ) { |
|
96 return this.getPref( pref ) == '1' |
|
97 }, |
|
98 |
|
99 |
|
100 // Insert or update a preference value. |
|
101 // |
|
102 setPref: function( pref, value ) { |
|
103 this.db.execute( 'BEGIN' ); |
|
104 |
|
105 // Row already exists, remove it first. |
|
106 if ( this.getPref( pref ) != null ) |
|
107 this.db.execute( 'DELETE FROM prefs WHERE key=?', pref ); |
|
108 |
|
109 this.db.execute( 'INSERT INTO prefs VALUES ( ?, ? )', pref, value ); |
|
110 this.db.execute( 'COMMIT' ); |
|
111 }, |
|
112 |
|
113 |
|
114 // Set a bool preference value. |
|
115 // |
|
116 setBoolPref: function( pref, value ) { |
|
117 this.setPref( pref, (value ? '1' : '0') ); |
|
118 }, |
|
119 |
|
120 |
|
121 // Generic delayed callback that returns the timer handle. |
|
122 // |
|
123 delay: (function() { |
|
124 var timer = null; |
|
125 return function( callback, ms, clear_previous ) { |
|
126 if ( clear_previous) clearTimeout( timer ); |
|
127 timer = setTimeout( callback, ms ); |
|
128 return timer; |
|
129 }; |
|
130 })(), |
|
131 |
|
132 |
|
133 // Create and show a new notification. |
|
134 // |
|
135 notify: function( title, message, callback ) { |
|
136 if ( ! callback ) callback = function(){}; |
|
137 |
|
138 var notification = Ti.Notification.createNotification({ |
|
139 'title' : title, |
|
140 'message' : message, |
|
141 'timeout' : 10, |
|
142 'callback' : callback, |
|
143 }); |
|
144 |
|
145 notification.show(); |
|
146 return notification; |
|
147 }, |
|
148 |
|
149 |
|
150 // Attempt a connection to a remote Thingfish server, and |
|
151 // populate the D.tf variable. |
|
152 // |
|
153 checkServer: function( uri ) { |
|
154 this.tf = null; |
|
155 |
|
156 var serverOk = function( data, status, xhr ) { |
|
157 var info = xhr.getResponseHeader( 'x-thingfish' ); |
|
158 if ( info ) { |
|
159 D.tf = { |
|
160 uri: uri, |
|
161 version: data.version |
|
162 }; |
|
163 D.notify( 'Connected.', info ); |
|
164 } |
|
165 else { |
|
166 D.notify( 'Unable to connect.', 'Not a Thingfish server?' ); |
|
167 } |
|
168 }; |
|
169 |
|
170 $.ajax({ |
|
171 url: uri, |
|
172 sync: false, |
|
173 success: serverOk, |
|
174 error: function( xhr, status, err ) { |
|
175 D.notify( 'Unable to connect.', err ); |
|
176 }, |
|
177 dataType: 'json' |
|
178 }); |
|
179 }, |
|
180 |
|
181 |
|
182 // Build the main menu. |
|
183 // |
|
184 setupMenu: function() { |
|
185 var menu = Ti.UI.createMenu(); |
|
186 var yep = Ti.UI.createMenuItem( 'Yep' ); |
|
187 |
|
188 yep.addItem( 'About', function() { |
|
189 if ( D.window.about && D.window.about.isVisible() ) { |
|
190 D.window.about.focus(); |
|
191 } |
|
192 else { |
|
193 D.window.about = D.window.main.createWindow( 'app://window/about.html' ); |
|
194 D.window.about.setTopMost( true ); |
|
195 D.window.about.open(); |
|
196 } |
|
197 }); |
|
198 |
|
199 yep.addItem( 'Preferences', function() { |
|
200 if ( D.window.prefs && D.window.prefs.isVisible() ) { |
|
201 D.window.prefs.focus(); |
|
202 } |
|
203 else { |
|
204 D.window.prefs = D.window.main.createWindow( 'app://window/prefs.html' ); |
|
205 D.window.prefs.open(); |
|
206 } |
|
207 }); |
|
208 |
|
209 yep.addItem( 'Toggle Full Screen', function() { |
|
210 D.window.main.setFullscreen( ! D.window.main.isFullscreen() ); |
|
211 }); |
|
212 |
|
213 menu.appendItem( yep ); |
|
214 Ti.UI.setMenu( menu ); |
|
215 }, |
|
216 |
|
217 |
|
218 /*###################################################################### |
|
219 ### M O D E L S |
|
220 ######################################################################*/ |
|
221 |
|
222 // A Thingfish asset. |
|
223 // |
|
224 initModel: function() { |
|
225 D.Asset = can.Model({ |
|
226 id : 'oid', |
|
227 findAll: 'GET ' + D.tf.uri + '/', |
|
228 findOne: 'GET ' + D.tf.uri + '/{oid}', |
|
229 create : 'POST ' + D.tf.uri + '/', |
|
230 update : 'PUT ' + D.tf.uri + '/{oid}', |
|
231 destroy: 'DELETE ' + D.tf.uri + '/{oid}', |
|
232 |
|
233 // TODO: other metadata hooks? diff model? |
|
234 metadata: 'GET ' + D.tf.uri + '/{oid}/metadata', |
|
235 |
|
236 }, {}). |
|
237 bind( 'created', function( ev, asset ) { |
|
238 console.debug( "Created a new asset " + asset.id ); |
|
239 }). |
|
240 bind( 'updated', function( ev, asset ) { |
|
241 console.debug( "Updated asset " + asset.id ); |
|
242 }). |
|
243 bind( 'destroyed', function( ev, asset ) { |
|
244 console.debug( "Removed asset " + asset.id ); |
|
245 } |
|
246 ); |
|
247 }, |
|
248 }; |
|
249 |
|
250 |
|
251 // Initialization. |
|
252 // |
|
253 D.window.main = Ti.UI.getMainWindow(); |
|
254 D.setupMenu(); |
|
255 D.initDB(); |
|
256 |