Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: chrome/browser/resources/md_downloads/crisper.js

Issue 1428833005: MD Downloads: track downloads in C++, dispatch discrete JS updates (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: dpapad@ + asanka@ feedback + self-review Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 if (typeof Polymer == 'undefined') 5 if (typeof Polymer == 'undefined')
6 Polymer = {dom: 'shadow'}; 6 Polymer = {dom: 'shadow'};
7 else 7 else
8 console.error('Polymer is already defined.'); 8 console.error('Polymer is already defined.');
9 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 9 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
10 // Use of this source code is governed by a BSD-style license that can be 10 // Use of this source code is governed by a BSD-style license that can be
(...skipping 1513 matching lines...) Expand 10 before | Expand all | Expand 10 after
1524 * @param {string} chromeSendName 1524 * @param {string} chromeSendName
1525 * @return {function(string):void} A chrome.send() callback with curried name. 1525 * @return {function(string):void} A chrome.send() callback with curried name.
1526 */ 1526 */
1527 function chromeSendWithId(chromeSendName) { 1527 function chromeSendWithId(chromeSendName) {
1528 return function(id) { chrome.send(chromeSendName, [id]); }; 1528 return function(id) { chrome.send(chromeSendName, [id]); };
1529 } 1529 }
1530 1530
1531 /** @constructor */ 1531 /** @constructor */
1532 function ActionService() {} 1532 function ActionService() {}
1533 1533
1534 /**
1535 * @param {string} searchText Input typed by the user into a search box.
1536 * @return {Array<string>} A list of terms extracted from |searchText|.
1537 */
1538 ActionService.splitTerms = function(searchText) {
1539 /**
1540 * @param {string} s
1541 * @return {string} |s| without whitespace at the beginning or end.
1542 */
1543 function trim(s) { return s.trim(); }
1544
1545 /**
1546 * @param {string} s
1547 * @return {boolean} Whether |s| is empty.
1548 */
1549 function notEmpty(s) { return s.length > 0; }
1550
1551 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']).
1552 return searchText.split(/"([^"]*)"/).map(trim).filter(notEmpty);
1553 };
1554
1534 ActionService.prototype = { 1555 ActionService.prototype = {
1535 /** @param {string} id ID of the download to cancel. */ 1556 /** @param {string} id ID of the download to cancel. */
1536 cancel: chromeSendWithId('cancel'), 1557 cancel: chromeSendWithId('cancel'),
1537 1558
1538 /** Instructs the browser to clear all finished downloads. */ 1559 /** Instructs the browser to clear all finished downloads. */
1539 clearAll: function() { 1560 clearAll: function() {
1540 if (loadTimeData.getBoolean('allowDeletingHistory')) { 1561 if (loadTimeData.getBoolean('allowDeletingHistory')) {
1541 chrome.send('clearAll'); 1562 chrome.send('clearAll');
1542 this.search(''); 1563 this.search('');
1543 } 1564 }
(...skipping 11 matching lines...) Expand all
1555 }, 1576 },
1556 1577
1557 /** @param {string} id ID of the download that the user started dragging. */ 1578 /** @param {string} id ID of the download that the user started dragging. */
1558 drag: chromeSendWithId('drag'), 1579 drag: chromeSendWithId('drag'),
1559 1580
1560 /** 1581 /**
1561 * @return {boolean} Whether the user is currently searching for downloads 1582 * @return {boolean} Whether the user is currently searching for downloads
1562 * (i.e. has a non-empty search term). 1583 * (i.e. has a non-empty search term).
1563 */ 1584 */
1564 isSearching: function() { 1585 isSearching: function() {
1565 return this.searchText_.length > 0; 1586 return !!this.searchText_;
1566 }, 1587 },
1567 1588
1568 /** Opens the current local destination for downloads. */ 1589 /** Opens the current local destination for downloads. */
1569 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'), 1590 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'),
1570 1591
1571 /** 1592 /**
1572 * @param {string} id ID of the download to run locally on the user's box. 1593 * @param {string} id ID of the download to run locally on the user's box.
1573 */ 1594 */
1574 openFile: chromeSendWithId('openFile'), 1595 openFile: chromeSendWithId('openFile'),
1575 1596
(...skipping 11 matching lines...) Expand all
1587 * warnings. 1608 * warnings.
1588 */ 1609 */
1589 saveDangerous: chromeSendWithId('saveDangerous'), 1610 saveDangerous: chromeSendWithId('saveDangerous'),
1590 1611
1591 /** @param {string} searchText What to search for. */ 1612 /** @param {string} searchText What to search for. */
1592 search: function(searchText) { 1613 search: function(searchText) {
1593 if (this.searchText_ == searchText) 1614 if (this.searchText_ == searchText)
1594 return; 1615 return;
1595 1616
1596 this.searchText_ = searchText; 1617 this.searchText_ = searchText;
1597 1618 chrome.send('getDownloads', ActionService.splitTerms(searchText));
1598 // Split quoted terms (e.g., 'The "lazy" dog' => ['The', 'lazy', 'dog']).
1599 function trim(s) { return s.trim(); }
1600 chrome.send('getDownloads', searchText.split(/"([^"]*)"/).map(trim));
1601 }, 1619 },
1602 1620
1603 /** 1621 /**
1604 * Shows the local folder a finished download resides in. 1622 * Shows the local folder a finished download resides in.
1605 * @param {string} id ID of the download to show. 1623 * @param {string} id ID of the download to show.
1606 */ 1624 */
1607 show: chromeSendWithId('show'), 1625 show: chromeSendWithId('show'),
1608 1626
1609 /** Undo download removal. */ 1627 /** Undo download removal. */
1610 undo: chrome.send.bind(chrome, 'undo'), 1628 undo: chrome.send.bind(chrome, 'undo'),
(...skipping 15319 matching lines...) Expand 10 before | Expand all | Expand 10 after
16930 // Copyright 2015 The Chromium Authors. All rights reserved. 16948 // Copyright 2015 The Chromium Authors. All rights reserved.
16931 // Use of this source code is governed by a BSD-style license that can be 16949 // Use of this source code is governed by a BSD-style license that can be
16932 // found in the LICENSE file. 16950 // found in the LICENSE file.
16933 16951
16934 cr.define('downloads', function() { 16952 cr.define('downloads', function() {
16935 var Manager = Polymer({ 16953 var Manager = Polymer({
16936 is: 'downloads-manager', 16954 is: 'downloads-manager',
16937 16955
16938 properties: { 16956 properties: {
16939 hasDownloads_: { 16957 hasDownloads_: {
16958 observer: 'hasDownloadsChanged_',
16940 type: Boolean, 16959 type: Boolean,
16941 value: false,
16942 }, 16960 },
16943 16961
16944 items_: { 16962 items_: {
16945 type: Array, 16963 type: Array,
16964 value: function() { return []; },
16946 }, 16965 },
16947 }, 16966 },
16948 16967
16949 hostAttributes: { 16968 hostAttributes: {
16950 loading: true, 16969 loading: true,
16951 }, 16970 },
16952 16971
16972 observers: [
16973 'itemsChanged_(items_.*)',
16974 ],
16975
16976 /** @private */
16977 clearAll_: function() {
16978 this.set('items_', []);
16979 },
16980
16981 /** @private */
16982 hasDownloadsChanged_: function() {
16983 if (loadTimeData.getBoolean('allowDeletingHistory'))
16984 this.$.toolbar.downloadsShowing = this.hasDownloads_;
16985
16986 if (this.hasDownloads_) {
16987 this.$['downloads-list'].fire('iron-resize');
16988 } else {
16989 var isSearching = downloads.ActionService.getInstance().isSearching();
16990 var messageToShow = isSearching ? 'noSearchResults' : 'noDownloads';
16991 this.$['no-downloads'].querySelector('span').textContent =
16992 loadTimeData.getString(messageToShow);
16993 }
16994 },
16995
16996 /**
16997 * @param {number} index
16998 * @param {!Array<!downloads.Data>} list
16999 * @private
17000 */
17001 insertItems_: function(index, list) {
17002 this.splice.apply(this, ['items_', index, 0].concat(list));
17003 this.updateHideDates_(index, index + list.length);
17004 this.removeAttribute('loading');
17005 },
17006
17007 /** @private */
17008 itemsChanged_: function() {
17009 this.hasDownloads_ = this.items_.length > 0;
17010 },
17011
16953 /** 17012 /**
16954 * @param {Event} e 17013 * @param {Event} e
16955 * @private 17014 * @private
16956 */ 17015 */
16957 onCanExecute_: function(e) { 17016 onCanExecute_: function(e) {
16958 e = /** @type {cr.ui.CanExecuteEvent} */(e); 17017 e = /** @type {cr.ui.CanExecuteEvent} */(e);
16959 switch (e.command.id) { 17018 switch (e.command.id) {
16960 case 'undo-command': 17019 case 'undo-command':
16961 e.canExecute = this.$.toolbar.canUndo(); 17020 e.canExecute = this.$.toolbar.canUndo();
16962 break; 17021 break;
(...skipping 18 matching lines...) Expand all
16981 onLoad_: function() { 17040 onLoad_: function() {
16982 cr.ui.decorate('command', cr.ui.Command); 17041 cr.ui.decorate('command', cr.ui.Command);
16983 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); 17042 document.addEventListener('canExecute', this.onCanExecute_.bind(this));
16984 document.addEventListener('command', this.onCommand_.bind(this)); 17043 document.addEventListener('command', this.onCommand_.bind(this));
16985 17044
16986 // Shows all downloads. 17045 // Shows all downloads.
16987 downloads.ActionService.getInstance().search(''); 17046 downloads.ActionService.getInstance().search('');
16988 }, 17047 },
16989 17048
16990 /** 17049 /**
16991 * @return {number} The number of downloads shown on the page. 17050 * @param {number} index
16992 * @private 17051 * @private
16993 */ 17052 */
16994 size_: function() { 17053 removeItem_: function(index) {
16995 return this.items_.length; 17054 this.splice('items_', index, 1);
17055 this.updateHideDates_(index, index);
16996 }, 17056 },
16997 17057
16998 /** 17058 /**
16999 * Called when all items need to be updated. 17059 * @param {number} start
17000 * @param {!Array<!downloads.Data>} list A list of new download data. 17060 * @param {number} end
17001 * @private 17061 * @private
17002 */ 17062 */
17003 updateAll_: function(list) { 17063 updateHideDates_: function(start, end) {
17004 /** @private {!Object<number>} */ 17064 for (var i = start; i <= end; ++i) {
17005 this.idToIndex_ = {}; 17065 var current = this.items_[i];
17006 17066 if (!current)
17007 for (var i = 0; i < list.length; ++i) { 17067 continue;
17008 var data = list[i]; 17068 var prev = this.items_[i - 1];
17009 17069 current.hideDate = !!prev && prev.date_string == current.date_string;
17010 this.idToIndex_[data.id] = data.index = i;
17011
17012 var prev = list[i - 1];
17013 data.hideDate = !!prev && prev.date_string == data.date_string;
17014 } 17070 }
17015
17016 // TODO(dbeam): this resets the scroll position, which is a huge bummer.
17017 // Removing something from the bottom of the list should not scroll you
17018 // back to the top. The grand plan is to restructure how the C++ sends the
17019 // JS data so that it only gets updates (rather than the most recent set
17020 // of items). TL;DR - we can't ship with this bug.
17021 this.items_ = list;
17022
17023 var hasDownloads = this.size_() > 0;
17024 if (!hasDownloads) {
17025 var isSearching = downloads.ActionService.getInstance().isSearching();
17026 var messageToShow = isSearching ? 'noSearchResults' : 'noDownloads';
17027 this.$['no-downloads'].querySelector('span').textContent =
17028 loadTimeData.getString(messageToShow);
17029 }
17030 this.hasDownloads_ = hasDownloads;
17031
17032 if (loadTimeData.getBoolean('allowDeletingHistory'))
17033 this.$.toolbar.downloadsShowing = this.hasDownloads_;
17034
17035 this.removeAttribute('loading');
17036 }, 17071 },
17037 17072
17038 /** 17073 /**
17074 * @param {number} index
17039 * @param {!downloads.Data} data 17075 * @param {!downloads.Data} data
17040 * @private 17076 * @private
17041 */ 17077 */
17042 updateItem_: function(data) { 17078 updateItem_: function(index, data) {
17043 var index = this.idToIndex_[data.id];
17044 this.set('items_.' + index, data); 17079 this.set('items_.' + index, data);
17080 this.updateHideDates_(index, index);
17045 this.$['downloads-list'].updateSizeForItem(index); 17081 this.$['downloads-list'].updateSizeForItem(index);
17046 }, 17082 },
17047 }); 17083 });
17048 17084
17049 Manager.size = function() { 17085 Manager.clearAll = function() {
17050 return document.querySelector('downloads-manager').size_(); 17086 Manager.get().clearAll_();
17051 }; 17087 };
17052 17088
17053 Manager.updateAll = function(list) { 17089 /** @return {!downloads.Manager} */
17054 document.querySelector('downloads-manager').updateAll_(list); 17090 Manager.get = function() {
17091 return queryRequiredElement('downloads-manager');
17055 }; 17092 };
17056 17093
17057 Manager.updateItem = function(item) { 17094 Manager.insertItems = function(index, list) {
17058 document.querySelector('downloads-manager').updateItem_(item); 17095 Manager.get().insertItems_(index, list);
17059 }; 17096 };
17060 17097
17061 Manager.onLoad = function() { 17098 Manager.onLoad = function() {
17062 document.querySelector('downloads-manager').onLoad_(); 17099 Manager.get().onLoad_();
17100 };
17101
17102 Manager.removeItem = function(index) {
17103 Manager.get().removeItem_(index);
17104 };
17105
17106 Manager.updateItem = function(index, data) {
17107 Manager.get().updateItem_(index, data);
17063 }; 17108 };
17064 17109
17065 return {Manager: Manager}; 17110 return {Manager: Manager};
17066 }); 17111 });
17067 // Copyright 2015 The Chromium Authors. All rights reserved. 17112 // Copyright 2015 The Chromium Authors. All rights reserved.
17068 // Use of this source code is governed by a BSD-style license that can be 17113 // Use of this source code is governed by a BSD-style license that can be
17069 // found in the LICENSE file. 17114 // found in the LICENSE file.
17070 17115
17071 window.addEventListener('load', downloads.Manager.onLoad); 17116 window.addEventListener('load', downloads.Manager.onLoad);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698