d9b175b0c9f0baf4b79387bd4817a46c308730d8
[profile/ivi/Modello_Appmanager.git] / js / main.js
1 /*global Bootstrap, StoreLibrary, PackageRepository, packageRepository, template, Speech, AppModel, ThemeKeyColor, _applicationDetail, _categories, popularAppsModel, popularController */
2
3 /**
4  * Store application provides access to [remote package server](../../package_server/index.html) with installable WGT packages. Packages are grouped
5  * into package categories like *System*, *Utilities* or *Media*. Package server takes following information from WGT
6  * package `config.xml` file:
7  *
8  * * application icon
9  * * application name
10  * * application version
11  *
12  * Package server provides additional metadata processed by Store application:
13  *
14  * * application rating
15  * * category
16  * * application description
17  * * price for application
18  * * application screenshots
19  * * flag assigning application into Promoted and/or Popular groups
20  *
21  * Store application uses {{#crossLink "PackageRepository"}}{{/crossLink}} class to download, install and uninstall applications.
22  *
23  * Package server address and credentials can be configured by updating {{#crossLink "Store/Config:property"}}{{/crossLink}} property.
24  * Please refer to [Package server documenation](../../package_server/index.html) for more details.
25  *
26  * Hover and click on elements in images below to navigate to components of Store application.
27  *
28  * <img id="Image-Maps_1201312180420487" src="../assets/img/store.png" usemap="#Image-Maps_1201312180420487" border="0" width="649" height="1152" alt="" />
29  *   <map id="_Image-Maps_1201312180420487" name="Image-Maps_1201312180420487">
30  *     <area shape="rect" coords="0,0,573,78" href="../classes/TopBarIcons.html" alt="top bar icons" title="Top bar icons" />
31  *     <area shape="rect" coords="0,77,644,132" href="../classes/Clock.html" alt="clock" title="Clock"    />
32  *     <area shape="rect" coords="0,994,644,1147" href="../classes/BottomPanel.html" alt="bottom panel" title="Bottom panel" />
33  *     <area shape="rect" coords="573,1,644,76" href="../modules/Settings.html" alt="Settings" title="Settings" />
34  *     <area  shape="rect" coords="497,135,648,178" alt="Store Library" title="Store Library" target="_self" href="../classes/StoreLibrary.html"     >
35  *     <area  shape="rect" coords="0,476,648,1001" alt="Popular applications" title="Popular applications" target="_self" href="../classes/popularController.html"     >
36  *     <area  shape="rect" coords="1,188,648,457" alt="Promoted applications" title="Promoted applications" target="_self" href="../classes/Store.html#property_promotedApplicationsModel"     >
37  *   </map>
38  *
39  * @module StoreApplication
40  * @main StoreApplication
41  * @class Store
42  **/
43
44 var moved = false;
45
46 /**
47  * Configuration object holding url and authentication access to remote store server
48  * @property Config
49  * @static
50  **/
51 var Config = {
52         httpPrefix: "http://localhost:80",
53         username: "intel",
54         pwd: "TiZ3N456!",
55         defaultIcon: "css/car/images/default_icon.png"
56 };
57
58 /**
59  * Reference to instance of object holding data about promoted applications
60  * @property promotedApplicationsModel {Object}
61  */
62 var promotedApplicationsModel;
63
64 /**
65  * Object handling speech commands to install or uninstall application
66  * @property speechObj {Object}
67  */
68 var speechObj;
69
70 /**
71  * Object holding data about apps installed on the device
72  * @property installedApps {Object}
73  */
74 var installedApps;
75
76 var bootstrap;
77
78 /**
79  * Method fills Promoted Applications carousel with data and rendering
80  * @method setupCarousel
81  * @static
82  **/
83 function setupCarousel() {
84         "use strict";
85         template.compile(promotedApplicationsModel, "templates/carouselDelegate.html", "#carousel_wrap", function() {
86                 $('#carousel_wrap').carouFredSel({
87                         auto: false,
88                         width: 720,
89                         items: {
90                                 visible: 3
91                         },
92                         swipe: {
93                                 onMouse: true,
94                                 onTouch: true
95                         },
96                         scroll: {
97                                 items: 1
98                         }
99                 });
100
101                 $('.carouselItem').on("touchstart", function (event) {
102                         moved = false;
103                 });
104
105                 $('.carouselItem').on("touchmove", function (event) {
106                         moved = true;
107                 });
108         });
109 }
110
111 /**
112  * Function invoked after `touchend` event on the carousel item
113  * @method triggerTouchEnd
114  * @param cat {String} Category
115  * @param app {String} Application
116  * @static
117  **/
118 function triggerTouchEnd(cat, app) {
119         "use strict";
120         if (moved === false) {
121                 StoreLibrary.setAppDetailAndCategory(cat, app);
122         }
123 }
124
125 /**
126  * Adds http prefix to application icons' urls for apps from the store
127  * @method enhanceModelUrls
128  * @static
129  **/
130 function enhanceModelUrls(model) {
131         "use strict";
132         $.each(model, function (itemIndex, item) {
133                 if (item.iconUrl.indexOf(Config.httpPrefix) < 0) {
134                         item.iconUrl = Config.httpPrefix + item.iconUrl;
135                 }
136         });
137 }
138
139 /**
140  * Looks for application icon file and provides a path to default one if not found
141  * @method getAppIcon
142  * @static
143  **/
144 function getAppIcon(appIconPath, callback) {
145         "use strict";
146         try {
147                 tizen.filesystem.resolve(appIconPath, function (iconFile) {
148                         callback(iconFile.fullPath);
149                 }, function (error) {
150                         callback(Config.defaultIcon);
151                 });
152         } catch(ex) {
153                 console.log("EXCEPTION when trying to find icon file: " + ex.message);
154         }
155 }
156
157 /**
158  * Applies selected theme to application icons
159  * @method setThemeImageColor
160  * @static
161  **/
162 function setThemeImageColor() {
163         "use strict";
164         var imageSource;
165         $('body').find('img').each(function() {
166                 var self = this;
167                 imageSource = $(this).attr('src');
168
169                 if (typeof(imageSource) !== 'undefined' && $(this.parentElement).hasClass('themeImage') === false &&
170                         (imageSource.indexOf(Config.httpPrefix) >= 0 || imageSource.indexOf('base64') >= 0)) {
171                         var img = new Image();
172                         var ctx = document.createElement('canvas').getContext('2d');
173                         img.onload = function () {
174                                 var w = ctx.canvas.width = img.width;
175                                 var h = ctx.canvas.height = img.height;
176                                 ctx.fillStyle = ThemeKeyColor;
177                                 ctx.fillRect(0, 0, w, h);
178                                 ctx.globalCompositeOperation = 'destination-in';
179                                 ctx.drawImage(img, 0, 0);
180
181                                 $(self).attr('src', ctx.canvas.toDataURL());
182                                 $(self).hide(0, function() { $(self).show();});
183                         };
184
185                         img.src = imageSource;
186                 }
187         });
188 }
189
190 /**
191  * Sets up voice recognition listeners for un/installing applications
192  * @method setupSpeechRecognition
193  * @static
194  **/
195 function setupSpeechRecognition() {
196         "use strict";
197         console.log("Store setupSpeechRecognition");
198         Speech.addVoiceRecognitionListener({
199                 onapplicationinstall : function() {
200                         console.log("Speech application install invoked");
201                         if (_applicationDetail.id !== undefined && $('#storeLibrary').library('isVisible') &&
202                                 (!_applicationDetail.installed || _applicationDetail.installed === false)) {
203                                 StoreLibrary.installApp(_applicationDetail.id);
204                         }
205                 },
206                 onapplicationuninstall : function() {
207                         console.log("Speech application uninstall invoked");
208                         if (_applicationDetail.id !== undefined && $('#storeLibrary').library('isVisible') && _applicationDetail.installed === true) {
209                                 StoreLibrary.uninstallApp(_applicationDetail.id);
210                         }
211                 }
212
213         });
214 }
215
216 /**
217  * Applies Base64 conversion to icon urls in the model
218  * @method setThemeIconColorBeforeRender
219  * @static
220  **/
221 function setThemeIconColorBeforeRender(model) {
222         "use strict";
223         if (!!model) {
224                 $.each(model, function (itemIndex, item) {
225                         if (item.iconUrl.indexOf(Config.httpPrefix) >= 0 || item.iconUrl.indexOf('base64') >= 0 || item.iconUrl.indexOf('intelPoc') >= 0) {
226                                 var img = new Image();
227                                 var aIcon = item.iconUrl;
228                                 var ctx = document.createElement('canvas').getContext('2d');
229                                 img.onload = function () {
230                                         var w = ctx.canvas.width = img.width;
231                                         var h = ctx.canvas.height = img.height;
232                                         ctx.fillStyle = ThemeKeyColor;
233                                         ctx.fillRect(0, 0, w, h);
234                                         ctx.globalCompositeOperation = 'destination-in';
235                                         ctx.drawImage(img, 0, 0);
236                                         item.iconUrl = ctx.canvas.toDataURL();
237                                 };
238
239                                 img.src = item.iconUrl;
240                         }
241                 });
242         }
243 }
244
245 /**
246  * Loads store data and builds the page based on the data
247  * @method loadUi
248  * @static
249  **/
250 function loadUi() {
251         "use strict";
252         var self;
253         packageRepository = new PackageRepository();
254         packageRepository.availableApplications(function (appData) {
255                 AppModel = appData;
256                 enhanceModelUrls(AppModel);
257                 setThemeIconColorBeforeRender(AppModel);
258
259                 promotedApplicationsModel = packageRepository.getPromotedApplications();
260                 setTimeout(function() {
261                         setupCarousel();
262
263                         packageRepository.getAppsInfo(function (appsInfo) {
264                                 installedApps = appsInfo;
265                                 var appsNotInStore = [];
266                                 var foundInStore = false;
267                                 var appsLength = appsInfo.length;
268                                 var appModelLength = AppModel.length;
269
270                                 var processApplication = function(i) {
271                                         for (var j = 0; j < appModelLength; j++) {
272                                                 if (appsInfo[i].name === AppModel[j].name) {
273                                                         foundInStore = true;
274                                                         AppModel[j].installed = true;
275
276                                                         break;
277                                                 } else if (!AppModel[j].installed) {
278                                                         AppModel[j].installed = false;
279                                                 }
280                                         }
281                                         if (foundInStore === false &&
282                                                 (appsInfo[i].name.toLowerCase() !== "store" && appsInfo[i].name.toLowerCase() !== "homescreen" && appsInfo[i].name.toLowerCase() !== "home screen")) {
283                                                 var appNotInStore = {};
284                                                 appNotInStore.id = appsInfo[i].id;
285                                                 appNotInStore.name = appsInfo[i].name;
286                                                 appNotInStore.version = 0;
287                                                 appNotInStore.silentInstall = false;
288                                                 /* jshint camelcase: false */
289                                                 appNotInStore.category_id = "system";
290                                                 /* jshint camelcase: true */
291                                                 appNotInStore.price = "0";
292                                                 appNotInStore.rating = "0";
293                                                 appNotInStore.description = "";
294                                                 appNotInStore.isPromoted = false;
295                                                 appNotInStore.isPopular = false;
296                                                 appNotInStore.screenshots = [];
297                                                 appNotInStore.downloadUrl = "";
298                                                 getAppIcon(appsInfo[i].iconPath, function(resolvedPath) {
299                                                         appNotInStore.iconUrl = resolvedPath;
300                                                 });
301                                                 appNotInStore.installed = true;
302                                                 AppModel.push(appNotInStore);
303                                         }
304                                         foundInStore = false;
305                                 };
306
307                                 for (var i = 0; i < appsLength; i++) {
308                                         processApplication(i);
309                                 }
310                                 popularAppsModel = packageRepository.getPopularApplications();
311                                 popularController.addHeader();
312                                 popularController.fillView(popularAppsModel);
313                         });
314
315                 },500);
316         }, function() {
317                         packageRepository.getAppsInfo(function (appsInfo) {
318                                 installedApps = appsInfo;
319                                 var appsNotInStore = [];
320                                 var appsLength = appsInfo.length;
321
322                                 var processApplication = function(i) {
323                                         if (appsInfo[i].name.toLowerCase() !== "store" && appsInfo[i].name.toLowerCase() !== "homescreen" && appsInfo[i].name.toLowerCase() !== "home screen") {
324                                                 var appNotInStore = {};
325                                                 appNotInStore.id = appsInfo[i].id;
326                                                 appNotInStore.name = appsInfo[i].name;
327                                                 appNotInStore.version = 0;
328                                                 appNotInStore.silentInstall = false;
329                                                 /* jshint camelcase: false */
330                                                 appNotInStore.category_id = "system";
331                                                 /* jshint camelcase: true */
332                                                 appNotInStore.price = "0";
333                                                 appNotInStore.rating = "0";
334                                                 appNotInStore.description = "";
335                                                 appNotInStore.isPromoted = false;
336                                                 appNotInStore.isPopular = false;
337                                                 appNotInStore.screenshots = [];
338                                                 appNotInStore.downloadUrl = "";
339                                                 getAppIcon(appsInfo[i].iconPath, function(resolvedPath) {
340                                                         appNotInStore.iconUrl = resolvedPath;
341                                                 });
342                                                 appNotInStore.installed = true;
343                                                 AppModel.push(appNotInStore);
344                                         }
345                                 };
346
347                                 for (var i = 0; i < appsLength; i++) {
348                                         processApplication(i);
349                                 }
350                         });
351         });
352         packageRepository.getCategories(function (catData) {
353                 _categories = catData;
354         });
355
356 }
357
358 /**
359  * Initialize plugins and register events for Store app.
360  * @method init
361  * @static
362  **/
363 var init = function () {
364         "use strict";
365         bootstrap = new Bootstrap(function (status) {
366                 $("#topBarIcons").topBarIconsPlugin('init', 'store');
367                 $("#clockElement").ClockPlugin('init', 5);
368                 $("#clockElement").ClockPlugin('startTimer');
369                 $('#bottomPanel').bottomPanel('init');
370
371                 loadUi();
372                 if (tizen.speech) {
373                         setupSpeechRecognition();
374                 } else {
375                         console.log("Store: Speech Recognition not running, voice control will be unavailable");
376                 }
377
378                 bootstrap.themeEngine.addStatusListener(function (eData) {
379                         setThemeImageColor();
380                 });
381         });
382 };
383
384 $(document).ready(init);
385
386 /**
387  * Opens store library after it's initialization or initialize library if it's not.
388  * @method openStoreLibrary
389  * @static
390  **/
391 function openStoreLibrary() {
392         "use strict";
393         if (!StoreLibrary.initialized) {
394                 StoreLibrary.init();
395         } else {
396                 StoreLibrary.show();
397         }
398         setThemeIconColorBeforeRender(AppModel);
399 }