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 |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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); |
OLD | NEW |