Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: chrome/browser/resources/md_bookmarks/reducers.js

Issue 2733463002: MD Bookmarks: Add basic page features to new data-flow system (Closed)
Patch Set: Rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 Module of functions which produce a new page state in response 6 * @fileoverview Module of functions which produce a new page state in response
7 * to an action. Reducers (in the same sense as Array.prototype.reduce) must be 7 * to an action. Reducers (in the same sense as Array.prototype.reduce) must be
8 * pure functions: they must not modify existing state objects, or make any API 8 * pure functions: they must not modify existing state objects, or make any API
9 * calls. 9 * calls.
10 */ 10 */
11 11
12 cr.define('bookmarks', function() { 12 cr.define('bookmarks', function() {
13 var NodeState = {};
14
15 /**
16 * @param {NodeList} nodes
17 * @param {string} id
18 * @param {function(BookmarkNode):BookmarkNode} callback
19 * @return {NodeList}
20 */
21 NodeState.modifyNode_ = function(nodes, id, callback) {
22 var nodeModification = {};
23 nodeModification[id] = callback(nodes[id]);
24 return Object.assign({}, nodes, nodeModification);
calamity 2017/03/07 07:27:35 How does closure understand this?
tsergeant 2017/03/08 02:47:10 I would guess that here Closure sees that Object.a
25 };
26
27 /**
28 * @param {NodeList} nodes
29 * @param {Action} action
30 * @return {NodeList}
31 */
32 NodeState.editBookmark = function(nodes, action) {
33 return NodeState.modifyNode_(nodes, action.id, function(node) {
34 return /** @type {BookmarkNode} */ (
35 Object.assign({}, node, action.changeInfo));
calamity 2017/03/07 07:27:35 While it doesn't understand this.
tsergeant 2017/03/08 02:47:10 But here, it isn't able to convert Object to the s
calamity 2017/03/08 06:57:19 Ech.
36 });
37 };
38
39 /**
40 * @param {NodeList} nodes
41 * @param {Action} action
42 * @return {NodeList}
43 */
44 NodeState.removeBookmark = function(nodes, action) {
45 return NodeState.modifyNode_(nodes, action.parentId, function(node) {
46 var newChildren = node.children.slice();
47 newChildren.splice(action.index, 1);
48 return /** @type {BookmarkNode} */ (
49 Object.assign({}, node, {children: newChildren}));
50 });
51 };
52
53 /**
54 * @param {NodeList} nodes
55 * @param {Action} action
56 * @return {NodeList}
57 */
58 NodeState.updateNodes = function(nodes, action) {
59 switch (action.name) {
60 case 'edit-bookmark':
61 return NodeState.editBookmark(nodes, action);
62 case 'remove-bookmark':
63 return NodeState.removeBookmark(nodes, action);
64 case 'refresh-nodes':
65 return action.nodes;
66 default:
67 return nodes;
68 }
69 };
70
71 var SelectedFolderState = {};
72
73 /**
74 * @param {NodeList} nodes
75 * @param {string} ancestorId
76 * @param {string} childId
77 * @return {boolean}
78 */
79 SelectedFolderState.isAncestorOf = function(nodes, ancestorId, childId) {
80 var currentId = childId;
81 // Work upwards through the tree from child.
82 while (currentId) {
83 if (currentId == ancestorId)
84 return true;
85 currentId = nodes[currentId].parentId;
86 }
87 return false;
88 };
89
90 /**
91 * @param {?string} selectedFolder
92 * @param {Action} action
93 * @param {NodeList} nodes
94 * @return {?string}
95 */
96 SelectedFolderState.updateSelectedFolder = function(
97 selectedFolder, action, nodes) {
98 // TODO(tsergeant): It should not be possible to select a non-folder.
calamity 2017/03/07 07:27:35 What's the plan for this TODO? Are you just going
tsergeant 2017/03/08 02:47:10 I think that if you try to select a folder that ei
calamity 2017/03/08 06:57:19 I'd prefer throwing an exception over failing sile
tsergeant 2017/03/08 23:17:53 Yeah, maybe. I have a feeling we want to avoid ass
99 switch (action.name) {
100 case 'select-folder':
101 return action.id;
102 case 'change-folder-open':
103 // When hiding the selected folder by closing its ancestor, select
104 // that ancestor instead.
105 if (!action.open && selectedFolder &&
106 SelectedFolderState.isAncestorOf(
107 nodes, action.id, selectedFolder)) {
108 return action.id;
109 }
110 return selectedFolder;
111 default:
112 return selectedFolder;
113 }
114 };
115
116 var ClosedFolderState = {};
117
118 /**
119 * @param {ClosedFolderState} state
120 * @param {Action} action
121 * @param {NodeList} nodes
122 * @return {ClosedFolderState}
123 */
124 ClosedFolderState.openAncestorsOf = function(state, action, nodes) {
125 var id = action.id;
126 var modifications = {};
127 var parentId = nodes[id].parentId;
128 while (parentId) {
129 if (state[parentId]) {
130 modifications[parentId] = false;
131 }
132 parentId = nodes[parentId].parentId;
133 }
134
135 return Object.assign({}, state, modifications);
136 };
137
138 /**
139 * @param {ClosedFolderState} state
140 * @param {Action} action
141 * @return {ClosedFolderState}
142 */
143 ClosedFolderState.toggleFolderOpen = function(state, action) {
144 var id = action.id;
calamity 2017/03/07 07:27:35 nit: This var seems superfluous.
tsergeant 2017/03/08 02:47:10 Done.
145 var closed = !action.open;
146 var modification = {};
147 modification[id] = closed;
148
149 return Object.assign({}, state, modification);
150 };
151
152 /**
153 * @param {ClosedFolderState} state
154 * @param {Action} action
155 * @param {NodeList} nodes
156 * @return {ClosedFolderState}
157 */
158 ClosedFolderState.updateClosedFolders = function(state, action, nodes) {
159 switch (action.name) {
160 case 'change-folder-open':
161 return ClosedFolderState.toggleFolderOpen(state, action);
162 case 'select-folder':
163 return ClosedFolderState.openAncestorsOf(state, action, nodes);
164 default:
165 return state;
166 };
167 };
168
13 /** 169 /**
14 * Root reducer for the Bookmarks page. This is called by the store in 170 * Root reducer for the Bookmarks page. This is called by the store in
15 * response to an action, and the return value is used to update the UI. 171 * response to an action, and the return value is used to update the UI.
16 * @param {!BookmarksPageState} state 172 * @param {!BookmarksPageState} state
17 * @param {Action} action 173 * @param {Action} action
18 * @return {!BookmarksPageState} 174 * @return {!BookmarksPageState}
19 */ 175 */
20 function reduceAction(state, action) { 176 function reduceAction(state, action) {
21 return {}; 177 return {
178 nodes: NodeState.updateNodes(state.nodes, action),
179 selectedFolder: SelectedFolderState.updateSelectedFolder(
180 state.selectedFolder, action, state.nodes),
181 closedFolders: ClosedFolderState.updateClosedFolders(
182 state.closedFolders, action, state.nodes),
183 };
22 } 184 }
23 185
24 return { 186 return {
25 reduceAction: reduceAction, 187 reduceAction: reduceAction,
188 ClosedFolderState: ClosedFolderState,
189 NodeState: NodeState,
190 SelectedFolderState: SelectedFolderState,
26 }; 191 };
27 }); 192 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698