OLD | NEW |
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 Loading... |
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 | |
1555 ActionService.prototype = { | 1534 ActionService.prototype = { |
1556 /** @param {string} id ID of the download to cancel. */ | 1535 /** @param {string} id ID of the download to cancel. */ |
1557 cancel: chromeSendWithId('cancel'), | 1536 cancel: chromeSendWithId('cancel'), |
1558 | 1537 |
1559 /** Instructs the browser to clear all finished downloads. */ | 1538 /** Instructs the browser to clear all finished downloads. */ |
1560 clearAll: function() { | 1539 clearAll: function() { |
1561 if (loadTimeData.getBoolean('allowDeletingHistory')) { | 1540 if (loadTimeData.getBoolean('allowDeletingHistory')) { |
1562 chrome.send('clearAll'); | 1541 chrome.send('clearAll'); |
1563 this.search(''); | 1542 this.search(''); |
1564 } | 1543 } |
(...skipping 11 matching lines...) Expand all Loading... |
1576 }, | 1555 }, |
1577 | 1556 |
1578 /** @param {string} id ID of the download that the user started dragging. */ | 1557 /** @param {string} id ID of the download that the user started dragging. */ |
1579 drag: chromeSendWithId('drag'), | 1558 drag: chromeSendWithId('drag'), |
1580 | 1559 |
1581 /** | 1560 /** |
1582 * @return {boolean} Whether the user is currently searching for downloads | 1561 * @return {boolean} Whether the user is currently searching for downloads |
1583 * (i.e. has a non-empty search term). | 1562 * (i.e. has a non-empty search term). |
1584 */ | 1563 */ |
1585 isSearching: function() { | 1564 isSearching: function() { |
1586 return !!this.searchText_; | 1565 return this.searchText_.length > 0; |
1587 }, | 1566 }, |
1588 | 1567 |
1589 /** Opens the current local destination for downloads. */ | 1568 /** Opens the current local destination for downloads. */ |
1590 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'), | 1569 openDownloadsFolder: chrome.send.bind(chrome, 'openDownloadsFolder'), |
1591 | 1570 |
1592 /** | 1571 /** |
1593 * @param {string} id ID of the download to run locally on the user's box. | 1572 * @param {string} id ID of the download to run locally on the user's box. |
1594 */ | 1573 */ |
1595 openFile: chromeSendWithId('openFile'), | 1574 openFile: chromeSendWithId('openFile'), |
1596 | 1575 |
(...skipping 11 matching lines...) Expand all Loading... |
1608 * warnings. | 1587 * warnings. |
1609 */ | 1588 */ |
1610 saveDangerous: chromeSendWithId('saveDangerous'), | 1589 saveDangerous: chromeSendWithId('saveDangerous'), |
1611 | 1590 |
1612 /** @param {string} searchText What to search for. */ | 1591 /** @param {string} searchText What to search for. */ |
1613 search: function(searchText) { | 1592 search: function(searchText) { |
1614 if (this.searchText_ == searchText) | 1593 if (this.searchText_ == searchText) |
1615 return; | 1594 return; |
1616 | 1595 |
1617 this.searchText_ = searchText; | 1596 this.searchText_ = searchText; |
1618 chrome.send('getDownloads', ActionService.splitTerms(searchText)); | 1597 |
| 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)); |
1619 }, | 1601 }, |
1620 | 1602 |
1621 /** | 1603 /** |
1622 * Shows the local folder a finished download resides in. | 1604 * Shows the local folder a finished download resides in. |
1623 * @param {string} id ID of the download to show. | 1605 * @param {string} id ID of the download to show. |
1624 */ | 1606 */ |
1625 show: chromeSendWithId('show'), | 1607 show: chromeSendWithId('show'), |
1626 | 1608 |
1627 /** Undo download removal. */ | 1609 /** Undo download removal. */ |
1628 undo: chrome.send.bind(chrome, 'undo'), | 1610 undo: chrome.send.bind(chrome, 'undo'), |
(...skipping 15319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16948 // Copyright 2015 The Chromium Authors. All rights reserved. | 16930 // Copyright 2015 The Chromium Authors. All rights reserved. |
16949 // Use of this source code is governed by a BSD-style license that can be | 16931 // Use of this source code is governed by a BSD-style license that can be |
16950 // found in the LICENSE file. | 16932 // found in the LICENSE file. |
16951 | 16933 |
16952 cr.define('downloads', function() { | 16934 cr.define('downloads', function() { |
16953 var Manager = Polymer({ | 16935 var Manager = Polymer({ |
16954 is: 'downloads-manager', | 16936 is: 'downloads-manager', |
16955 | 16937 |
16956 properties: { | 16938 properties: { |
16957 hasDownloads_: { | 16939 hasDownloads_: { |
16958 observer: 'hasDownloadsChanged_', | |
16959 type: Boolean, | 16940 type: Boolean, |
| 16941 value: false, |
16960 }, | 16942 }, |
16961 | 16943 |
16962 items_: { | 16944 items_: { |
16963 type: Array, | 16945 type: Array, |
16964 value: function() { return []; }, | |
16965 }, | 16946 }, |
16966 }, | 16947 }, |
16967 | 16948 |
16968 hostAttributes: { | 16949 hostAttributes: { |
16969 loading: true, | 16950 loading: true, |
16970 }, | 16951 }, |
16971 | 16952 |
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 /** | 16953 /** |
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 | |
17012 /** | |
17013 * @param {Event} e | 16954 * @param {Event} e |
17014 * @private | 16955 * @private |
17015 */ | 16956 */ |
17016 onCanExecute_: function(e) { | 16957 onCanExecute_: function(e) { |
17017 e = /** @type {cr.ui.CanExecuteEvent} */(e); | 16958 e = /** @type {cr.ui.CanExecuteEvent} */(e); |
17018 switch (e.command.id) { | 16959 switch (e.command.id) { |
17019 case 'undo-command': | 16960 case 'undo-command': |
17020 e.canExecute = this.$.toolbar.canUndo(); | 16961 e.canExecute = this.$.toolbar.canUndo(); |
17021 break; | 16962 break; |
17022 case 'clear-all-command': | 16963 case 'clear-all-command': |
(...skipping 17 matching lines...) Expand all Loading... |
17040 onLoad_: function() { | 16981 onLoad_: function() { |
17041 cr.ui.decorate('command', cr.ui.Command); | 16982 cr.ui.decorate('command', cr.ui.Command); |
17042 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); | 16983 document.addEventListener('canExecute', this.onCanExecute_.bind(this)); |
17043 document.addEventListener('command', this.onCommand_.bind(this)); | 16984 document.addEventListener('command', this.onCommand_.bind(this)); |
17044 | 16985 |
17045 // Shows all downloads. | 16986 // Shows all downloads. |
17046 downloads.ActionService.getInstance().search(''); | 16987 downloads.ActionService.getInstance().search(''); |
17047 }, | 16988 }, |
17048 | 16989 |
17049 /** | 16990 /** |
17050 * @param {number} index | 16991 * @return {number} The number of downloads shown on the page. |
17051 * @private | 16992 * @private |
17052 */ | 16993 */ |
17053 removeItem_: function(index) { | 16994 size_: function() { |
17054 this.splice('items_', index, 1); | 16995 return this.items_.length; |
17055 this.updateHideDates_(index, index); | |
17056 }, | 16996 }, |
17057 | 16997 |
17058 /** | 16998 /** |
17059 * @param {number} start | 16999 * Called when all items need to be updated. |
17060 * @param {number} end | 17000 * @param {!Array<!downloads.Data>} list A list of new download data. |
17061 * @private | 17001 * @private |
17062 */ | 17002 */ |
17063 updateHideDates_: function(start, end) { | 17003 updateAll_: function(list) { |
17064 for (var i = start; i <= end; ++i) { | 17004 /** @private {!Object<number>} */ |
17065 var current = this.items_[i]; | 17005 this.idToIndex_ = {}; |
17066 if (!current) | 17006 |
17067 continue; | 17007 for (var i = 0; i < list.length; ++i) { |
17068 var prev = this.items_[i - 1]; | 17008 var data = list[i]; |
17069 current.hideDate = !!prev && prev.date_string == current.date_string; | 17009 |
| 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; |
17070 } | 17014 } |
| 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'); |
17071 }, | 17036 }, |
17072 | 17037 |
17073 /** | 17038 /** |
17074 * @param {number} index | |
17075 * @param {!downloads.Data} data | 17039 * @param {!downloads.Data} data |
17076 * @private | 17040 * @private |
17077 */ | 17041 */ |
17078 updateItem_: function(index, data) { | 17042 updateItem_: function(data) { |
| 17043 var index = this.idToIndex_[data.id]; |
17079 this.set('items_.' + index, data); | 17044 this.set('items_.' + index, data); |
17080 this.updateHideDates_(index, index); | |
17081 this.$['downloads-list'].updateSizeForItem(index); | 17045 this.$['downloads-list'].updateSizeForItem(index); |
17082 }, | 17046 }, |
17083 }); | 17047 }); |
17084 | 17048 |
17085 Manager.clearAll = function() { | 17049 Manager.size = function() { |
17086 Manager.get().clearAll_(); | 17050 return document.querySelector('downloads-manager').size_(); |
17087 }; | 17051 }; |
17088 | 17052 |
17089 /** @return {!downloads.Manager} */ | 17053 Manager.updateAll = function(list) { |
17090 Manager.get = function() { | 17054 document.querySelector('downloads-manager').updateAll_(list); |
17091 return queryRequiredElement('downloads-manager'); | |
17092 }; | 17055 }; |
17093 | 17056 |
17094 Manager.insertItems = function(index, list) { | 17057 Manager.updateItem = function(item) { |
17095 Manager.get().insertItems_(index, list); | 17058 document.querySelector('downloads-manager').updateItem_(item); |
17096 }; | 17059 }; |
17097 | 17060 |
17098 Manager.onLoad = function() { | 17061 Manager.onLoad = function() { |
17099 Manager.get().onLoad_(); | 17062 document.querySelector('downloads-manager').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); | |
17108 }; | 17063 }; |
17109 | 17064 |
17110 return {Manager: Manager}; | 17065 return {Manager: Manager}; |
17111 }); | 17066 }); |
17112 // Copyright 2015 The Chromium Authors. All rights reserved. | 17067 // Copyright 2015 The Chromium Authors. All rights reserved. |
17113 // Use of this source code is governed by a BSD-style license that can be | 17068 // Use of this source code is governed by a BSD-style license that can be |
17114 // found in the LICENSE file. | 17069 // found in the LICENSE file. |
17115 | 17070 |
17116 window.addEventListener('load', downloads.Manager.onLoad); | 17071 window.addEventListener('load', downloads.Manager.onLoad); |
OLD | NEW |