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 A singleton datastore for the Bookmarks page. Page state is | 6 * @fileoverview A singleton datastore for the Bookmarks page. Page state is |
7 * publicly readable, but can only be modified by dispatching an Action to | 7 * publicly readable, but can only be modified by dispatching an Action to |
8 * the store. | 8 * the store. |
9 */ | 9 */ |
10 | 10 |
11 cr.define('bookmarks', function() { | 11 cr.define('bookmarks', function() { |
12 /** @constructor */ | 12 /** @constructor */ |
13 function Store() { | 13 function Store() { |
14 /** @type {!BookmarksPageState} */ | 14 /** @type {!BookmarksPageState} */ |
15 this.data_ = bookmarks.util.createEmptyState(); | 15 this.data_ = bookmarks.util.createEmptyState(); |
16 /** @type {boolean} */ | 16 /** @type {boolean} */ |
17 this.initialized_ = false; | 17 this.initialized_ = false; |
18 /** @type {!Array<DeferredAction>} */ | 18 /** @type {!Array<DeferredAction>} */ |
19 this.queuedActions_ = []; | 19 this.queuedActions_ = []; |
20 /** @type {!Array<!StoreObserver>} */ | 20 /** @type {!Array<!StoreObserver>} */ |
21 this.observers_ = []; | 21 this.observers_ = []; |
| 22 /** @private {boolean} */ |
| 23 this.batchMode_ = false; |
22 } | 24 } |
23 | 25 |
24 Store.prototype = { | 26 Store.prototype = { |
25 /** | 27 /** |
26 * @param {!BookmarksPageState} initialState | 28 * @param {!BookmarksPageState} initialState |
27 */ | 29 */ |
28 init: function(initialState) { | 30 init: function(initialState) { |
29 this.data_ = initialState; | 31 this.data_ = initialState; |
30 | 32 |
31 this.queuedActions_.forEach(function(action) { | 33 this.queuedActions_.forEach(function(action) { |
(...skipping 19 matching lines...) Expand all Loading... |
51 this.observers_.push(observer); | 53 this.observers_.push(observer); |
52 }, | 54 }, |
53 | 55 |
54 /** @param {!StoreObserver} observer */ | 56 /** @param {!StoreObserver} observer */ |
55 removeObserver: function(observer) { | 57 removeObserver: function(observer) { |
56 var index = this.observers_.indexOf(observer); | 58 var index = this.observers_.indexOf(observer); |
57 this.observers_.splice(index, 1); | 59 this.observers_.splice(index, 1); |
58 }, | 60 }, |
59 | 61 |
60 /** | 62 /** |
| 63 * Begin a batch update to store data, which will disable updates to the |
| 64 * UI until `endBatchUpdate` is called. This is useful when a single UI |
| 65 * operation is likely to cause many sequential model updates (eg, deleting |
| 66 * 100 bookmarks). |
| 67 */ |
| 68 beginBatchUpdate: function() { |
| 69 this.batchMode_ = true; |
| 70 }, |
| 71 |
| 72 /** |
| 73 * End a batch update to the store data, notifying the UI of any changes |
| 74 * which occurred while batch mode was enabled. |
| 75 */ |
| 76 endBatchUpdate: function() { |
| 77 this.batchMode_ = false; |
| 78 this.notifyObservers_(this.data); |
| 79 }, |
| 80 |
| 81 /** |
61 * Handles a 'deferred' action, which can asynchronously dispatch actions | 82 * Handles a 'deferred' action, which can asynchronously dispatch actions |
62 * to the Store in order to reach a new UI state. DeferredActions have the | 83 * to the Store in order to reach a new UI state. DeferredActions have the |
63 * form `dispatchAsync(function(dispatch) { ... })`). Inside that function, | 84 * form `dispatchAsync(function(dispatch) { ... })`). Inside that function, |
64 * the |dispatch| callback can be called asynchronously to dispatch Actions | 85 * the |dispatch| callback can be called asynchronously to dispatch Actions |
65 * directly to the Store. | 86 * directly to the Store. |
66 * @param {DeferredAction} action | 87 * @param {DeferredAction} action |
67 */ | 88 */ |
68 dispatchAsync: function(action) { | 89 dispatchAsync: function(action) { |
69 if (!this.initialized_) { | 90 if (!this.initialized_) { |
70 this.queuedActions_.push(action); | 91 this.queuedActions_.push(action); |
(...skipping 26 matching lines...) Expand all Loading... |
97 * @param {?Action} action | 118 * @param {?Action} action |
98 * @private | 119 * @private |
99 */ | 120 */ |
100 reduce_: function(action) { | 121 reduce_: function(action) { |
101 if (!action) | 122 if (!action) |
102 return; | 123 return; |
103 | 124 |
104 this.data_ = bookmarks.reduceAction(this.data_, action); | 125 this.data_ = bookmarks.reduceAction(this.data_, action); |
105 // Batch notifications until after all initialization queuedActions are | 126 // Batch notifications until after all initialization queuedActions are |
106 // resolved. | 127 // resolved. |
107 if (this.isInitialized()) | 128 if (this.isInitialized() && !this.batchMode_) |
108 this.notifyObservers_(this.data_); | 129 this.notifyObservers_(this.data_); |
109 }, | 130 }, |
110 | 131 |
111 /** | 132 /** |
112 * @param {!BookmarksPageState} state | 133 * @param {!BookmarksPageState} state |
113 * @private | 134 * @private |
114 */ | 135 */ |
115 notifyObservers_: function(state) { | 136 notifyObservers_: function(state) { |
116 this.observers_.forEach(function(o) { | 137 this.observers_.forEach(function(o) { |
117 o.onStateChanged(state); | 138 o.onStateChanged(state); |
118 }); | 139 }); |
119 }, | 140 }, |
120 }; | 141 }; |
121 | 142 |
122 cr.addSingletonGetter(Store); | 143 cr.addSingletonGetter(Store); |
123 | 144 |
124 return { | 145 return { |
125 Store: Store, | 146 Store: Store, |
126 }; | 147 }; |
127 }); | 148 }); |
OLD | NEW |