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

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: calamity@ review 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);
25 };
26
27 /**
28 * @param {NodeList} nodes
29 * @param {Action} action
30 * @return {NodeList}
31 */
32 NodeState.editBookmark = function(nodes, action) {
33 // Do not allow folders to change URL (making them no longer folders).
34 if (!nodes[action.id].url && action.changeInfo.url)
35 delete action.changeInfo.url;
36
37 return NodeState.modifyNode_(nodes, action.id, function(node) {
38 return /** @type {BookmarkNode} */ (
39 Object.assign({}, node, action.changeInfo));
40 });
41 };
42
43 /**
44 * @param {NodeList} nodes
45 * @param {Action} action
46 * @return {NodeList}
47 */
48 NodeState.removeBookmark = function(nodes, action) {
49 return NodeState.modifyNode_(nodes, action.parentId, function(node) {
50 var newChildren = node.children.slice();
51 newChildren.splice(action.index, 1);
52 return /** @type {BookmarkNode} */ (
53 Object.assign({}, node, {children: newChildren}));
54 });
55 };
56
57 /**
58 * @param {NodeList} nodes
59 * @param {Action} action
60 * @return {NodeList}
61 */
62 NodeState.updateNodes = function(nodes, action) {
63 switch (action.name) {
64 case 'edit-bookmark':
65 return NodeState.editBookmark(nodes, action);
66 case 'remove-bookmark':
67 return NodeState.removeBookmark(nodes, action);
68 case 'refresh-nodes':
69 return action.nodes;
70 default:
71 return nodes;
72 }
73 };
74
75 var SelectedFolderState = {};
76
77 /**
78 * @param {NodeList} nodes
79 * @param {string} ancestorId
80 * @param {string} childId
81 * @return {boolean}
82 */
83 SelectedFolderState.isAncestorOf = function(nodes, ancestorId, childId) {
84 var currentId = childId;
85 // Work upwards through the tree from child.
86 while (currentId) {
87 if (currentId == ancestorId)
88 return true;
89 currentId = nodes[currentId].parentId;
90 }
91 return false;
92 };
93
94 /**
95 * @param {?string} selectedFolder
96 * @param {Action} action
97 * @param {NodeList} nodes
98 * @return {?string}
99 */
100 SelectedFolderState.updateSelectedFolder = function(
101 selectedFolder, action, nodes) {
102 // TODO(tsergeant): It should not be possible to select a non-folder.
103 switch (action.name) {
104 case 'select-folder':
105 return action.id;
106 case 'change-folder-open':
107 // When hiding the selected folder by closing its ancestor, select
108 // that ancestor instead.
109 if (!action.open && selectedFolder &&
110 SelectedFolderState.isAncestorOf(
111 nodes, action.id, selectedFolder)) {
112 return action.id;
113 }
114 return selectedFolder;
115 default:
116 return selectedFolder;
117 }
118 };
119
120 var ClosedFolderState = {};
121
122 /**
123 * @param {ClosedFolderState} state
124 * @param {Action} action
125 * @param {NodeList} nodes
126 * @return {ClosedFolderState}
127 */
128 ClosedFolderState.openAncestorsOf = function(state, action, nodes) {
129 var id = action.id;
130 var modifications = {};
131 var parentId = nodes[id].parentId;
132 while (parentId) {
133 if (state[parentId]) {
134 modifications[parentId] = false;
135 }
136 parentId = nodes[parentId].parentId;
137 }
138
139 return Object.assign({}, state, modifications);
140 };
141
142 /**
143 * @param {ClosedFolderState} state
144 * @param {Action} action
145 * @return {ClosedFolderState}
146 */
147 ClosedFolderState.changeFolderOpen = function(state, action) {
148 var closed = !action.open;
149 var modification = {};
150 modification[action.id] = closed;
151
152 return Object.assign({}, state, modification);
153 };
154
155 /**
156 * @param {ClosedFolderState} state
157 * @param {Action} action
158 * @param {NodeList} nodes
159 * @return {ClosedFolderState}
160 */
161 ClosedFolderState.updateClosedFolders = function(state, action, nodes) {
162 switch (action.name) {
163 case 'change-folder-open':
164 return ClosedFolderState.changeFolderOpen(state, action);
165 case 'select-folder':
166 return ClosedFolderState.openAncestorsOf(state, action, nodes);
167 default:
168 return state;
169 };
170 };
171
13 /** 172 /**
14 * Root reducer for the Bookmarks page. This is called by the store in 173 * 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. 174 * response to an action, and the return value is used to update the UI.
16 * @param {!BookmarksPageState} state 175 * @param {!BookmarksPageState} state
17 * @param {Action} action 176 * @param {Action} action
18 * @return {!BookmarksPageState} 177 * @return {!BookmarksPageState}
19 */ 178 */
20 function reduceAction(state, action) { 179 function reduceAction(state, action) {
21 return {}; 180 return {
181 nodes: NodeState.updateNodes(state.nodes, action),
182 selectedFolder: SelectedFolderState.updateSelectedFolder(
183 state.selectedFolder, action, state.nodes),
184 closedFolders: ClosedFolderState.updateClosedFolders(
185 state.closedFolders, action, state.nodes),
186 };
22 } 187 }
23 188
24 return { 189 return {
25 reduceAction: reduceAction, 190 reduceAction: reduceAction,
191 ClosedFolderState: ClosedFolderState,
192 NodeState: NodeState,
193 SelectedFolderState: SelectedFolderState,
26 }; 194 };
27 }); 195 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698