|
1 | | -import * as Parallel from 'async-parallel' |
2 | 1 | import Diff, { ActionType, CreateAction, MoveAction, RemoveAction, ReorderAction, UpdateAction } from './Diff' |
3 | 2 | import { Bookmark, Folder, ItemLocation, ItemType, TItem, TItemLocation } from './Tree' |
4 | 3 | import Logger from './Logger' |
@@ -121,58 +120,57 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation> |
121 | 120 | const stillUnmatched = new Set(newFolder.children) |
122 | 121 |
|
123 | 122 | // (using map here, because 'each' doesn't provide indices) |
124 | | - await Parallel.map( |
125 | | - oldFolder.children, |
126 | | - async(old, index) => { |
127 | | - const key = `${old.type}_${old.title}` |
128 | | - const potentialMatches = unmatchedMap.get(key) |
129 | | - let newItem = null |
130 | | - if (potentialMatches) { |
131 | | - const matchIndex = potentialMatches.findIndex((m) => |
132 | | - this.mergeable(old, m) |
133 | | - ) |
134 | | - if (matchIndex !== -1) { |
135 | | - newItem = potentialMatches.splice(matchIndex, 1)[0] |
136 | | - stillUnmatched.delete(newItem) |
137 | | - } |
138 | | - } |
139 | | - // we found an item in the new folder that matches the one in the old folder |
140 | | - if (newItem) { |
141 | | - await this.diffItem(old, newItem) |
142 | | - return |
| 123 | + let index = 0 |
| 124 | + for (const old of oldFolder.children) { |
| 125 | + const key = `${old.type}_${old.title}` |
| 126 | + const potentialMatches = unmatchedMap.get(key) |
| 127 | + let newItem = null |
| 128 | + if (potentialMatches) { |
| 129 | + const matchIndex = potentialMatches.findIndex((m) => |
| 130 | + this.mergeable(old, m) |
| 131 | + ) |
| 132 | + if (matchIndex !== -1) { |
| 133 | + newItem = potentialMatches.splice(matchIndex, 1)[0] |
| 134 | + stillUnmatched.delete(newItem) |
143 | 135 | } |
| 136 | + } |
| 137 | + // we found an item in the new folder that matches the one in the old folder |
| 138 | + if (newItem) { |
| 139 | + await this.diffItem(old, newItem) |
| 140 | + index++ |
| 141 | + continue |
| 142 | + } |
144 | 143 |
|
145 | | - if (newFolder.isRoot && newFolder.location === ItemLocation.LOCAL) { |
146 | | - // We can't remove root folders locally |
147 | | - return |
148 | | - } |
| 144 | + if (newFolder.isRoot && newFolder.location === ItemLocation.LOCAL) { |
| 145 | + // We can't remove root folders locally |
| 146 | + index++ |
| 147 | + continue |
| 148 | + } |
149 | 149 |
|
150 | | - this.result.REMOVE.commit({ |
151 | | - type: ActionType.REMOVE, |
152 | | - payload: old, |
153 | | - index, |
154 | | - }) |
155 | | - }, |
156 | | - 1 |
157 | | - ) |
| 150 | + this.result.REMOVE.commit({ |
| 151 | + type: ActionType.REMOVE, |
| 152 | + payload: old, |
| 153 | + index, |
| 154 | + }) |
| 155 | + |
| 156 | + index++ |
| 157 | + } |
158 | 158 |
|
159 | 159 | // created Items |
160 | | - // (using map here, because 'each' doesn't provide indices) |
161 | | - await Parallel.map( |
162 | | - Array.from(stillUnmatched.values()), |
163 | | - async(newChild) => { |
164 | | - if (oldFolder.isRoot && oldFolder.location === ItemLocation.LOCAL) { |
165 | | - // We can't create root folders locally |
166 | | - return |
167 | | - } |
168 | | - this.result.CREATE.commit({ |
169 | | - type: ActionType.CREATE, |
170 | | - payload: newChild, |
171 | | - index: newFolder.children.findIndex((child) => child === newChild), |
172 | | - }) |
173 | | - }, |
174 | | - 1 |
175 | | - ) |
| 160 | + const childToIndex = new Map<TItem<L2>, number>() |
| 161 | + newFolder.children.forEach((child, i) => childToIndex.set(child, i)) |
| 162 | + |
| 163 | + for (const newChild of stillUnmatched) { |
| 164 | + if (oldFolder.isRoot && oldFolder.location === ItemLocation.LOCAL) { |
| 165 | + // We can't create root folders locally |
| 166 | + continue |
| 167 | + } |
| 168 | + this.result.CREATE.commit({ |
| 169 | + type: ActionType.CREATE, |
| 170 | + payload: newChild, |
| 171 | + index: childToIndex.get(newChild), |
| 172 | + }) |
| 173 | + } |
176 | 174 | } |
177 | 175 |
|
178 | 176 | async diffBookmark(oldBookmark:Bookmark<L1>, newBookmark:Bookmark<L2>):Promise<void> { |
@@ -230,7 +228,12 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation> |
230 | 228 | keys.add(item.type) |
231 | 229 |
|
232 | 230 | for (const key of keys) { |
233 | | - removedFuzzyMap.set(key, (removedFuzzyMap.get(key) || []).concat({ rootAction: action, item })) |
| 231 | + let list = removedFuzzyMap.get(key) |
| 232 | + if (!list) { |
| 233 | + list = [] |
| 234 | + removedFuzzyMap.set(key, list) |
| 235 | + } |
| 236 | + list.push({ rootAction: action, item }) |
234 | 237 | } |
235 | 238 | } |
236 | 239 |
|
@@ -275,8 +278,16 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation> |
275 | 278 | const potentialSet = new Set<{ rootAction: RemoveAction<L1, L2>; item: TItem<L1> }>() |
276 | 279 | for (const key of searchKeys) { |
277 | 280 | const list = removedFuzzyMap.get(key) |
278 | | - if (list && list.filter((m) => this.mergeable(m.item, createdItem)).length) { |
279 | | - list.forEach(m => potentialSet.add(m)) |
| 281 | + if (!list) continue |
| 282 | + let hasMergeable = false |
| 283 | + for (const m of list) { |
| 284 | + if (this.mergeable(m.item, createdItem)) { |
| 285 | + hasMergeable = true |
| 286 | + break |
| 287 | + } |
| 288 | + } |
| 289 | + if (hasMergeable) { |
| 290 | + list.forEach((m) => potentialSet.add(m)) |
280 | 291 | break |
281 | 292 | } |
282 | 293 | } |
@@ -362,7 +373,6 @@ export default class Scanner<L1 extends TItemLocation, L2 extends TItemLocation> |
362 | 373 |
|
363 | 374 | await this.diffItem(oldItem, createdItem) |
364 | 375 | hasNewActions = true |
365 | | - break |
366 | 376 | } |
367 | 377 | } |
368 | 378 |
|
|
0 commit comments