| 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 |