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.

1268 lines
48 KiB

  1. // Listview view
  2. enyo.kind({
  3. name: "Sugar.Journal",
  4. published: { journal: null },
  5. kind: "FittableRows",
  6. components: [
  7. {name: "warningbox", kind: "Sugar.GenericDialogBox", showing: false, classes: "journal-dialogbox", onCancel: "dialogSelectedCancel", onOk: "dialogSelectedOk"},
  8. {name: "content", kind: "Scroller", fit: true, classes: "journal-content", onresize: "draw", onScroll: "onscroll", components: [
  9. {name: "empty", classes: "journal-empty", showing: true},
  10. {name: "message", classes: "journal-message", showing: true},
  11. {name: "nofilter", kind: "Sugar.IconButton", icon: {directory: "icons", icon: "dialog-cancel.svg"}, classes: "listview-button", ontap: "nofilter", showing: false},
  12. {name: "journalList", classes: "journal-list", kind: "Repeater", onSetupItem: "setupItem", components: [
  13. {name: "item", classes: "journal-list-item", components: [
  14. {name: "check", kind: "Input", type: "checkbox", classes: "toggle journal-check", onchange: "switchCheck"},
  15. {name: "favorite", kind: "Sugar.Icon", x: 40, y: 4, size: constant.iconSizeLargeFavorite, ontap: "switchFavorite"},
  16. {name: "activity", kind: "Sugar.Icon", x: 100, y: 5, size: constant.iconSizeList, colorized: true, ontap: "runActivity"},
  17. {name: "title", showing: true, classes: "journal-title", ontap: "titleEditStart"},
  18. {name: "titleEdit", showing: false, kind: "enyo.Input", classes: "journal-title-edit", onblur:"titleEditEnd"},
  19. {name: "time", classes: "journal-time"},
  20. {name: "goright", kind: "Sugar.Icon", classes: "journal-goright", size: constant.iconSizeFavorite, ontap: "runActivity"}
  21. ]}
  22. ]},
  23. {name: "activityPopup", kind: "Sugar.Popup", showing: false}
  24. ]},
  25. {name: "footer", classes: "journal-footer toolbar", showing: false, components: [
  26. {name: "journalbutton", kind: "Button", classes: "toolbutton view-localjournal-button active", title:"Journal", ontap: "showLocalJournal"},
  27. {name: "cloudonebutton", kind: "Button", classes: "toolbutton view-cloudone-button", title:"Private", ontap: "showPrivateCloud"},
  28. {name: "cloudallbutton", kind: "Button", classes: "toolbutton view-cloudall-button", title:"Shared", ontap: "showSharedCloud"},
  29. {name: "syncgear", classes: "sync-button sync-gear sync-gear-journal", showing: false},
  30. {name: "syncbutton", kind: "Button", classes: "toolbutton sync-button sync-journal", title:"Sync", ontap: "syncJournal"},
  31. {name: "pageup", kind: "Button", classes: "toolbutton page-up", showing: false, title:"Previous", ontap: "pagePrevious"},
  32. {name: "pagecount", content: "99/99", classes: "page-count", showing: false},
  33. {name: "pagedown", kind: "Button", classes: "toolbutton page-down", showing: false, title:"Next", ontap: "pageNext"}
  34. ]}
  35. ],
  36. // Constructor: init list
  37. create: function() {
  38. this.inherited(arguments);
  39. this.toolbar = null;
  40. this.empty = (this.journal.length == 0);
  41. this.realLength = 0;
  42. this.loadResult = {};
  43. this.loadingError = false;
  44. this.journalType = constant.journalLocal;
  45. this.smallTime = false;
  46. this.dialogAction = -1;
  47. this.journalChanged();
  48. this.$.footer.setShowing(preferences.getNetworkId() != null && preferences.getPrivateJournal() != null && preferences.getSharedJournal() != null);
  49. if (l10n.language.direction == "rtl") {
  50. this.$.message.addClass("rtl-10");
  51. }
  52. this.draw();
  53. },
  54. // Render
  55. rendered: function() {
  56. this.inherited(arguments);
  57. // Colorizer footer icons
  58. iconLib.colorize(this.$.journalbutton.hasNode(), preferences.getColor(), function() {});
  59. iconLib.colorize(this.$.cloudonebutton.hasNode(), preferences.getColor(), function() {});
  60. iconLib.colorize(this.$.cloudallbutton.hasNode(), preferences.getColor(), function() {});
  61. this.$.syncbutton.setNodeProperty("title", l10n.get("Synchronize"));
  62. this.$.pageup.setNodeProperty("title", l10n.get("Back"));
  63. this.$.pagedown.setNodeProperty("title", l10n.get("Next"));
  64. this.journalChanged();
  65. },
  66. // Handle scroll to lazy display on local content
  67. onscroll: function(inSender, inEvent) {
  68. var scrollBounds = inEvent.scrollBounds;
  69. var scrollAtBottom = ((scrollBounds.maxTop - scrollBounds.top) < constant.journalScrollLimit);
  70. var currentCount = this.$.journalList.get("count");
  71. if (this.journalType == constant.journalLocal && !this.getToolbar().hasFilter() && scrollAtBottom && this.realLength > currentCount) {
  72. var selection = this.getSelection();
  73. var length = Math.min(currentCount + constant.journalStepCount, this.journal.length);
  74. humane.log(l10n.get("Loading"));
  75. this.$.journalList.set("count", length, true);
  76. this.setSelection(selection);
  77. this.updateSelectionCount();
  78. }
  79. },
  80. // Load next remote page in Journal
  81. pageNext: function() {
  82. var result = this.loadResult;
  83. if ((result.offset+result.limit) < result.total) {
  84. this.getToolbar().setMultiselectToolbarVisibility(false);
  85. this.$.warningbox.setShowing(false);
  86. var journalId = (this.journalType == constant.journalRemotePrivate ) ? preferences.getPrivateJournal() : preferences.getSharedJournal();
  87. var offset = result.offset + result.limit;
  88. if (result.total - offset < result.limit) {
  89. offset = result.total - result.limit;
  90. }
  91. humane.log(l10n.get("Loading"));
  92. if (!this.getToolbar().hasFilter()) {
  93. this.loadRemoteJournal(journalId, offset);
  94. } else {
  95. this.filterEntries(this.request.name, this.request.favorite, this.request.typeactivity, this.request.stime, offset);
  96. }
  97. }
  98. },
  99. // Load previous remote page in Journal
  100. pagePrevious: function() {
  101. var result = this.loadResult;
  102. if (result.offset > 0) {
  103. this.getToolbar().setMultiselectToolbarVisibility(false);
  104. this.$.warningbox.setShowing(false);
  105. var journalId = (this.journalType == constant.journalRemotePrivate ) ? preferences.getPrivateJournal() : preferences.getSharedJournal();
  106. var offset = result.offset - result.limit;
  107. if (offset < result.limit) {
  108. offset = 0;
  109. }
  110. humane.log(l10n.get("Loading"));
  111. if (!this.getToolbar().hasFilter()) {
  112. this.loadRemoteJournal(journalId, offset);
  113. } else {
  114. this.filterEntries(this.request.name, this.request.favorite, this.request.typeactivity, this.request.stime, offset);
  115. }
  116. }
  117. },
  118. // Show/hide remote page button
  119. showPageButton: function() {
  120. var result = this.loadResult;
  121. if (this.journalType == constant.journalLocal || !result) {
  122. this.$.pagedown.setShowing(false);
  123. this.$.pageup.setShowing(false);
  124. this.$.pagecount.setShowing(false);
  125. return;
  126. }
  127. var up = (result.offset > 0);
  128. this.$.pageup.setShowing(up);
  129. var down = (result.offset+result.limit) < result.total;
  130. this.$.pagedown.setShowing(down);
  131. var currentPage = (result.total?1:0)+Math.ceil(result.offset/result.limit);
  132. var lastPage = Math.ceil(result.total/result.limit);
  133. this.$.pagecount.setContent(currentPage+"/"+lastPage);
  134. this.$.pagecount.setShowing(down || up);
  135. },
  136. // Get linked toolbar
  137. getToolbar: function() {
  138. if (this.toolbar == null) {
  139. this.toolbar = new Sugar.JournalToolbar();
  140. }
  141. return this.toolbar;
  142. },
  143. // Draw screen
  144. draw: function() {
  145. // Resize content and set Journal empty in the middle
  146. var canvas_center = util.getCanvasCenter();
  147. var footer_size = this.$.footer.getShowing() ? 55 : 0; // HACK: 55 is the footer height
  148. this.smallTime = (canvas_center.dx < 660);
  149. var android_gap = (enyo.platform.android ? 3 : 0);
  150. this.$.content.applyStyle("height", (canvas_center.dy-footer_size-android_gap)+"px");
  151. this.$.empty.applyStyle("margin-left", (canvas_center.x-constant.sizeEmpty/4)+"px");
  152. var margintop = (canvas_center.y-constant.sizeEmpty/4-80);
  153. this.$.empty.applyStyle("margin-top", margintop+"px");
  154. this.$.message.setContent(l10n.get("JournalEmpty"));
  155. if (preferences.getNetworkId() != null && preferences.getPrivateJournal() != null && preferences.getSharedJournal() != null) {
  156. tutorial.setElement("journalbutton", this.$.journalbutton.getAttribute("id"));
  157. tutorial.setElement("cloudonebutton", this.$.cloudonebutton.getAttribute("id"));
  158. tutorial.setElement("cloudallbutton", this.$.cloudallbutton.getAttribute("id"));
  159. }
  160. },
  161. updateNetworkBar: function() {
  162. this.$.footer.setShowing(preferences.getNetworkId() != null && preferences.getPrivateJournal() != null && preferences.getSharedJournal() != null);
  163. this.draw();
  164. },
  165. // Property changed
  166. journalChanged: function() {
  167. if (!this.$.empty) {
  168. return;
  169. }
  170. this.$.empty.show();
  171. this.$.message.show();
  172. this.$.nofilter.show();
  173. var noFilter = !this.getToolbar().hasFilter();
  174. var isLocalJournal = (this.journalType == constant.journalLocal);
  175. this.empty = (noFilter && !this.loadingError && this.journal.length == 0);
  176. if (this.journal != null && this.journal.length > 0) {
  177. var length = (isLocalJournal && noFilter && this.journal.length > constant.journalInitCount) ? constant.journalInitCount : this.journal.length;
  178. this.realLength = this.journal.length;
  179. this.$.journalList.set("count", length, true);
  180. this.$.empty.hide();
  181. this.$.message.hide();
  182. this.$.nofilter.hide();
  183. } else {
  184. this.$.journalList.set("count", 0, true);
  185. if (this.empty) {
  186. // Journal empty
  187. this.$.message.setContent(l10n.get("JournalEmpty"));
  188. this.$.nofilter.hide();
  189. } else if (this.loadingError) {
  190. // Loading error
  191. this.$.message.setContent(l10n.get("ErrorLoadingRemote"));
  192. this.$.nofilter.setText(l10n.get("Retry"));
  193. this.$.nofilter.setIcon({directory: "icons", icon: "system-restart.svg"});
  194. } else {
  195. // Filtering return no result
  196. this.$.message.setContent(l10n.get("NoMatchingEntries"));
  197. this.$.nofilter.setText(l10n.get("ClearSearch"));
  198. this.$.nofilter.setIcon({directory: "icons", icon: "dialog-cancel.svg"});
  199. }
  200. }
  201. this.showPageButton();
  202. },
  203. // Init setup for a line
  204. setupItem: function(inSender, inEvent) {
  205. // Set item in the template
  206. var entry = this.journal[inEvent.index];
  207. if (entry.metadata.buddy_color) {
  208. inEvent.item.$.activity.setColorizedColor(entry.metadata.buddy_color);
  209. }
  210. var activityIcon = preferences.getActivity(entry.metadata.activity);
  211. if (activityIcon == preferences.genericActivity) {
  212. if (entry.metadata.mimetype == "text/plain") {
  213. activityIcon = {directory: "icons", icon: "application-x-txt.svg"};
  214. } else if (entry.metadata.mimetype == "application/pdf") {
  215. activityIcon = {directory: "icons", icon: "application-x-pdf.svg"};
  216. } else if (entry.metadata.mimetype == "application/msword") {
  217. activityIcon = {directory: "icons", icon: "application-x-doc.svg"};
  218. } else if (entry.metadata.mimetype == "application/vnd.oasis.opendocument.text") {
  219. activityIcon = {directory: "icons", icon: "application-x-odt.svg"};
  220. }
  221. }
  222. inEvent.item.$.activity.setIcon(activityIcon);
  223. inEvent.item.$.favorite.setIcon({directory: "icons", icon: "emblem-favorite-large.svg"});
  224. var keep = entry.metadata.keep;
  225. inEvent.item.$.favorite.setColorized(keep !== undefined && keep == 1);
  226. inEvent.item.$.title.setContent(entry.metadata.title);
  227. var sortfield = this.getToolbar().getSortType();
  228. if (sortfield == 1) {
  229. inEvent.item.$.time.setContent(util.timestampToElapsedString(entry.metadata.creation_time, 2, this.smallTime));
  230. } else if (sortfield == 2) {
  231. inEvent.item.$.time.setContent(util.formatSize(entry.metadata.textsize || 0));
  232. } else {
  233. inEvent.item.$.time.setContent(util.timestampToElapsedString(entry.metadata.timestamp, 2, this.smallTime));
  234. }
  235. inEvent.item.$.goright.setIcon({directory: "icons", icon: "go-right.svg"});
  236. inEvent.item.$.activity.setPopupShow(enyo.bind(this, "showActivityPopup"));
  237. inEvent.item.$.activity.setPopupHide(enyo.bind(this, "hideActivityPopup"));
  238. inEvent.item.$.activity.setData(entry);
  239. if (l10n.language.direction == "rtl") {
  240. inEvent.item.$.title.addClass("rtl-14");
  241. inEvent.item.$.titleEdit.addClass("rtl-14");
  242. inEvent.item.$.time.addClass("rtl-14");
  243. }
  244. if (inEvent.index == 0) {
  245. tutorial.setElement("checkitem", inEvent.item.$.check.getAttribute("id"));
  246. tutorial.setElement("activityitem", inEvent.item.$.activity.getAttribute("id"));
  247. tutorial.setElement("titleitem", inEvent.item.$.title.getAttribute("id"));
  248. tutorial.setElement("timeitem", inEvent.item.$.time.getAttribute("id"));
  249. tutorial.setElement("favoriteitem", inEvent.item.$.favorite.getAttribute("id"));
  250. }
  251. },
  252. // Switch favorite value for clicked line
  253. switchFavorite: function(inSender, inEvent) {
  254. var objectId = this.journal[inEvent.index].objectId;
  255. var keep = this.journal[inEvent.index].metadata.keep;
  256. if (keep === undefined) {
  257. this.journal[inEvent.index].metadata.keep = 1;
  258. } else {
  259. this.journal[inEvent.index].metadata.keep = (keep + 1) % 2;
  260. }
  261. stats.trace(constant.viewNames[app.getView()], 'switch_favorite', objectId, null);
  262. var ds = new datastore.DatastoreObject(objectId);
  263. ds.setMetadata(this.journal[inEvent.index].metadata);
  264. ds.save();
  265. inEvent.dispatchTarget.container.setColorized(this.journal[inEvent.index].metadata.keep == 1);
  266. inEvent.dispatchTarget.container.render();
  267. },
  268. // Check/uncheck an item Checkbox
  269. switchCheck: function(inSender, inEvent) {
  270. this.$.warningbox.setShowing(false);
  271. this.getToolbar().setMultiselectToolbarVisibility(this.updateSelectionCount() > 0);
  272. },
  273. updateSelectionCount: function() {
  274. var selection = this.getSelection();
  275. this.getToolbar().setSelectedCount(selection.length, this.$.journalList.get("count"));
  276. return selection.length;
  277. },
  278. getSelection: function() {
  279. var selection = [];
  280. var length = this.$.journalList.get("count");
  281. for (var i = 0 ; i < length ; i++) {
  282. if (this.$.journalList.children[i].$.check.getNodeProperty("checked")) {
  283. selection.push(i);
  284. }
  285. }
  286. return selection;
  287. },
  288. setSelection: function(selection) {
  289. var length = selection.length;
  290. for (var i = 0 ; i < length ; i++) {
  291. var index = selection[i];
  292. this.$.journalList.children[index].$.check.setNodeProperty("checked", true);
  293. }
  294. },
  295. selectAll: function() {
  296. var length = this.$.journalList.get("count");
  297. for (var i = 0 ; i < length ; i++) {
  298. this.$.journalList.children[i].$.check.setNodeProperty("checked", true);
  299. }
  300. this.getToolbar().setSelectedCount(length, length);
  301. },
  302. unselectAll: function() {
  303. var length = this.$.journalList.get("count");
  304. for (var i = 0 ; i < length ; i++) {
  305. this.$.journalList.children[i].$.check.setNodeProperty("checked", false);
  306. }
  307. this.getToolbar().setMultiselectToolbarVisibility(false);
  308. },
  309. removeSelected: function() {
  310. this.dialogAction = constant.journalRemove;
  311. this.$.warningbox.setTitle(l10n.get("Erase"));
  312. var length = this.getSelection().length;
  313. this.$.warningbox.setMessage(length == 1 ? l10n.get("Erase_one",{count:length}) : l10n.get("Erase_other",{count:length}));
  314. this.$.warningbox.setOkText(l10n.get("Ok"));
  315. this.$.warningbox.setCancelText(l10n.get("Cancel"));
  316. this.$.warningbox.setShowing(true);
  317. },
  318. copySelected: function(dest) {
  319. this.dialogAction = dest;
  320. var title = ["CopyToLocal", "CopyToPrivate", "CopyToShared", "", "CopyToDevice"];
  321. this.$.warningbox.setTitle(l10n.get(title[dest]));
  322. var length = this.getSelection().length;
  323. this.$.warningbox.setMessage(length == 1 ? l10n.get(title[dest]+"_one",{count:length}) : l10n.get(title[dest]+"_other",{count:length}));
  324. this.$.warningbox.setOkText(l10n.get("Ok"));
  325. this.$.warningbox.setCancelText(l10n.get("Cancel"));
  326. this.$.warningbox.setShowing(true);
  327. },
  328. dialogSelectedOk: function() {
  329. this.$.warningbox.setShowing(false);
  330. this.getToolbar().setMultiselectToolbarVisibility(false);
  331. var selection = this.getSelection();
  332. var toProcess = [];
  333. for (var i = 0 ; i < selection.length ; i++) {
  334. toProcess.push(this.journal[selection[i]]);
  335. }
  336. var that = this;
  337. var isMultiple = (this.dialogAction == constant.journalDevice && util.getClientType() == constant.appType && enyo.platform.electron);
  338. if (!isMultiple) {
  339. humane.log(l10n.get(this.dialogAction == constant.journalRemove ? "Erasing" : "Copying"));
  340. }
  341. window.setTimeout(function() {
  342. if (!isMultiple) {
  343. // Do action on each entry
  344. for (var i = 0 ; i < toProcess.length ; i++) {
  345. if (that.dialogAction == constant.journalDevice) {
  346. that.copyToDevice(toProcess[i]);
  347. } else if (that.dialogAction == constant.journalRemove) {
  348. that.removeEntry(toProcess[i], {isLast: (i==toProcess.length-1)});
  349. } else if (that.dialogAction == constant.journalLocal) {
  350. that.copyToLocal(toProcess[i]);
  351. } else {
  352. that.copyToRemote(toProcess[i], (that.dialogAction == constant.journalRemotePrivate ? preferences.getPrivateJournal() : preferences.getSharedJournal()));
  353. }
  354. }
  355. } else {
  356. // Do action on all entries
  357. that.copyMultipleToDevice(toProcess);
  358. }
  359. that.unselectAll();
  360. }, 100);
  361. },
  362. dialogSelectedCancel: function() {
  363. this.$.warningbox.setShowing(false);
  364. this.getToolbar().setMultiselectToolbarVisibility(true);
  365. },
  366. // Run activity from icon or from the popup menu
  367. runActivity: function(inSender, inEvent) {
  368. this.runCurrentActivity(this.journal[inEvent.index]);
  369. },
  370. runCurrentActivity: function(activity) {
  371. // Generic activity type, try to open as a document
  372. var activityInstance = preferences.getActivity(activity.metadata.activity);
  373. if (activityInstance == preferences.genericActivity) {
  374. if (activity.metadata.mimetype == "application/pdf") {
  375. var that = this;
  376. this.loadEntry(activity, function(err, metadata, text) {
  377. that.$.activityPopup.hidePopup();
  378. util.openAsDocument(metadata, text);
  379. return;
  380. });
  381. }
  382. return;
  383. }
  384. // Load text content
  385. var that = this;
  386. this.loadEntry(activity, function(err, metadata, text) {
  387. // Remote entry, copy in the local journal first
  388. if (that.journalType != constant.journalLocal) {
  389. // Create the entry with same oid - or update the entry if already there
  390. var ds = new datastore.DatastoreObject(activity.objectId);
  391. ds.setMetadata(metadata);
  392. ds.setDataAsText(text);
  393. ds.save(function() {
  394. // Run updated local entry
  395. preferences.runActivity(
  396. activityInstance,
  397. activity.objectId,
  398. metadata.title);
  399. });
  400. return;
  401. }
  402. // Run local entry
  403. preferences.runActivity(
  404. activityInstance,
  405. activity.objectId,
  406. metadata.title);
  407. });
  408. },
  409. // Filter entries handling
  410. filterEntries: function(name, favorite, typeactivity, timeperiod, offset) {
  411. // Filter remote entries
  412. var sortfield = this.getToolbar().getSortType();
  413. if (this.journalType != constant.journalLocal) {
  414. var journalId = (this.journalType == constant.journalRemotePrivate ) ? preferences.getPrivateJournal() : preferences.getSharedJournal();
  415. var that = this;
  416. var sort = '-timestamp';
  417. if (sortfield == 1) {
  418. sort = '-creation_time';
  419. } else if (sortfield == 2) {
  420. sort = '-textsize';
  421. }
  422. var request = {
  423. typeactivity: typeactivity,
  424. title: (name !== undefined) ? name : undefined,
  425. stime: (timeperiod !== undefined ? timeperiod : undefined),
  426. favorite: favorite,
  427. field: constant.fieldMetadata,
  428. limit: constant.pageJournalSize,
  429. sort: sort,
  430. offset: (offset !== undefined ? offset : 0)
  431. }
  432. myserver.getJournal(journalId, request,
  433. function(inSender, inResponse) {
  434. that.loadResult = {offset: inResponse.offset, total: inResponse.total, limit: inResponse.limit};
  435. that.request = request;
  436. that.journal = inResponse.entries;
  437. that.empty = (!that.getToolbar().hasFilter() && !this.loadingError && that.journal.length == 0);
  438. that.loadingError = false;
  439. that.journalChanged();
  440. },
  441. function() {
  442. console.log("WARNING: Error filtering journal "+journalId);
  443. that.loadResult = {};
  444. that.request = {};
  445. that.journal = [];
  446. that.loadingError = true;
  447. that.journalChanged();
  448. }
  449. );
  450. return;
  451. }
  452. // Filter local entries
  453. this.journal = datastore.find(typeactivity);
  454. this.loadingError = false;
  455. this.journal = this.journal.filter(function(activity) {
  456. return (favorite !== undefined ? activity.metadata.keep : true)
  457. && (name.length != 0 ? activity.metadata.title.toLowerCase().indexOf(name.toLowerCase()) != -1 : true)
  458. && (timeperiod !== undefined ? activity.metadata.timestamp >= timeperiod : true);
  459. });
  460. var that = this;
  461. this.journal = this.journal.sort(function(e0, e1) {
  462. if (sortfield == 1) {
  463. return parseInt(e1.metadata.creation_time) - parseInt(e0.metadata.creation_time);
  464. } else if (sortfield == 2) {
  465. return parseInt(e1.metadata.textsize || 0) - parseInt(e0.metadata.textsize || 0);
  466. } else {
  467. return parseInt(e1.metadata.timestamp) - parseInt(e0.metadata.timestamp);
  468. }
  469. });
  470. this.journalChanged();
  471. },
  472. nofilter: function() {
  473. this.toolbar.removeFilter();
  474. this.filterEntries("", undefined, undefined, undefined, undefined);
  475. },
  476. // Activity popup
  477. showActivityPopup: function(icon) {
  478. // Create popup
  479. if (!icon.owner) {
  480. return;
  481. }
  482. var activity = icon.icon; // HACK: activity is stored as an icon
  483. var entry = icon.getData();
  484. var title = null;
  485. if (this.journalType != constant.sharedJournal) {
  486. if (entry.metadata.textsize && entry.metadata.textsize > constant.minimumSizeDisplay) {
  487. title = util.formatSize(entry.metadata.textsize);
  488. }
  489. } else if (entry.metadata.buddy_name) {
  490. title = l10n.get("ByUser", {user:entry.metadata.buddy_name});
  491. }
  492. this.$.activityPopup.setHeader({
  493. icon: icon.icon,
  494. colorized: true,
  495. colorizedColor: (entry.metadata.buddy_color ? entry.metadata.buddy_color : null),
  496. name: entry.metadata.title,
  497. title: title,
  498. action: enyo.bind(this, "runCurrentActivity"),
  499. data: [entry, null]
  500. });
  501. this.$.activityPopup.setItems(null);
  502. var items = [];
  503. items.push({
  504. icon: {directory: "icons", icon: "activity-start.svg"},
  505. colorized: false,
  506. name: l10n.get("RestartActivity"),
  507. action: enyo.bind(this, "runCurrentActivity"),
  508. disable: (preferences.getActivity(entry.metadata.activity) == preferences.genericActivity && entry.metadata.mimetype != "application/pdf"),
  509. data: [entry, null]
  510. });
  511. items.push({
  512. icon: {directory: "icons", icon: "copy-journal.svg"},
  513. colorized: false,
  514. name: l10n.get("CopyToLocal"),
  515. action: enyo.bind(this, "copyToLocal"),
  516. data: [entry, null],
  517. disable: this.journalType == constant.journalLocal
  518. });
  519. items.push({
  520. icon: {directory: "icons", icon: "copy-cloud-one.svg"},
  521. colorized: false,
  522. name: l10n.get("CopyToPrivate"),
  523. action: enyo.bind(this, "copyToRemote"),
  524. data: [entry, preferences.getPrivateJournal()],
  525. disable: !preferences.isConnected() || this.journalType == constant.journalRemotePrivate
  526. });
  527. items.push({
  528. icon: {directory: "icons", icon: "copy-cloud-all.svg"},
  529. colorized: false,
  530. name: l10n.get("CopyToShared"),
  531. action: enyo.bind(this, "copyToRemote"),
  532. data: [entry, preferences.getSharedJournal()],
  533. disable: !preferences.isConnected() || this.journalType == constant.journalRemoteShared
  534. });
  535. items.push({
  536. icon: {directory: "icons", icon: "copy-to-device.svg"},
  537. colorized: false,
  538. name: l10n.get("CopyToDevice"),
  539. action: enyo.bind(this, "copyToDevice"),
  540. data: [entry, null]
  541. });
  542. items.push({
  543. icon: {directory: "icons", icon: "list-remove.svg"},
  544. colorized: false,
  545. name: l10n.get("Erase"),
  546. action: enyo.bind(this, "removeEntry"),
  547. data: [entry, null]
  548. });
  549. this.$.activityPopup.setFooter(items);
  550. // Show popup
  551. this.$.activityPopup.setMargin({left: 0, top: (icon.owner.index*60)+20-mouse.position.y});
  552. this.$.activityPopup.showPopup();
  553. },
  554. hideActivityPopup: function(icon) {
  555. if (!this.$.activityPopup) {
  556. return true;
  557. }
  558. if (this.$.activityPopup.cursorIsInside() || icon.cursorIsInside()) {
  559. return false;
  560. }
  561. this.$.activityPopup.hidePopup();
  562. return true;
  563. },
  564. // Copy activity content to the local journal
  565. copyToLocal: function(entry) {
  566. var that = this;
  567. stats.trace(constant.viewNames[app.getView()], 'copy_to_local', entry.objectId, null);
  568. this.loadEntry(entry, function(err, metadata, text) {
  569. var ds = new datastore.DatastoreObject(entry.objectId);
  570. ds.setMetadata(metadata);
  571. ds.setDataAsText(text);
  572. ds.save();
  573. that.$.activityPopup.hidePopup();
  574. });
  575. },
  576. // Copy activity content into a file on the device
  577. copyToDevice: function(entry, directory) {
  578. var that = this;
  579. that.$.activityPopup.hidePopup();
  580. this.loadEntry(entry, function(err, metadata, text) {
  581. util.writeFile(directory, metadata, text, function(err, filename) {
  582. if (err) {
  583. humane.log(l10n.get("ErrorWritingFile"));
  584. } else {
  585. humane.log(l10n.get("FileWroteTo",{file:filename}));
  586. }
  587. });
  588. });
  589. },
  590. // Copy a set of entries on the device: ask directory, then copy each entry
  591. copyMultipleToDevice: function(entries) {
  592. var that = this;
  593. util.askDirectory(function(directory) {
  594. for (var i = 0 ; i < entries.length ; i++) {
  595. that.copyToDevice(entries[i], directory);
  596. }
  597. });
  598. },
  599. // Copy activity content to a remote journal
  600. copyToRemote: function(entry, journalId) {
  601. stats.trace(constant.viewNames[app.getView()], 'copy_to_remote', entry.objectId, journalId);
  602. this.loadEntry(entry, function(err, metadata, text) {
  603. var dataentry = {metadata: metadata, text: text, objectId: entry.objectId};
  604. myserver.putJournalEntry(journalId, entry.objectId, dataentry,
  605. function() {},
  606. function() {
  607. console.log("WARNING: Error writing journal "+journalId);
  608. }
  609. );
  610. });
  611. this.$.activityPopup.hidePopup();
  612. },
  613. // Load local journal
  614. loadLocalJournal: function() {
  615. this.journal = datastore.find();
  616. this.journal = this.journal.sort(function(e0, e1) {
  617. return parseInt(e1.metadata.timestamp) - parseInt(e0.metadata.timestamp);
  618. });
  619. this.journalChanged();
  620. },
  621. // Load a remote journal
  622. loadRemoteJournal: function(journalId, offset) {
  623. var that = this;
  624. var request = {
  625. field: constant.fieldMetadata,
  626. limit: constant.pageJournalSize,
  627. offset: (offset !== undefined ? offset : 0),
  628. sort: '-timestamp'
  629. }
  630. var sortfield = this.getToolbar().getSortType();
  631. if (sortfield == 1) {
  632. request.sort = '-creation_time';
  633. } else if (sortfield == 2) {
  634. request.sort = '-textsize';
  635. }
  636. myserver.getJournal(journalId, request,
  637. function(inSender, inResponse) {
  638. that.loadResult = {offset: inResponse.offset, total: inResponse.total, limit: inResponse.limit};
  639. that.journal = inResponse.entries;
  640. that.empty = (!that.getToolbar().hasFilter() && !this.loadingError && that.journal.length == 0);
  641. that.loadingError = false;
  642. that.journalChanged();
  643. },
  644. function() {
  645. console.log("WARNING: Error reading journal "+journalId);
  646. that.loadResult = {};
  647. that.journal = [];
  648. that.loadingError = true;
  649. that.journalChanged();
  650. }
  651. );
  652. },
  653. // Load entry in the journal
  654. loadEntry: function(entry, callback) {
  655. if (this.journalType == constant.journalLocal) {
  656. var dataentry = new datastore.DatastoreObject(entry.objectId);
  657. dataentry.loadAsText(function(err, metadata, text) {
  658. callback(err, metadata, text);
  659. });
  660. } else {
  661. var journalId;
  662. if (this.journalType == constant.journalRemotePrivate) {
  663. journalId = preferences.getPrivateJournal();
  664. } else if (this.journalType == constant.journalRemoteShared) {
  665. journalId = preferences.getSharedJournal();
  666. }
  667. myserver.getJournalEntry(journalId, entry.objectId,
  668. function(inSender, inResponse) {
  669. callback(null, inResponse.entries[0].metadata, inResponse.entries[0].text);
  670. },
  671. function() {
  672. console.log("WARNING: Error loading entry "+objectId+" in journal "+journalId);
  673. }
  674. );
  675. }
  676. },
  677. // Remove an entry in the journal
  678. removeEntry: function(entry, multiple) {
  679. // Remove from local journal
  680. if (this.journalType == constant.journalLocal) {
  681. // Delete in datastore
  682. stats.trace(constant.viewNames[app.getView()], 'remove_entry', entry.objectId, null);
  683. datastore.remove(entry.objectId);
  684. // If connected and in sync, try remove also the matching remote entry
  685. if (preferences.isConnected() && preferences.getOptions("sync")) {
  686. var journalId = preferences.getPrivateJournal();
  687. var objectId = entry.objectId;
  688. myserver.deleteJournalEntry(journalId, objectId,
  689. function(inSender, inResponse) {},
  690. function() {
  691. console.log("WARNING: Error removing entry "+objectId+" in journal "+journalId);
  692. }
  693. );
  694. }
  695. // Test if refresh
  696. var refresh = (!multiple || multiple.isLast);
  697. if (refresh) {
  698. // Refresh screen
  699. this.toolbar.removeFilter();
  700. this.loadLocalJournal();
  701. // Refresh home screen: activity menu, journal content
  702. preferences.updateEntries();
  703. app.journal = this.journal;
  704. app.redraw();
  705. }
  706. } else {
  707. // Remove from remote journal
  708. var journalId = (this.journalType == constant.journalRemotePrivate ) ? preferences.getPrivateJournal() : preferences.getSharedJournal();
  709. var objectId = entry.objectId;
  710. var that = this;
  711. this.toolbar.removeFilter();
  712. stats.trace(constant.viewNames[app.getView()], 'remove_entry', objectId, journalId);
  713. myserver.deleteJournalEntry(journalId, objectId,
  714. function(inSender, inResponse) {
  715. that.loadRemoteJournal(journalId);
  716. that.$.activityPopup.hidePopup();
  717. },
  718. function() {
  719. console.log("WARNING: Error removing entry "+objectId+" in journal "+journalId);
  720. that.loadRemoteJournal(journalId);
  721. that.$.activityPopup.hidePopup();
  722. }
  723. );
  724. return;
  725. }
  726. this.$.activityPopup.hidePopup();
  727. },
  728. // Handle entry title update
  729. titleEditStart: function(inSender, inEvent) {
  730. var line = inEvent.dispatchTarget.owner.$;
  731. line.title.setShowing(false);
  732. line.titleEdit.setValue(line.title.getContent());
  733. line.titleEdit.setShowing(true);
  734. line.titleEdit.focus();
  735. },
  736. titleEditEnd: function(inSender, inEvent) {
  737. var line = inEvent.dispatchTarget.owner.$;
  738. line.title.setShowing(true);
  739. line.titleEdit.setShowing(false);
  740. var newtitle = line.titleEdit.getValue();
  741. if (newtitle == line.title.getContent()) {
  742. return;
  743. }
  744. var objectId = this.journal[inEvent.index].objectId;
  745. // Update local journal
  746. var that = this;
  747. this.loadEntry(this.journal[inEvent.index], function(err, metadata, text) {
  748. if (that.journalType == constant.journalLocal) {
  749. // Update metadata
  750. metadata.title = newtitle;
  751. stats.trace(constant.viewNames[app.getView()], 'rename_entry', objectId, 'local');
  752. // Update datastore
  753. var ds = new datastore.DatastoreObject(objectId);
  754. ds.setMetadata(metadata);
  755. ds.setDataAsText(text);
  756. ds.save();
  757. // Refresh screen
  758. that.loadLocalJournal();
  759. // Refresh home screen: activity menu, journal content
  760. preferences.updateEntries();
  761. app.journal = that.journal;
  762. app.redraw();
  763. }
  764. // Update remote journal
  765. else {
  766. // Update metadata
  767. metadata.title = newtitle;
  768. // Update remote journal
  769. var journalId = (that.journalType == constant.journalRemotePrivate ) ? preferences.getPrivateJournal() : preferences.getSharedJournal();
  770. var dataentry = {metadata: metadata, text: text, objectId: objectId};
  771. stats.trace(constant.viewNames[app.getView()], 'rename_entry', objectId, journalId);
  772. myserver.putJournalEntry(journalId, objectId, dataentry,
  773. function() {
  774. that.loadRemoteJournal(journalId);
  775. },
  776. function() {
  777. console.log("WARNING: Error updating journal "+journalId);
  778. that.loadRemoteJournal(journalId);
  779. }
  780. );
  781. }
  782. });
  783. },
  784. // Switch journal
  785. showLocalJournal: function() {
  786. this.changeJournalType(constant.journalLocal);
  787. stats.trace(constant.viewNames[app.getView()], 'show_journal', 'local', null);
  788. this.loadLocalJournal();
  789. },
  790. showPrivateCloud: function() {
  791. stats.trace(constant.viewNames[app.getView()], 'show_journal', 'private', null);
  792. this.changeJournalType(constant.journalRemotePrivate);
  793. this.loadRemoteJournal(preferences.getPrivateJournal());
  794. },
  795. showSharedCloud: function() {
  796. stats.trace(constant.viewNames[app.getView()], 'show_journal', 'shared', null);
  797. this.changeJournalType(constant.journalRemoteShared);
  798. this.loadRemoteJournal(preferences.getSharedJournal());
  799. },
  800. // Sync local journal with remote journal
  801. syncJournal: function() {
  802. var that = this;
  803. autosync.synchronizeJournal(
  804. function(count) {
  805. if (count) {
  806. humane.log(l10n.get("RetrievingJournal"));
  807. that.$.syncbutton.setShowing(false);
  808. that.$.syncgear.setShowing(true);
  809. }
  810. },
  811. function(locale, remote, error) {
  812. // Display button
  813. if (!that.$.syncbutton) {
  814. return;
  815. }
  816. that.$.syncbutton.setShowing(true);
  817. that.$.syncgear.setShowing(false);
  818. // Locale has changed, update display
  819. if (locale && that.journalType == constant.journalLocal) {
  820. that.loadLocalJournal();
  821. app.journal = that.journal;
  822. preferences.updateEntries();
  823. app.draw();
  824. }
  825. // Remote has changed, update display
  826. if (remote && that.journalType == constant.journalRemotePrivate) {
  827. that.loadRemoteJournal(preferences.getPrivateJournal());
  828. }
  829. }
  830. );
  831. },
  832. changeJournalType: function(newType) {
  833. this.journalType = newType;
  834. this.$.journalbutton.addRemoveClass('active', newType == constant.journalLocal);
  835. this.$.cloudonebutton.addRemoveClass('active', newType == constant.journalRemotePrivate);
  836. this.$.cloudallbutton.addRemoveClass('active', newType == constant.journalRemoteShared);
  837. this.getToolbar().removeFilter();
  838. this.getToolbar().setMultiselectToolbarVisibility(false);
  839. this.$.warningbox.setShowing(false);
  840. },
  841. getJournalType: function() {
  842. return this.journalType;
  843. }
  844. });
  845. // Class for journal toolbar
  846. enyo.kind({
  847. name: "Sugar.JournalToolbar",
  848. kind: enyo.Control,
  849. components: [
  850. {name: "unselallbutton", showing: false, kind: "Sugar.Icon", classes: "journal-unselectall", x: 0, y: 0, icon: {directory: "icons", icon: "select-none.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "unselectAll"},
  851. {name: "selallbutton", showing: false, kind: "Sugar.Icon", classes: "journal-selectall", x: 0, y: 0, icon: {directory: "icons", icon: "select-all.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "selectAll"},
  852. {name: "split1", showing: false, classes: "splitbar"},
  853. {name: "copyjournalbutton", showing: false, kind: "Sugar.Icon", classes: "journal-copy", x: 0, y: 0, icon: {directory: "icons", icon: "copy-journal.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "copySelected"},
  854. {name: "copycloudonebutton", showing: false, kind: "Sugar.Icon", classes: "journal-copy", x: 0, y: 0, icon: {directory: "icons", icon: "copy-cloud-one.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "copySelected"},
  855. {name: "copycloudallbutton", showing: false, kind: "Sugar.Icon", classes: "journal-copy", x: 0, y: 0, icon: {directory: "icons", icon: "copy-cloud-all.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "copySelected"},
  856. {name: "copydevicebutton", showing: false, kind: "Sugar.Icon", classes: "journal-copy", x: 0, y: 0, icon: {directory: "icons", icon: "copy-to-device.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "copySelected"},
  857. {name: "removebutton", showing: false, kind: "Sugar.Icon", classes: "journal-remove", x: 0, y: 0, icon: {directory: "icons", icon: "list-remove.svg"}, size: constant.iconSizeList, disabledBackground: "#282828", ontap: "removeSelected"},
  858. {name: "split2", showing: false, classes: "splitbar"},
  859. {name: "selectcount", showing: false, classes: "journal-selectcount"},
  860. {name: "favoritebutton", kind: "Sugar.Icon", classes: "journal-filter-favorite", x: 0, y: 4, icon: {directory: "icons", icon: "emblem-favorite.svg"}, size: constant.iconSizeList, ontap: "filterFavorite"},
  861. {name: "journalsearch", kind: "Sugar.SearchField", onTextChanged: "filterEntries", classes: "journal-filter-text"},
  862. {name: "radialbutton", kind: "Button", classes: "toolbutton view-desktop-button", title:"Home", ontap: "gotoDesktop"},
  863. {name: "typepalette", kind: "Sugar.Palette", ontap: "showTypePalette", icon: {directory: "icons", icon: "view-type.svg"}, size: constant.iconSizeList, classes: "journal-filtertype-palette", contentsClasses: "journal-filtertype-content", contents: []},
  864. {name: "datepalette", kind: "Sugar.Palette", ontap: "showDatePalette", icon: {directory: "icons", icon: "view-created.svg"}, size: constant.iconSizeList, classes: "journal-filterdate-palette", contentsClasses: "journal-filterdate-content", contents: []},
  865. {name: "sortpalette", kind: "Sugar.Palette", ontap: "showSortPalette", icon: {directory: "icons", icon: "view-lastedit.svg"}, size: constant.iconSizeList, classes: "journal-sort-palette", contentsClasses: "journal-sort-content", contents: []},
  866. {name: "split3", classes: "splitbar journal-split split3"},
  867. {name: "fromdevicebutton", kind: "Sugar.Icon", x: 0, y: 0, icon: {directory: "icons", icon: "copy-from-device.svg"}, classes: "journal-fromdevice", size: constant.iconSizeList, ontap: "fromDeviceSelected"},
  868. {name: "split4", classes: "splitbar journal-split split4"},
  869. {name: "helpbutton", kind: "Button", classes: "toolbutton help-button-journal", title:"Help", ontap: "startTutorial"}
  870. ],
  871. // Constructor
  872. create: function() {
  873. this.inherited(arguments);
  874. this.localize();
  875. this.typeselected = 0;
  876. this.dateselected = 0;
  877. this.sortfield = 0;
  878. if (util.getClientType() == constant.webAppType || (util.getClientType() == constant.appType && !enyo.platform.android && !enyo.platform.androidChrome && !enyo.platform.ios && !enyo.platform.electron)) {
  879. this.createComponent({name: "file", kind: "Input", type: "file", showing: false, onchange: "fileSelected"}, {owner: this});
  880. }
  881. },
  882. rendered: function() {
  883. this.inherited(arguments);
  884. this.localize();
  885. },
  886. localize: function() {
  887. // Localize items
  888. this.$.favoritebutton.setNodeProperty("title", l10n.get("FilterFavorites"));
  889. this.$.radialbutton.setNodeProperty("title", l10n.get("Home"));
  890. this.$.helpbutton.setNodeProperty("title", l10n.get("Tutorial"));
  891. this.$.unselallbutton.setNodeProperty("title", l10n.get("UnselectAll"));
  892. this.$.selallbutton.setNodeProperty("title", l10n.get("SelectAll"));
  893. this.$.removebutton.setNodeProperty("title", l10n.get("Erase"));
  894. this.$.copyjournalbutton.setNodeProperty("title", l10n.get("CopyToLocal"));
  895. this.$.copycloudonebutton.setNodeProperty("title", l10n.get("CopyToPrivate"));
  896. this.$.copycloudallbutton.setNodeProperty("title", l10n.get("CopyToShared"));
  897. this.$.copydevicebutton.setNodeProperty("title", l10n.get("CopyToDevice"));
  898. this.$.journalsearch.setPlaceholder(l10n.get("SearchJournal"));
  899. this.$.typepalette.setText(l10n.get("AllType"));
  900. this.$.datepalette.setText(l10n.get("Anytime"));
  901. // Set time selectbox content
  902. this.dates = [l10n.get("Anytime"), l10n.get("Today"), l10n.get("SinceYesterday"), l10n.get("PastWeek"), l10n.get("PastMonth")];
  903. var items = [];
  904. this.$.datepalette.setHeader(l10n.get("SelectFilter"));
  905. for(var i = 0 ; i < this.dates.length ; i++) {
  906. items.push({id: ""+(i+1), classes: "journal-filterdate-line", components:[
  907. {classes: "journal-filterdate-item", content: this.dates[i]}
  908. ], ontap: "tapDate"});
  909. }
  910. this.$.datepalette.setItems(items);
  911. // Set type selectbox content
  912. items = [];
  913. this.$.typepalette.setHeader(l10n.get("SelectFilter"));
  914. items.push({id: "0", classes: "journal-filtertype-line", components:[
  915. {kind: "Sugar.Icon", icon: {directory: "icons", icon: "application-x-generic.svg"}, x: 5, y: 3, size: constant.iconSizeFavorite},
  916. {classes: "item-name", content: l10n.get("AllType")}
  917. ], ontap: "tapLine"});
  918. var activities = preferences.getActivities();
  919. var unsortedItems = [];
  920. for(var i = 0 ; i < activities.length ; i++) {
  921. unsortedItems.push({id: ""+(i+1), classes: "journal-filtertype-line", components:[
  922. {kind: "Sugar.Icon", icon: activities[i], x: 5, y: 3, size: constant.iconSizeFavorite},
  923. {classes: "item-name", content: activities[i].name}
  924. ], ontap: "tapLine"});
  925. }
  926. unsortedItems.sort(function(a,b) {
  927. var ca = a.components[1].content, cb = b.components[1].content;
  928. if (ca > cb) { return 1; }
  929. else if (ca < cb) { return -1; }
  930. else return 0;
  931. });
  932. for (var i = 0 ; i < unsortedItems.length ; i++) {
  933. items.push(unsortedItems[i]);
  934. }
  935. this.$.typepalette.setItems(items);
  936. // Set sort selectbox content
  937. this.sorts = [{text: l10n.get("SortByUpdated"), icon:"view-lastedit.svg"}, {text: l10n.get("SortByCreated"), icon:"view-created.svg"}, {text: l10n.get("SortBySize"), icon:"view-size.svg"}];
  938. var items = [];
  939. this.$.sortpalette.setHeader(l10n.get("SortDisplay"));
  940. for(var i = 0 ; i < this.sorts.length ; i++) {
  941. items.push({id: ""+(i+1), classes: "journal-sort-line", components:[
  942. {kind: "Sugar.Icon", icon: {directory: "icons", icon: this.sorts[i].icon}, x: 5, y: 3, size: constant.iconSizeFavorite},
  943. {classes: "journal-sort-item", content: this.sorts[i].text}
  944. ], ontap: "tapSort"});
  945. }
  946. this.$.sortpalette.setItems(items);
  947. },
  948. // Event handling
  949. gotoDesktop: function() {
  950. util.vibrate();
  951. app.showView(constant.radialView);
  952. },
  953. filterFavorite: function() {
  954. this.$.favoritebutton.setColorized(!this.$.favoritebutton.getColorized());
  955. this.$.favoritebutton.render();
  956. this.filterEntries();
  957. },
  958. showTypePalette: function() {
  959. this.$.typepalette.switchPalette(app.otherview);
  960. },
  961. tapLine: function(e, s) {
  962. var activities = preferences.getActivities();
  963. var generic = {directory: "icons", icon: "application-x-generic.svg"};
  964. this.typeselected = e.getId();
  965. this.$.typepalette.setIcon((this.typeselected == 0 ? generic : activities[this.typeselected-1]));
  966. this.$.typepalette.setText((this.typeselected == 0 ? l10n.get("AllType") : activities[this.typeselected-1].name));
  967. this.filterEntries();
  968. this.$.typepalette.switchPalette(app.otherview);
  969. },
  970. showDatePalette: function() {
  971. this.$.datepalette.switchPalette(app.otherview);
  972. },
  973. tapDate: function(e, s) {
  974. this.dateselected = e.getId()-1;
  975. this.$.datepalette.setText(this.dates[this.dateselected]);
  976. this.filterEntries();
  977. this.$.datepalette.switchPalette(app.otherview);
  978. },
  979. showSortPalette: function() {
  980. this.$.sortpalette.switchPalette(app.otherview);
  981. },
  982. tapSort: function(e, s) {
  983. this.sortfield = e.getId()-1;
  984. this.$.sortpalette.setIcon({directory: "icons", icon: this.sorts[this.sortfield].icon});
  985. this.filterEntries();
  986. this.$.sortpalette.switchPalette(app.otherview);
  987. },
  988. selectAll: function() {
  989. if (this.$.selallbutton.getDisabled()) {
  990. return;
  991. }
  992. app.otherview.selectAll();
  993. },
  994. unselectAll: function() {
  995. if (this.$.unselallbutton.getDisabled()) {
  996. return;
  997. }
  998. app.otherview.unselectAll();
  999. },
  1000. setSelectedCount: function(count, total) {
  1001. if (count <= 1) {
  1002. this.$.selectcount.setContent(l10n.get("Selected_one", {count: count, total: total}));
  1003. } else {
  1004. this.$.selectcount.setContent(l10n.get("Selected_other", {count: count, total: total}));
  1005. }
  1006. },
  1007. removeSelected: function() {
  1008. if (this.$.removebutton.getDisabled()) {
  1009. return;
  1010. }
  1011. this.disableMultiselectToolbarVisibility();
  1012. app.otherview.removeSelected();
  1013. },
  1014. copySelected: function(e, s) {
  1015. if (e.getDisabled()) {
  1016. return;
  1017. }
  1018. this.disableMultiselectToolbarVisibility();
  1019. var dest;
  1020. if (e.name == "copydevicebutton") {
  1021. dest = constant.journalDevice;
  1022. } else if (e.name == "copycloudonebutton") {
  1023. dest = constant.journalRemotePrivate;
  1024. } else if (e.name == "copycloudallbutton") {
  1025. dest = constant.journalRemoteShared;
  1026. } else {
  1027. dest = constant.journalLocal;
  1028. }
  1029. app.otherview.copySelected(dest);
  1030. },
  1031. fromDeviceSelected: function() {
  1032. if (util.getClientType() == constant.webAppType || (util.getClientType() == constant.appType && !enyo.platform.android && !enyo.platform.androidChrome && !enyo.platform.ios && !enyo.platform.electron)) {
  1033. this.$.file.setNodeProperty("accept", ".png,.jpg,.wav,.webm,.json,.mp3,.mp4,.pdf,.txt,.doc,.odt");
  1034. this.$.file.setNodeProperty("multiple", "true");
  1035. this.$.file.hasNode().click();
  1036. } else {
  1037. util.askFiles(function(file, err, metadata, text) {
  1038. if (err) {
  1039. humane.log(l10n.get("ErrorLoadingFile",{file:file}));
  1040. return;
  1041. }
  1042. metadata.timestamp = new Date().getTime();
  1043. metadata.creation_time = new Date().getTime();
  1044. datastore.create(metadata, function(err) {
  1045. if (err) {
  1046. humane.log(l10n.get("ErrorLoadingFile",{file:file}));
  1047. return;
  1048. }
  1049. app.otherview.loadLocalJournal();
  1050. if (preferences.isConnected()) {
  1051. app.otherview.syncJournal();
  1052. }
  1053. }, text);
  1054. });
  1055. }
  1056. },
  1057. fileSelected: function() {
  1058. var files = this.$.file.getNodeProperty("files");
  1059. for (var i = 0 ; i < files.length ; i++) {
  1060. util.loadFile(files[i], function(file, err, metadata, text) {
  1061. if (err) {
  1062. humane.log(l10n.get("ErrorLoadingFile",{file:file}));
  1063. return;
  1064. }
  1065. metadata.timestamp = new Date().getTime();
  1066. metadata.creation_time = new Date().getTime();
  1067. datastore.create(metadata, function() {
  1068. app.otherview.loadLocalJournal();
  1069. if (preferences.isConnected()) {
  1070. app.otherview.syncJournal();
  1071. }
  1072. }, text);
  1073. });
  1074. }
  1075. },
  1076. // Compute filter
  1077. hasFilter: function() {
  1078. return this.$.journalsearch.getText() != ""
  1079. || this.$.favoritebutton.getColorized()
  1080. || this.typeselected > 0
  1081. || this.dateselected > 0;
  1082. },
  1083. getSortType: function() {
  1084. return this.sortfield;
  1085. },
  1086. filterEntries: function() {
  1087. var text = this.$.journalsearch.getText();
  1088. var favorite = this.$.favoritebutton.getColorized() ? true : undefined;
  1089. var selected = this.typeselected;
  1090. var typeselected = (selected <= 0 ? undefined : preferences.getActivities()[selected-1].id);
  1091. selected = this.dateselected;
  1092. var timeselected = (selected <= 0 ? undefined : util.getDateRange(selected).min);
  1093. var filtertext = 'q=' + text;
  1094. if (favorite) filtertext += '&favorite=true';
  1095. if (typeselected) filtertext += '&type=' + typeselected;
  1096. if (timeselected) filtertext += '&time=' + timeselected;
  1097. stats.trace(constant.viewNames[app.getView()], 'search', filtertext, null);
  1098. app.otherview.filterEntries(text, favorite, typeselected, timeselected, undefined, this.sortfield);
  1099. },
  1100. removeFilter: function() {
  1101. this.typeselected = 0;
  1102. this.$.typepalette.setIcon({directory: "icons", icon: "application-x-generic.svg"});
  1103. this.dateselected = 0;
  1104. this.sortfield = 0;
  1105. this.$.sortpalette.setIcon({directory: "icons", icon: "view-lastedit.svg"})
  1106. this.$.favoritebutton.setColorized(false);
  1107. this.$.journalsearch.setText("");
  1108. this.render();
  1109. },
  1110. setMultiselectToolbarVisibility: function(shown) {
  1111. if (this.$.typepalette.isOpen()) {
  1112. this.$.typepalette.switchPalette(app.otherview);
  1113. }
  1114. if (this.$.datepalette.isOpen()) {
  1115. this.$.datepalette.switchPalette(app.otherview);
  1116. }
  1117. if (this.$.sortpalette.isOpen()) {
  1118. this.$.sortpalette.switchPalette(app.otherview);
  1119. }
  1120. var journalType = app.otherview.getJournalType();
  1121. this.$.favoritebutton.setShowing(!shown);
  1122. this.$.journalsearch.setShowing(!shown);
  1123. this.$.radialbutton.setShowing(!shown);
  1124. this.$.typepalette.setShowing(!shown);
  1125. this.$.datepalette.setShowing(!shown);
  1126. this.$.sortpalette.setShowing(!shown);
  1127. this.$.split3.setShowing(!shown && journalType == constant.journalLocal);
  1128. this.$.fromdevicebutton.setShowing(!shown && journalType == constant.journalLocal);
  1129. this.$.split4.setShowing(!shown);
  1130. this.$.helpbutton.setShowing(!shown);
  1131. this.$.unselallbutton.setShowing(shown);
  1132. this.$.selallbutton.setShowing(shown);
  1133. this.$.split1.setShowing(shown);
  1134. this.$.removebutton.setShowing(shown);
  1135. this.$.copyjournalbutton.setShowing(shown && journalType != constant.journalLocal);
  1136. this.$.copycloudonebutton.setShowing(shown && journalType != constant.journalRemotePrivate && preferences.isConnected());
  1137. this.$.copycloudallbutton.setShowing(shown && journalType != constant.journalRemoteShared && preferences.isConnected());
  1138. this.$.copydevicebutton.setShowing(shown);
  1139. this.$.split2.setShowing(shown);
  1140. this.$.selectcount.setShowing(shown);
  1141. this.$.unselallbutton.setDisabled(!shown);
  1142. this.$.selallbutton.setDisabled(!shown);
  1143. this.$.removebutton.setDisabled(!shown);
  1144. this.$.copyjournalbutton.setDisabled(!shown);
  1145. this.$.copycloudonebutton.setDisabled(!shown);
  1146. this.$.copycloudallbutton.setDisabled(!shown);
  1147. this.$.copydevicebutton.setDisabled(!shown);
  1148. this.$.selectcount.addRemoveClass("journal-selectcount-disabled", !shown);
  1149. },
  1150. disableMultiselectToolbarVisibility: function() {
  1151. this.$.unselallbutton.setDisabled(true);
  1152. this.$.selallbutton.setDisabled(true);
  1153. this.$.removebutton.setDisabled(true);
  1154. this.$.copyjournalbutton.setDisabled(true);
  1155. this.$.copycloudonebutton.setDisabled(true);
  1156. this.$.copycloudallbutton.setDisabled(true);
  1157. this.$.copydevicebutton.setDisabled(true);
  1158. this.$.selectcount.addRemoveClass("journal-selectcount-disabled", true);
  1159. },
  1160. startTutorial: function() {
  1161. tutorial.setElement("favoritebutton", this.$.favoritebutton.getAttribute("id"));
  1162. tutorial.setElement("searchtext", this.$.journalsearch.getAttribute("id"));
  1163. tutorial.setElement("typeselect", this.$.typepalette.getAttribute("id"));
  1164. tutorial.setElement("timeselect", this.$.datepalette.getAttribute("id"));
  1165. tutorial.setElement("sortselect", this.$.sortpalette.getAttribute("id"));
  1166. tutorial.setElement("fromdevicebutton", this.$.fromdevicebutton.getAttribute("id"));
  1167. tutorial.setElement("radialbutton", this.$.radialbutton.getAttribute("id"));
  1168. stats.trace(constant.viewNames[app.getView()], 'tutorial', 'start', null);
  1169. tutorial.start();
  1170. }
  1171. });