not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

872 lines
27 KiB

  1. // Sugar Libraries (initialized by require)
  2. var app = null;
  3. var toolbar = null;
  4. var mouse = {position: {x: -1, y: -1}};
  5. var isFirstLaunch = false;
  6. var iconLib;
  7. var xoPalette;
  8. var radioButtonsGroup;
  9. var datastore;
  10. var presence;
  11. var l10n;
  12. var preferences;
  13. var util;
  14. var myserver;
  15. var humane;
  16. var tutorial;
  17. var stats;
  18. var autosync;
  19. // Main app class
  20. enyo.kind({
  21. name: "Sugar.Desktop",
  22. kind: enyo.Control,
  23. components: [
  24. {name: "owner", kind: "Sugar.Icon", size: constant.sizeOwner, colorized: true, classes: "owner-icon", showing: false},
  25. {name: "journal", kind: "Sugar.Icon", size: constant.sizeJournal, ontap: "showJournal", classes: "journal-icon", showing: false},
  26. {name: "desktop", showing: true, onresize: "resize", components: []},
  27. {name: "otherview", showing: true, components: []},
  28. {name: "activityPopup", kind: "Sugar.Popup", showing: false},
  29. {name: "activities", kind: "enyo.WebService", onResponse: "queryActivitiesResponse", onError: "queryActivitiesFail"}
  30. ],
  31. // Constructor
  32. create: function() {
  33. // Init screen
  34. app = this;
  35. this.inherited(arguments);
  36. this.timer = null;
  37. this.otherview = null;
  38. this.toolbar = null;
  39. util.setToolbar(this.getToolbar());
  40. this.$.owner.setIcon({directory: "icons", icon: "owner-icon.svg"});
  41. this.$.owner.setPopupShow(enyo.bind(this, "showBuddyPopup"));
  42. this.$.owner.setPopupHide(enyo.bind(this, "hideBuddyPopup"));
  43. this.$.journal.setIcon({directory: "icons", icon: "activity-journal.svg"});
  44. this.restrictedModeInfo = { start: 0 };
  45. util.hideNativeToolbar();
  46. this.tutorialActivity = null;
  47. // Load and sort journal
  48. this.loadJournal();
  49. this.isJournalFull = false;
  50. this.testJournalSize();
  51. // Call activities list service
  52. if (util.getClientType() == constant.webAppType) {
  53. this.$.activities.setUrl(myserver.getActivitiesUrl());
  54. myserver.getActivities(enyo.bind(this, "queryActivitiesResponse"), enyo.bind(this, "queryActivitiesFail"));
  55. } else {
  56. this.$.activities.setUrl(constant.staticInitActivitiesURL);
  57. this.$.activities.send();
  58. }
  59. // Check change on preferences from server
  60. var isConnected = preferences.isConnected();
  61. this.getToolbar().showServerWarning(!isConnected);
  62. if (isConnected) {
  63. var that = this;
  64. this.connectToServer(function(success) {
  65. if (that.getToolbar() && that.getToolbar().showServerWarning) {
  66. that.getToolbar().showServerWarning(!success);
  67. }
  68. });
  69. } else {
  70. util.updateFavicon();
  71. }
  72. // Launch tutorial at first launch
  73. var that = this;
  74. window.setTimeout(function() {
  75. if (isFirstLaunch) {
  76. that.getToolbar().startTutorial();
  77. }
  78. }, constant.timerBeforeTutorial);
  79. },
  80. // Load and sort journal
  81. loadJournal: function() {
  82. this.journal = datastore.find();
  83. this.journal = this.journal.sort(function(e0, e1) {
  84. return parseInt(e1.metadata.timestamp) - parseInt(e0.metadata.timestamp);
  85. });
  86. },
  87. // Test Journal size to ensure it's not full
  88. testJournalSize: function() {
  89. this.isJournalFull = false;
  90. var that = this;
  91. util.computeDatastoreSize(function(size) {
  92. var percentremain = ((size.remain/size.total)*100);
  93. if (percentremain < constant.minStorageSizePercent) {
  94. console.log("WARNING: Journal almost full");
  95. that.isJournalFull = true;
  96. }
  97. });
  98. },
  99. // Init activities service response, redraw screen
  100. queryActivitiesResponse: function(inSender, inResponse) {
  101. // No activities at start
  102. if (preferences.getActivities() == null) {
  103. // Just copy the activities from the service
  104. preferences.setActivities(inResponse.data);
  105. preferences.save();
  106. } else {
  107. // Update with new activities
  108. if (preferences.updateActivities(inResponse.data)) {
  109. preferences.save();
  110. }
  111. }
  112. preferences.updateEntries();
  113. // If we are in the SugarizerOS environment, load the android apps into activities
  114. if (window.sugarizerOS){
  115. var t = this;
  116. sugarizerOS.isAppCacheReady(function(response) {
  117. if (!response.ready) {
  118. var loading = humane.create({timeout: 5000, baseCls: "humane-libnotify"});
  119. loading.log(l10n.get("Loading"));
  120. }
  121. });
  122. sugarizerOS.initActivitiesPreferences(function(){t.init();});
  123. sugarizerOS.isWifiEnabled(function(value){
  124. if (value != 0) {
  125. sugarizerOS.scanWifi();
  126. }
  127. });
  128. sugarizerOS.popupTimer = 0;
  129. if (sugarizerOS.launches == 2 && sugarizerOS.launcherPackageName != sugarizerOS.packageName &&
  130. !sugarizerOS.isSetup){
  131. this.doResetLauncher();
  132. sugarizerOS.putInt("IS_SETUP", 1);
  133. }
  134. }
  135. else {
  136. this.init();
  137. }
  138. },
  139. // Error on init activities
  140. queryActivitiesFail: function(inSender, inError) {
  141. // Dynamic don't work try static list
  142. if (this.$.activities.getUrl().indexOf(constant.dynamicInitActivitiesURL) != -1) {
  143. console.log("WARNING: Backoffice not responding, use static list");
  144. this.$.activities.setUrl(constant.staticInitActivitiesURL);
  145. this.$.activities.send();
  146. }
  147. // Unable to load
  148. else {
  149. console.log("Error loading init activities");
  150. }
  151. },
  152. // Try to connect to the server: update preferences, sync journal, ...
  153. connectToServer: function(callback) {
  154. var networkId = preferences.getNetworkId();
  155. var that = this;
  156. myserver.getUser(
  157. networkId,
  158. function(inSender, inResponse) {
  159. var changed = preferences.merge(inResponse);
  160. util.updateFavicon();
  161. if (changed) {
  162. preferences.save();
  163. util.restartApp();
  164. } else if (that.currentView == constant.journalView) {
  165. that.otherview.updateNetworkBar();
  166. }
  167. presence.joinNetwork(function (error, user) {
  168. if (error) {
  169. console.log("WARNING: Can't connect to presence server");
  170. }
  171. });
  172. callback(true);
  173. autosync.synchronizeJournal(
  174. function(count) {
  175. if (count) {
  176. setTimeout(function() {
  177. var message = l10n.get("RetrievingJournal");
  178. if (message) humane.log(message);
  179. }, 100);
  180. var toolbar = that.getToolbar();
  181. if (toolbar.showSync) {
  182. toolbar.showSync(true);
  183. }
  184. }
  185. },
  186. function(locale, remote, error) {
  187. var toolbar = that.getToolbar();
  188. if (toolbar.showSync) {
  189. toolbar.showSync(false);
  190. }
  191. // Locale journal has changed, update display
  192. if (locale && !error) {
  193. that.loadJournal();
  194. that.testJournalSize();
  195. preferences.updateEntries();
  196. that.draw();
  197. that.render();
  198. }
  199. }
  200. );
  201. },
  202. function() {
  203. console.log("WARNING: Can't read network user settings");
  204. callback(false);
  205. }
  206. );
  207. },
  208. // Get linked toolbar
  209. getToolbar: function() {
  210. if (this.toolbar == null) {
  211. this.toolbar = new Sugar.DesktopToolbar();
  212. }
  213. if (this.currentView != constant.listView && this.otherview != null) {
  214. return this.otherview.getToolbar();
  215. }
  216. return this.toolbar;
  217. },
  218. // Get linked popup
  219. getPopup: function() {
  220. return this.$.activityPopup;
  221. },
  222. // Init desktop
  223. init: function() {
  224. this.currentView = constant.radialView;
  225. if (preferences.getView()) {
  226. this.showView(preferences.getView());
  227. }
  228. this.draw();
  229. },
  230. localize: function() {
  231. if (this.otherview && this.otherview.localize) {
  232. this.otherview.localize();
  233. }
  234. },
  235. // Draw desktop
  236. draw: function() {
  237. // Clean desktop
  238. var items = [];
  239. enyo.forEach(this.$.desktop.getControls(), function(item) { items.push(item); });
  240. for (var i = 0 ; i < items.length ; i++) { items[i].destroy(); };
  241. this.tutorialActivity = null;
  242. // Compute center and radius
  243. var canvas_center = util.getCanvasCenter();
  244. var icon_size = constant.iconSizeStandard;
  245. var icon_padding = icon_size*constant.iconSpacingFactor;
  246. var semi_size = icon_size/2;
  247. var jdeltay = (canvas_center.dy < 480) ? -12 : 0;
  248. // Draw XO owner
  249. this.$.owner.applyStyle("margin-left", (canvas_center.x-constant.sizeOwner/2)+"px");
  250. this.$.owner.applyStyle("margin-top", (canvas_center.y-constant.sizeOwner/2)+"px");
  251. this.$.journal.setColorized(this.journal.length > 0);
  252. this.$.journal.applyStyle("margin-left", (canvas_center.x-constant.sizeJournal/2)+"px");
  253. this.$.journal.applyStyle("margin-top", (canvas_center.y+constant.sizeOwner-constant.sizeJournal+jdeltay)+"px");
  254. this.$.owner.setShowing(this.currentView == constant.radialView);
  255. this.$.journal.setShowing(this.currentView == constant.radialView);
  256. // Compute ring size and shape
  257. var activitiesList = preferences.getFavoritesActivities();
  258. var activitiesCount = activitiesList.length;
  259. var activitiesIndex = 0;
  260. var radiusx, radiusy, base_angle, spiralMode, restrictedMode;
  261. var PI2 = Math.PI*2.0;
  262. radiusx = radiusy = Math.max(constant.ringMinRadiusSize, Math.min(canvas_center.x-icon_size,canvas_center.y-icon_size));
  263. var circumference = PI2*radiusx;
  264. if ((circumference/activitiesList.length) >= constant.iconSpacingFactor*icon_padding) {
  265. spiralMode = restrictedMode = false;
  266. base_angle = (PI2/parseFloat(activitiesList.length));
  267. } else {
  268. if (this.hasRoomForSpiral(canvas_center, icon_padding)) {
  269. spiralMode = true; restrictedMode = false;
  270. radiusx = radiusy = icon_padding*constant.ringInitSpaceFactor;
  271. activitiesCount = parseInt((PI2*radiusx)/icon_padding);
  272. base_angle = PI2/activitiesCount;
  273. } else {
  274. restrictedMode = true; spiralMode = false;
  275. activitiesCount = parseInt(circumference/icon_padding)-1;
  276. this.restrictedModeInfo.count = activitiesCount;
  277. this.restrictedModeInfo.length = activitiesList.length;
  278. base_angle = (PI2/parseFloat(activitiesCount+1));
  279. }
  280. }
  281. // Draw activity icons
  282. var angle = -Math.PI/2.0-base_angle;
  283. for (var i = 0 ; i < activitiesList.length ; i++) {
  284. // Compute icon position
  285. var activity = activitiesList[i];
  286. var ix, iy;
  287. var previousAngle = angle;
  288. if (!spiralMode) {
  289. angle += base_angle;
  290. ix = (canvas_center.x+Math.cos(angle)*radiusx-semi_size);
  291. iy = (canvas_center.y+Math.sin(angle)*radiusy-semi_size);
  292. } else {
  293. angle += base_angle;
  294. if (activitiesIndex >= activitiesCount) {
  295. radiusx = radiusy = radiusx + icon_padding*constant.ringSpaceFactor;
  296. activitiesCount = parseInt((PI2*radiusx)/icon_padding);
  297. activitiesIndex = 0;
  298. angle -= (base_angle/constant.ringAdjustAngleFactor);
  299. base_angle = PI2/activitiesCount;
  300. }
  301. var delta = (icon_padding*constant.ringAdjustSizeFactor)/(activitiesCount-activitiesIndex);
  302. ix = (canvas_center.x+Math.cos(angle)*(radiusx+delta)-semi_size);
  303. iy = (canvas_center.y+Math.sin(angle)*(radiusy+delta)-semi_size);
  304. }
  305. // Restricted mode for small device: integrate a way to scroll on the circle
  306. if (restrictedMode) {
  307. if (i < this.restrictedModeInfo.start) {
  308. angle = previousAngle;
  309. continue;
  310. } else if (i > 0 && i == this.restrictedModeInfo.start) {
  311. this.$.desktop.createComponent({
  312. kind: "Sugar.Icon",
  313. icon: {directory: "icons", icon: "activity-etc.svg", name: l10n.get("ListView")},
  314. size: icon_size,
  315. x: ix,
  316. y: iy,
  317. ontap: "showPreviousRestrictedList"
  318. },
  319. {owner: this}).render();
  320. continue;
  321. } else if (i >= this.restrictedModeInfo.start+activitiesCount-1 && this.restrictedModeInfo.start + activitiesCount < activitiesList.length) {
  322. this.$.desktop.createComponent({
  323. kind: "Sugar.Icon",
  324. icon: {directory: "icons", icon: "activity-etc.svg", name: l10n.get("ListView")},
  325. size: icon_size,
  326. x: ix,
  327. y: iy,
  328. ontap: "showNextRestrictedList"
  329. },
  330. {owner: this}).render();
  331. break;
  332. }
  333. }
  334. // Draw icon
  335. if (activity.type != null && activity.type == "native") {
  336. activity.isNative = true;
  337. }
  338. var newIcon = this.$.desktop.createComponent({
  339. kind: "Sugar.Icon",
  340. icon: activity, // HACK: Icon characteristics are embedded in activity object
  341. size: icon_size,
  342. x: ix,
  343. y: iy,
  344. colorized: activity.instances !== undefined && activity.instances.length > 0,
  345. colorizedColor: (activity.instances !== undefined && activity.instances.length > 0 && activity.instances[0].metadata.buddy_color) ? activity.instances[0].metadata.buddy_color : null,
  346. ontap: "runMatchingActivity",
  347. popupShow: enyo.bind(this, "showActivityPopup"),
  348. popupHide: enyo.bind(this, "hideActivityPopup")
  349. },
  350. {owner: this}
  351. );
  352. newIcon.render();
  353. activitiesIndex++;
  354. // Set tutorial
  355. if (!this.tutorialActivity) {
  356. this.tutorialActivity = newIcon;
  357. }
  358. }
  359. },
  360. // Redraw, for example after a resized event
  361. redraw: function() {
  362. this.draw();
  363. if (this.currentView == constant.radialView || this.currentView == constant.listView) {
  364. this.filterActivities();
  365. }
  366. this.render();
  367. },
  368. resize: function() {
  369. if (this.noresize) {
  370. return;
  371. }
  372. this.redraw();
  373. },
  374. hasRoomForSpiral: function(canvas_center, icon_padding) {
  375. var activitiesList = preferences.getFavoritesActivities();
  376. var activitiesCount = activitiesList.length;
  377. var radius = icon_padding*constant.ringInitSpaceFactor;
  378. while (activitiesCount > 0) {
  379. activitiesCount -= parseInt(((Math.PI*2.0)*radius)/icon_padding);
  380. radius += icon_padding*constant.ringSpaceFactor;
  381. }
  382. radius -= (icon_padding/2.0);
  383. var diameter = radius*2;
  384. return (diameter <= canvas_center.dx && diameter <= canvas_center.dy);
  385. },
  386. showPreviousRestrictedList: function() {
  387. this.getPopup().hidePopup();
  388. var newStart = this.restrictedModeInfo.start - this.restrictedModeInfo.count;
  389. if (newStart < 0) {
  390. newStart = 0;
  391. }
  392. this.restrictedModeInfo.start = newStart;
  393. this.draw();
  394. },
  395. showNextRestrictedList: function() {
  396. this.getPopup().hidePopup();
  397. var newStart = this.restrictedModeInfo.start + this.restrictedModeInfo.count - 2;
  398. if (newStart > this.restrictedModeInfo.length-1) {
  399. return;
  400. } else if (newStart+this.restrictedModeInfo.count > this.restrictedModeInfo.length) {
  401. newStart = this.restrictedModeInfo.length - this.restrictedModeInfo.count;
  402. }
  403. this.restrictedModeInfo.start = newStart;
  404. this.draw();
  405. },
  406. // Switch between radial and other views (list or journal)
  407. showView: function(newView) {
  408. if (this.currentView == newView) {
  409. return;
  410. }
  411. var oldView = this.currentView;
  412. this.currentView = newView;
  413. stats.trace(constant.viewNames[oldView], 'change_view', constant.viewNames[newView]);
  414. // Show desktop
  415. if (newView == constant.radialView) {
  416. this.otherview = null;
  417. util.setToolbar(this.getToolbar());
  418. toolbar.setActiveView(constant.radialView);
  419. this.$.otherview.hide();
  420. this.$.desktop.show();
  421. this.$.owner.show();
  422. this.$.journal.show();
  423. this.clearView();
  424. return;
  425. }
  426. // Hide desktop
  427. this.$.owner.hide();
  428. this.$.journal.hide();
  429. this.$.desktop.hide();
  430. this.clearView();
  431. // Show list
  432. if (newView == constant.listView) {
  433. util.setToolbar(this.getToolbar());
  434. var filter = toolbar.getSearchText().toLowerCase();
  435. toolbar.setActiveView(constant.listView);
  436. this.otherview = this.$.otherview.createComponent({kind: "Sugar.DesktopListView", activities: preferences.getActivitiesByName(filter)});
  437. }
  438. // Show journal
  439. else if (newView == constant.journalView) {
  440. if (this.timer != null) {
  441. this.getPopup().hidePopup();
  442. window.clearInterval(this.timer);
  443. }
  444. this.otherview = this.$.otherview.createComponent({kind: "Sugar.Journal", journal: this.journal});
  445. util.setToolbar(this.otherview.getToolbar());
  446. }
  447. // Show neighborhood
  448. else if (newView == constant.neighborhoodView) {
  449. this.otherview = this.$.otherview.createComponent({kind: "Sugar.NeighborhoodView"});
  450. toolbar.setActiveView(constant.neighborhoodView);
  451. util.setToolbar(this.otherview.getToolbar());
  452. }
  453. this.$.otherview.show();
  454. this.$.otherview.render();
  455. },
  456. getView: function() {
  457. return this.currentView;
  458. },
  459. clearView: function() {
  460. var controls = this.$.otherview.getControls();
  461. for (var i = 0, c; c = controls[i]; i++) c.destroy();
  462. },
  463. showListView: function() {
  464. this.showView(constant.listView);
  465. },
  466. // Render
  467. rendered: function() {
  468. this.inherited(arguments);
  469. this.$.owner.colorize(preferences.getColor());
  470. if (this.journal.length > 0) {
  471. this.$.journal.colorize(preferences.getColor());
  472. }
  473. if (this.isJournalFull && l10n.get("JournalAlmostFull")) {
  474. humane.log(l10n.get("JournalAlmostFull"));
  475. this.isJournalFull = false;
  476. }
  477. },
  478. // Initialize information for tutorial
  479. beforeHelp: function() {
  480. tutorial.setElement("owner", app.$.owner.getAttribute("id"));
  481. tutorial.setElement("journal", app.$.journal.getAttribute("id"));
  482. if (this.tutorialActivity) {
  483. tutorial.setElement("activity", this.tutorialActivity.getAttribute("id"));
  484. }
  485. },
  486. // Run activity
  487. runMatchingActivity: function(icon) {
  488. if (!icon.getDisabled() && !this.getPopup().showing){
  489. this.hideActivityPopup(icon);
  490. util.vibrate();
  491. this.runActivity(icon.icon);
  492. }
  493. },
  494. runActivity: function(activity) {
  495. // Run the last activity instance in the context
  496. util.vibrate();
  497. var help = tutorial.isLaunched() && activity.id == tutorial.activityId;
  498. preferences.runActivity(activity, undefined, null, null, help);
  499. this.postRunActivity(activity.isNative);
  500. },
  501. runOldActivity: function(activity, instance) {
  502. // Run an old activity instance
  503. this.getPopup().hidePopup()
  504. util.vibrate();
  505. var help = tutorial.isLaunched() && activity.id == tutorial.activityId;
  506. preferences.runActivity(activity, instance.objectId, instance.metadata.title, null, help);
  507. },
  508. runNewActivity: function(activity) {
  509. // Start a new activity instance
  510. this.getPopup().hidePopup()
  511. util.vibrate();
  512. var help = tutorial.isLaunched() && activity.id == tutorial.activityId;
  513. preferences.runActivity(activity, null, null, null, help);
  514. this.postRunActivity(activity.isNative);
  515. },
  516. postRunActivity: function(isNative) {
  517. // When run a native activity, should update journal and view to reflect journal change
  518. if (window.sugarizerOS && isNative) {
  519. sugarizerOS.popupTimer = new Date();
  520. this.loadJournal();
  521. preferences.updateEntries();
  522. this.draw();
  523. }
  524. },
  525. // Display journal
  526. showJournal: function() {
  527. this.showView(constant.journalView);
  528. },
  529. // Popup menu for activities handling
  530. showActivityPopup: function(icon) {
  531. // Create popup
  532. if (window.sugarizerOS) {
  533. var now = new Date();
  534. if (sugarizerOS.popupTimer && now.getTime() - sugarizerOS.popupTimer.getTime() < 3000) {
  535. return;
  536. }
  537. sugarizerOS.popupTimer = now;
  538. }
  539. var title;
  540. var activity = icon.icon; // HACK: activity is stored as an icon
  541. if (activity.instances !== undefined && activity.instances.length > 0 && activity.instances[0].metadata.title !== undefined) {
  542. title = activity.instances[0].metadata.title;
  543. } else {
  544. title = l10n.get('NameActivity', {name: activity.name});
  545. }
  546. this.getPopup().setHeader({
  547. icon: activity,
  548. colorized: activity.instances !== undefined && activity.instances.length > 0,
  549. colorizedColor: (activity.instances !== undefined && activity.instances.length > 0 && activity.instances[0].metadata.buddy_color) ? activity.instances[0].metadata.buddy_color : null,
  550. name: activity.name,
  551. title: title,
  552. action: enyo.bind(this, "runActivity"),
  553. data: [activity, null]
  554. });
  555. var items = [];
  556. if (activity.instances) {
  557. for(var i = 0 ; i < activity.instances.length && i < constant.maxPopupHistory; i++) {
  558. items.push({
  559. icon: activity,
  560. colorized: true,
  561. colorizedColor: (activity.instances[i].metadata.buddy_color ? activity.instances[i].metadata.buddy_color : null),
  562. name: activity.instances[i].metadata.title,
  563. action: enyo.bind(this, "runOldActivity"),
  564. data: [activity, activity.instances[i]]
  565. });
  566. }
  567. }
  568. this.getPopup().setItems(items);
  569. this.getPopup().setFooter([{
  570. icon: activity,
  571. colorized: false,
  572. name: l10n.get("StartNew"),
  573. action: enyo.bind(this, "runNewActivity"),
  574. data: [activity, null]
  575. }]);
  576. // Show popup
  577. this.getPopup().showPopup();
  578. },
  579. hideActivityPopup: function(icon) {
  580. // Hide popup
  581. if (this.getPopup().cursorIsInside() || icon.cursorIsInside()) {
  582. return false;
  583. }
  584. this.getPopup().hidePopup();
  585. return true;
  586. },
  587. // Popup menu for buddy handling
  588. showBuddyPopup: function(icon) {
  589. // Create popup
  590. this.getPopup().setHeader({
  591. icon: icon.icon,
  592. colorized: true,
  593. name: preferences.getName(),
  594. title: null,
  595. action: null
  596. });
  597. this.getPopup().setItems(null);
  598. var items = [];
  599. items.push({
  600. icon: {directory: "icons", icon: "system-shutdown.svg"},
  601. colorized: false,
  602. name: l10n.get("Logoff"),
  603. action: enyo.bind(this, "doLogoff"),
  604. data: null
  605. });
  606. items.push({
  607. icon: {directory: "icons", icon: "system-restart.svg"},
  608. colorized: false,
  609. name: l10n.get("Restart"),
  610. action: enyo.bind(this, "doRestart"),
  611. data: null
  612. });
  613. items.push({
  614. icon: {directory: "icons", icon: "preferences-system.svg"},
  615. colorized: false,
  616. name: l10n.get("MySettings"),
  617. action: enyo.bind(this, "doSettings"),
  618. data: null
  619. });
  620. this.getPopup().setFooter(items);
  621. // Show popup
  622. this.getPopup().showPopup();
  623. },
  624. hideBuddyPopup: function(icon) {
  625. if (this.getPopup().cursorIsInside() || icon.cursorIsInside()) {
  626. return false;
  627. }
  628. this.getPopup().hidePopup();
  629. return true;
  630. },
  631. doLogoff: function() {
  632. stats.trace(constant.viewNames[this.getView()], 'click', 'logoff');
  633. this.getPopup().hidePopup();
  634. if (!preferences.isConnected() || (preferences.isConnected() && !preferences.getOptions("sync"))) {
  635. this.otherview = this.$.otherview.createComponent({kind: "Sugar.DialogWarningMessage"}, {owner:this});
  636. this.otherview.show();
  637. } else {
  638. preferences.addUserInHistory();
  639. util.cleanDatastore(null, function() {
  640. util.restartApp();
  641. });
  642. }
  643. },
  644. doRestart: function() {
  645. stats.trace(constant.viewNames[this.getView()], 'click', 'restart');
  646. util.restartApp();
  647. },
  648. doSettings: function() {
  649. stats.trace(constant.viewNames[this.getView()], 'click', 'my_settings');
  650. this.getPopup().hidePopup();
  651. this.otherview = this.$.otherview.createComponent({kind: "Sugar.DialogSettings"}, {owner:this});
  652. this.otherview.show();
  653. },
  654. doResetLauncher: function() {
  655. this.otherview = this.$.otherview.createComponent({kind: "Sugar.DialogSetLauncher"}, {owner:this});
  656. this.otherview.show();
  657. },
  658. // Filter activities handling
  659. filterActivities: function() {
  660. var filter = toolbar.getSearchText().toLowerCase();
  661. // In radial view, just disable activities
  662. enyo.forEach(this.$.desktop.getControls(), function(item) {
  663. item.setDisabled(item.icon.name.toLowerCase().indexOf(filter) == -1 && filter.length != 0);
  664. });
  665. // In list view display only matching activities
  666. if (this.currentView == constant.listView) {
  667. this.otherview.setActivities(preferences.getActivitiesByName(filter));
  668. }
  669. }
  670. });
  671. // Class for desktop toolbar
  672. enyo.kind({
  673. name: "Sugar.DesktopToolbar",
  674. kind: enyo.Control,
  675. components: [
  676. {name: "searchtext", kind: "Sugar.SearchField", classes: "homeview-filter-text", onTextChanged: "filterActivities"},
  677. {name: "helpbutton", kind: "Button", classes: "toolbutton help-button", title:"Help", ontap: "startTutorial"},
  678. {name: "syncbutton", classes: "sync-button sync-home sync-gear sync-gear-home", showing: false},
  679. {name: "offlinebutton", kind: "Button", classes: "toolbutton offline-button", title:"Not connected", ontap: "doServerSettings", showing: false},
  680. {name: "radialbutton", kind: "Button", classes: "toolbutton view-radial-button active", title:"Home", ontap: "showRadialView"},
  681. {name: "neighborbutton", kind: "Button", classes: "toolbutton view-neighbor-button", title:"Home", ontap: "showNeighborView"},
  682. {name: "listbutton", kind: "Button", classes: "toolbutton view-list-button", title:"List", ontap: "showListView"}
  683. ],
  684. // Constructor
  685. create: function() {
  686. this.inherited(arguments);
  687. this.needRedraw = false;
  688. },
  689. rendered: function() {
  690. this.inherited(arguments);
  691. this.localize();
  692. },
  693. localize: function() {
  694. // Localize items
  695. this.$.searchtext.setPlaceholder(l10n.get("SearchHome"));
  696. this.$.radialbutton.setNodeProperty("title", l10n.get("FavoritesView"));
  697. this.$.listbutton.setNodeProperty("title", l10n.get("ListView"));
  698. this.$.neighborbutton.setNodeProperty("title", l10n.get("NeighborhoodView"));
  699. this.$.helpbutton.setNodeProperty("title", l10n.get("Tutorial"));
  700. this.$.offlinebutton.setNodeProperty("title", l10n.get("NotConnected"));
  701. if (app.localize) {
  702. app.localize();
  703. }
  704. },
  705. askRedraw: function() {
  706. this.needRedraw = true;
  707. },
  708. // Handle search text content
  709. getSearchText: function() {
  710. return this.$.searchtext.getText();
  711. },
  712. setSearchText: function(value) {
  713. this.$.searchtext.setText(value);
  714. },
  715. // Handle active button
  716. setActiveView: function(view) {
  717. if (view == constant.radialView) {
  718. this.$.radialbutton.addRemoveClass('active', true);
  719. this.$.neighborbutton.addRemoveClass('active', false);
  720. this.$.listbutton.addRemoveClass('active', false);
  721. } else if (view == constant.listView) {
  722. this.$.radialbutton.addRemoveClass('active', false);
  723. this.$.neighborbutton.addRemoveClass('active', false);
  724. this.$.listbutton.addRemoveClass('active', true);
  725. } else if (view == constant.neighborhoodView) {
  726. this.$.radialbutton.addRemoveClass('active', false);
  727. this.$.neighborbutton.addRemoveClass('active', true);
  728. this.$.listbutton.addRemoveClass('active', false);
  729. }
  730. },
  731. // Handle events
  732. filterActivities: function() {
  733. stats.trace(constant.viewNames[app.getView()], 'search', 'q='+this.getSearchText(), null);
  734. app.filterActivities();
  735. },
  736. showRadialView: function() {
  737. util.vibrate();
  738. app.showView(constant.radialView);
  739. if (this.needRedraw) {
  740. this.needRedraw = false;
  741. app.redraw();
  742. }
  743. },
  744. showListView: function() {
  745. util.vibrate();
  746. app.showView(constant.listView);
  747. if (this.needRedraw) {
  748. this.needRedraw = false;
  749. app.redraw();
  750. }
  751. },
  752. showNeighborView: function() {
  753. util.vibrate();
  754. app.showView(constant.neighborhoodView);
  755. if (this.needRedraw) {
  756. this.needRedraw = false;
  757. app.redraw();
  758. }
  759. },
  760. showSync: function(showing) {
  761. this.$.syncbutton.setShowing(showing);
  762. },
  763. showServerWarning: function(showing) {
  764. this.$.offlinebutton.setShowing(showing);
  765. },
  766. doServerSettings: function() {
  767. if (preferences.isConnected()) {
  768. var token = preferences.getToken();
  769. if (token && !token.expired) {
  770. // No need to show settings, connection issue, just try to reconnect
  771. var that = app;
  772. app.connectToServer(function(success) {
  773. if (that.getToolbar() && that.getToolbar().showServerWarning) {
  774. that.getToolbar().showServerWarning(!success);
  775. }
  776. });
  777. return;
  778. }
  779. }
  780. var otherview = app.$.otherview.createComponent({kind: "Sugar.DialogServer"}, {owner:this});
  781. otherview.show();
  782. },
  783. startTutorial: function() {
  784. tutorial.setElement("radialbutton", this.$.radialbutton.getAttribute("id"));
  785. tutorial.setElement("listbutton", this.$.listbutton.getAttribute("id"));
  786. tutorial.setElement("neighborbutton", this.$.neighborbutton.getAttribute("id"));
  787. tutorial.setElement("searchtext", this.$.searchtext.getAttribute("id"));
  788. tutorial.setElement("offlinebutton", this.$.offlinebutton.getAttribute("id"));
  789. if (app.otherview && app.otherview.beforeHelp) {
  790. app.otherview.beforeHelp();
  791. } else {
  792. app.beforeHelp();
  793. }
  794. stats.trace(constant.viewNames[app.getView()], 'tutorial', 'start', null);
  795. tutorial.start();
  796. }
  797. });