Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 /** | 5 /** |
| 6 * @fileoverview Listener functions which translate events from the | 6 * @fileoverview Listener functions which translate events from the |
| 7 * chrome.bookmarks API into actions to modify the local page state. | 7 * chrome.bookmarks API into actions to modify the local page state. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 cr.define('bookmarks.ApiListener', function() { | 10 cr.define('bookmarks.ApiListener', function() { |
| 11 | 11 |
| 12 /** @type {?number} */ | 12 /** @type {?number} */ |
| 13 var timerHandle; | 13 var timerHandle; |
| 14 /** @type {boolean} */ | |
| 15 var trackUpdates = false; | |
| 16 /** @type {!Array<string>} */ | |
| 17 var updatedItems = []; | |
| 18 /** @type {boolean} */ | |
| 19 var shouldHighlightAfterBatch = false; | |
|
calamity
2017/07/20 05:49:03
As discussed, it would be nice to have a resettabl
tsergeant
2017/07/25 00:13:00
Done.
| |
| 14 | 20 |
| 15 /** | 21 /** |
| 16 * Batches UI updates so that no changes will be made to UI until the next | 22 * Batches UI updates so that no changes will be made to UI until the next |
| 17 * task after the last call to this method. This is useful for listeners which | 23 * task after the last call to this method. This is useful for listeners which |
| 18 * can be called in a tight loop by UI actions. | 24 * can be called in a tight loop by UI actions. |
| 19 */ | 25 */ |
| 20 function batchUIUpdates() { | 26 function batchUIUpdates() { |
| 21 if (timerHandle) | 27 if (timerHandle) |
| 22 clearTimeout(timerHandle); | 28 clearTimeout(timerHandle); |
| 23 else | 29 else |
| 24 bookmarks.Store.getInstance().beginBatchUpdate(); | 30 bookmarks.Store.getInstance().beginBatchUpdate(); |
| 25 | 31 |
| 26 timerHandle = setTimeout(function() { | 32 timerHandle = setTimeout(function() { |
| 27 bookmarks.Store.getInstance().endBatchUpdate(); | 33 bookmarks.Store.getInstance().endBatchUpdate(); |
| 28 timerHandle = null; | 34 timerHandle = null; |
| 35 | |
| 36 if (shouldHighlightAfterBatch) | |
| 37 highlightUpdatedItemsImpl(); | |
| 29 }); | 38 }); |
| 30 } | 39 } |
| 31 | 40 |
| 41 /** | |
| 42 * Tracks any items that are created or moved. | |
| 43 */ | |
| 44 function trackUpdatedItems() { | |
| 45 trackUpdates = true; | |
| 46 } | |
| 47 | |
| 48 function highlightUpdatedItemsImpl() { | |
| 49 if (!trackUpdates) | |
| 50 return; | |
| 51 | |
| 52 document.dispatchEvent(new CustomEvent('highlight-items', { | |
| 53 detail: updatedItems, | |
| 54 })); | |
| 55 updatedItems = []; | |
| 56 trackUpdates = false; | |
| 57 shouldHighlightAfterBatch = false; | |
| 58 } | |
| 59 | |
| 60 /** | |
| 61 * Highlights any items that have been updated since |trackUpdatedItems| was | |
| 62 * called. Should be called after a user action causes new items to appear in | |
| 63 * the main list. | |
| 64 */ | |
| 65 function highlightUpdatedItems() { | |
| 66 // Ensure that the items are highlighted after the current batch update (if | |
| 67 // there is one) is completed. | |
| 68 if (timerHandle) | |
| 69 shouldHighlightAfterBatch = true; | |
| 70 else | |
| 71 highlightUpdatedItemsImpl(); | |
| 72 } | |
| 73 | |
| 32 /** @param {Action} action */ | 74 /** @param {Action} action */ |
| 33 function dispatch(action) { | 75 function dispatch(action) { |
| 34 bookmarks.Store.getInstance().dispatch(action); | 76 bookmarks.Store.getInstance().dispatch(action); |
| 35 } | 77 } |
| 36 | 78 |
| 37 /** | 79 /** |
| 38 * @param {string} id | 80 * @param {string} id |
| 39 * @param {{title: string, url: (string|undefined)}} changeInfo | 81 * @param {{title: string, url: (string|undefined)}} changeInfo |
| 40 */ | 82 */ |
| 41 function onBookmarkChanged(id, changeInfo) { | 83 function onBookmarkChanged(id, changeInfo) { |
| 42 dispatch(bookmarks.actions.editBookmark(id, changeInfo)); | 84 dispatch(bookmarks.actions.editBookmark(id, changeInfo)); |
| 43 } | 85 } |
| 44 | 86 |
| 45 /** | 87 /** |
| 46 * @param {string} id | 88 * @param {string} id |
| 47 * @param {BookmarkTreeNode} treeNode | 89 * @param {BookmarkTreeNode} treeNode |
| 48 */ | 90 */ |
| 49 function onBookmarkCreated(id, treeNode) { | 91 function onBookmarkCreated(id, treeNode) { |
| 50 batchUIUpdates(); | 92 batchUIUpdates(); |
| 93 if (trackUpdatedItems) | |
| 94 updatedItems.push(id); | |
| 51 dispatch(bookmarks.actions.createBookmark(id, treeNode)); | 95 dispatch(bookmarks.actions.createBookmark(id, treeNode)); |
| 52 } | 96 } |
| 53 | 97 |
| 54 /** | 98 /** |
| 55 * @param {string} id | 99 * @param {string} id |
| 56 * @param {{parentId: string, index: number}} removeInfo | 100 * @param {{parentId: string, index: number}} removeInfo |
| 57 */ | 101 */ |
| 58 function onBookmarkRemoved(id, removeInfo) { | 102 function onBookmarkRemoved(id, removeInfo) { |
| 59 batchUIUpdates(); | 103 batchUIUpdates(); |
| 60 var nodes = bookmarks.Store.getInstance().data.nodes; | 104 var nodes = bookmarks.Store.getInstance().data.nodes; |
| 61 dispatch(bookmarks.actions.removeBookmark( | 105 dispatch(bookmarks.actions.removeBookmark( |
| 62 id, removeInfo.parentId, removeInfo.index, nodes)); | 106 id, removeInfo.parentId, removeInfo.index, nodes)); |
| 63 } | 107 } |
| 64 | 108 |
| 65 /** | 109 /** |
| 66 * @param {string} id | 110 * @param {string} id |
| 67 * @param {{ | 111 * @param {{ |
| 68 * parentId: string, | 112 * parentId: string, |
| 69 * index: number, | 113 * index: number, |
| 70 * oldParentId: string, | 114 * oldParentId: string, |
| 71 * oldIndex: number | 115 * oldIndex: number |
| 72 * }} moveInfo | 116 * }} moveInfo |
| 73 */ | 117 */ |
| 74 function onBookmarkMoved(id, moveInfo) { | 118 function onBookmarkMoved(id, moveInfo) { |
| 75 batchUIUpdates(); | 119 batchUIUpdates(); |
| 120 if (trackUpdatedItems) | |
| 121 updatedItems.push(id); | |
| 76 dispatch(bookmarks.actions.moveBookmark( | 122 dispatch(bookmarks.actions.moveBookmark( |
| 77 id, moveInfo.parentId, moveInfo.index, moveInfo.oldParentId, | 123 id, moveInfo.parentId, moveInfo.index, moveInfo.oldParentId, |
| 78 moveInfo.oldIndex)); | 124 moveInfo.oldIndex)); |
| 79 } | 125 } |
| 80 | 126 |
| 81 /** | 127 /** |
| 82 * @param {string} id | 128 * @param {string} id |
| 83 * @param {{childIds: !Array<string>}} reorderInfo | 129 * @param {{childIds: !Array<string>}} reorderInfo |
| 84 */ | 130 */ |
| 85 function onChildrenReordered(id, reorderInfo) { | 131 function onChildrenReordered(id, reorderInfo) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 109 dispatch(bookmarks.actions.setIncognitoAvailability(availability)); | 155 dispatch(bookmarks.actions.setIncognitoAvailability(availability)); |
| 110 } | 156 } |
| 111 | 157 |
| 112 /** | 158 /** |
| 113 * @param {boolean} canEdit | 159 * @param {boolean} canEdit |
| 114 */ | 160 */ |
| 115 function onCanEditBookmarksChanged(canEdit) { | 161 function onCanEditBookmarksChanged(canEdit) { |
| 116 dispatch(bookmarks.actions.setCanEditBookmarks(canEdit)); | 162 dispatch(bookmarks.actions.setCanEditBookmarks(canEdit)); |
| 117 } | 163 } |
| 118 | 164 |
| 165 var listeners = [ | |
| 166 {api: chrome.bookmarks.onChanged, fn: onBookmarkChanged}, | |
| 167 {api: chrome.bookmarks.onChildrenReordered, fn: onChildrenReordered}, | |
| 168 {api: chrome.bookmarks.onCreated, fn: onBookmarkCreated}, | |
| 169 {api: chrome.bookmarks.onMoved, fn: onBookmarkMoved}, | |
| 170 {api: chrome.bookmarks.onRemoved, fn: onBookmarkRemoved}, | |
| 171 {api: chrome.bookmarks.onImportBegan, fn: onImportBegan}, | |
| 172 {api: chrome.bookmarks.onImportEnded, fn: onImportEnded}, | |
| 173 ]; | |
| 174 | |
| 119 function init() { | 175 function init() { |
| 120 chrome.bookmarks.onChanged.addListener(onBookmarkChanged); | 176 listeners.forEach((listener) => listener.api.addListener(listener.fn)); |
| 121 chrome.bookmarks.onChildrenReordered.addListener(onChildrenReordered); | |
| 122 chrome.bookmarks.onCreated.addListener(onBookmarkCreated); | |
| 123 chrome.bookmarks.onMoved.addListener(onBookmarkMoved); | |
| 124 chrome.bookmarks.onRemoved.addListener(onBookmarkRemoved); | |
| 125 chrome.bookmarks.onImportBegan.addListener(onImportBegan); | |
| 126 chrome.bookmarks.onImportEnded.addListener(onImportEnded); | |
| 127 | 177 |
| 128 cr.sendWithPromise('getIncognitoAvailability') | 178 cr.sendWithPromise('getIncognitoAvailability') |
| 129 .then(onIncognitoAvailabilityChanged); | 179 .then(onIncognitoAvailabilityChanged); |
| 130 cr.addWebUIListener( | 180 cr.addWebUIListener( |
| 131 'incognito-availability-changed', onIncognitoAvailabilityChanged); | 181 'incognito-availability-changed', onIncognitoAvailabilityChanged); |
| 132 | 182 |
| 133 cr.sendWithPromise('getCanEditBookmarks').then(onCanEditBookmarksChanged); | 183 cr.sendWithPromise('getCanEditBookmarks').then(onCanEditBookmarksChanged); |
| 134 cr.addWebUIListener( | 184 cr.addWebUIListener( |
| 135 'can-edit-bookmarks-changed', onCanEditBookmarksChanged); | 185 'can-edit-bookmarks-changed', onCanEditBookmarksChanged); |
| 136 } | 186 } |
| 137 | 187 |
| 188 function destroy() { | |
| 189 listeners.forEach((listener) => listener.api.removeListener(listener.fn)); | |
| 190 cr.removeWebUIListener( | |
| 191 'incognito-availability-changed', onIncognitoAvailabilityChanged); | |
| 192 cr.removeWebUIListener( | |
| 193 'can-edit-bookmarks-changed', onCanEditBookmarksChanged); | |
| 194 } | |
| 195 | |
| 138 return { | 196 return { |
| 139 init: init, | 197 init: init, |
| 198 destroy: destroy, | |
| 199 trackUpdatedItems: trackUpdatedItems, | |
| 200 highlightUpdatedItems: highlightUpdatedItems, | |
| 140 }; | 201 }; |
| 141 }); | 202 }); |
| OLD | NEW |