@lvce-editor/explorer-view 2.36.0 → 2.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/explorerViewWorkerMain.js +235 -229
- package/package.json +1 -1
|
@@ -932,6 +932,9 @@ const dirname = (pathSeparator, path) => {
|
|
|
932
932
|
}
|
|
933
933
|
return path.slice(0, index);
|
|
934
934
|
};
|
|
935
|
+
const dirname2 = path => {
|
|
936
|
+
return dirname('/', path);
|
|
937
|
+
};
|
|
935
938
|
const join = (pathSeparator, ...parts) => {
|
|
936
939
|
return parts.join(pathSeparator);
|
|
937
940
|
};
|
|
@@ -960,6 +963,21 @@ const createNewDirentsAccept = async (newFileName, pathSeparator, absolutePath,
|
|
|
960
963
|
}
|
|
961
964
|
};
|
|
962
965
|
|
|
966
|
+
const createTree = (items, root) => {
|
|
967
|
+
const tree = Object.create(null);
|
|
968
|
+
const rootLength = root.length;
|
|
969
|
+
for (const item of items) {
|
|
970
|
+
const relativePath = item.path.slice(rootLength);
|
|
971
|
+
const dirname = dirname2(relativePath);
|
|
972
|
+
tree[dirname] ||= [];
|
|
973
|
+
tree[dirname].push({
|
|
974
|
+
name: item.name,
|
|
975
|
+
type: item.type
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
return tree;
|
|
979
|
+
};
|
|
980
|
+
|
|
963
981
|
const None$5 = 0;
|
|
964
982
|
const CreateFile = 1;
|
|
965
983
|
const CreateFolder = 2;
|
|
@@ -1158,6 +1176,88 @@ const getFileIcons = async (dirents, fileIconCache) => {
|
|
|
1158
1176
|
};
|
|
1159
1177
|
};
|
|
1160
1178
|
|
|
1179
|
+
const getParentFolder = (dirents, index, root) => {
|
|
1180
|
+
if (index < 0) {
|
|
1181
|
+
return root;
|
|
1182
|
+
}
|
|
1183
|
+
return dirents[index].path;
|
|
1184
|
+
};
|
|
1185
|
+
|
|
1186
|
+
const getPathParts = (root, uri, pathSeparator) => {
|
|
1187
|
+
const parts = [];
|
|
1188
|
+
let index = root.length - 1;
|
|
1189
|
+
let depth = 0;
|
|
1190
|
+
while ((index = uri.indexOf('/', index + 1)) !== -1) {
|
|
1191
|
+
const partUri = uri.slice(0, index);
|
|
1192
|
+
parts.push({
|
|
1193
|
+
path: partUri,
|
|
1194
|
+
depth: depth++,
|
|
1195
|
+
root,
|
|
1196
|
+
pathSeparator
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
return parts;
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
const isSymbolicLink = dirent => {
|
|
1203
|
+
return dirent.type === Symlink;
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1206
|
+
const hasSymbolicLinks = rawDirents => {
|
|
1207
|
+
return rawDirents.some(isSymbolicLink);
|
|
1208
|
+
};
|
|
1209
|
+
|
|
1210
|
+
const ENOENT = 'ENOENT';
|
|
1211
|
+
|
|
1212
|
+
const getSymlinkType = type => {
|
|
1213
|
+
switch (type) {
|
|
1214
|
+
case File:
|
|
1215
|
+
return SymLinkFile;
|
|
1216
|
+
case Directory:
|
|
1217
|
+
return SymLinkFolder;
|
|
1218
|
+
default:
|
|
1219
|
+
return Symlink;
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
// TODO maybe resolving of symbolic links should happen in shared process?
|
|
1224
|
+
// so that there is less code and less work in the frontend
|
|
1225
|
+
const resolveSymbolicLink = async (uri, rawDirent) => {
|
|
1226
|
+
try {
|
|
1227
|
+
// TODO support windows paths
|
|
1228
|
+
const absolutePath = uri + '/' + rawDirent.name;
|
|
1229
|
+
const type = await stat(absolutePath);
|
|
1230
|
+
const symLinkType = getSymlinkType(type);
|
|
1231
|
+
return {
|
|
1232
|
+
name: rawDirent.name,
|
|
1233
|
+
type: symLinkType
|
|
1234
|
+
};
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
// @ts-ignore
|
|
1237
|
+
if (error && error.code === ENOENT) {
|
|
1238
|
+
return {
|
|
1239
|
+
name: rawDirent.name,
|
|
1240
|
+
type: SymLinkFile
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
console.error(`Failed to resolve symbolic link for ${rawDirent.name}: ${error}`);
|
|
1244
|
+
return rawDirent;
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
const resolveSymbolicLinks = async (uri, rawDirents) => {
|
|
1248
|
+
const promises = [];
|
|
1249
|
+
for (const rawDirent of rawDirents) {
|
|
1250
|
+
if (isSymbolicLink(rawDirent)) {
|
|
1251
|
+
const resolvedDirent = resolveSymbolicLink(uri, rawDirent);
|
|
1252
|
+
promises.push(resolvedDirent);
|
|
1253
|
+
} else {
|
|
1254
|
+
promises.push(rawDirent);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
const resolvedDirents = await Promise.all(promises);
|
|
1258
|
+
return resolvedDirents;
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1161
1261
|
const RE_CHARACTERS = /^[a-zA-Z.-]+$/;
|
|
1162
1262
|
const compareStringNumeric = (a, b) => {
|
|
1163
1263
|
if (RE_CHARACTERS.test(a) && RE_CHARACTERS.test(b)) {
|
|
@@ -1186,72 +1286,138 @@ const compareDirent = (direntA, direntB) => {
|
|
|
1186
1286
|
return compareDirentType(direntA, direntB) || compareDirentName(direntA, direntB);
|
|
1187
1287
|
};
|
|
1188
1288
|
|
|
1189
|
-
const
|
|
1190
|
-
|
|
1191
|
-
return root;
|
|
1192
|
-
}
|
|
1193
|
-
return dirents[index].path;
|
|
1289
|
+
const sortExplorerItems = rawDirents => {
|
|
1290
|
+
return rawDirents.toSorted(compareDirent);
|
|
1194
1291
|
};
|
|
1195
1292
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
const
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
setSize: 1,
|
|
1208
|
-
depth,
|
|
1209
|
-
name: newFileName,
|
|
1210
|
-
type: newDirentType,
|
|
1293
|
+
// TODO figure out whether this uses too much memory (name,path -> redundant, depth could be computed on demand)
|
|
1294
|
+
const toDisplayDirent = (parentDirent, rawDirent, index, length) => {
|
|
1295
|
+
const path = join2(parentDirent.path, rawDirent.name);
|
|
1296
|
+
return {
|
|
1297
|
+
name: rawDirent.name,
|
|
1298
|
+
posInSet: index + 1,
|
|
1299
|
+
setSize: length,
|
|
1300
|
+
depth: parentDirent.depth + 1,
|
|
1301
|
+
type: rawDirent.type,
|
|
1302
|
+
path,
|
|
1303
|
+
// TODO storing absolute path might be too costly, could also store relative path here
|
|
1211
1304
|
icon: '',
|
|
1212
1305
|
selected: false
|
|
1213
1306
|
};
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
for (; i < items.length; i++) {
|
|
1223
|
-
const dirent = items[i];
|
|
1224
|
-
if (dirent.depth !== depth) {
|
|
1225
|
-
break;
|
|
1226
|
-
}
|
|
1227
|
-
const compareResult = compareDirent(dirent, newDirent);
|
|
1228
|
-
if (compareResult === 1) {
|
|
1229
|
-
insertIndex = i - 1;
|
|
1230
|
-
deltaPosInSet = 1 - 1;
|
|
1231
|
-
break;
|
|
1232
|
-
} else {
|
|
1233
|
-
// @ts-ignore
|
|
1234
|
-
posInSet = dirent.posInSet + 1;
|
|
1235
|
-
// @ts-ignore
|
|
1236
|
-
setSize = dirent.setSize + 1;
|
|
1237
|
-
// @ts-ignore
|
|
1238
|
-
insertIndex = i;
|
|
1307
|
+
};
|
|
1308
|
+
|
|
1309
|
+
const toDisplayDirents = (pathSeparator, rawDirents, parentDirent, excluded) => {
|
|
1310
|
+
rawDirents = sortExplorerItems(rawDirents);
|
|
1311
|
+
const result = [];
|
|
1312
|
+
const visibleItems = rawDirents.filter(item => {
|
|
1313
|
+
if (excluded.includes(item.name)) {
|
|
1314
|
+
return false;
|
|
1239
1315
|
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1316
|
+
return true;
|
|
1317
|
+
});
|
|
1318
|
+
const count = visibleItems.length;
|
|
1319
|
+
for (let i = 0; i < visibleItems.length; i++) {
|
|
1320
|
+
const rawDirent = visibleItems[i];
|
|
1321
|
+
result.push(toDisplayDirent(parentDirent, rawDirent, i, count));
|
|
1244
1322
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1323
|
+
return result;
|
|
1324
|
+
};
|
|
1325
|
+
|
|
1326
|
+
const getChildDirentsRaw = async uri => {
|
|
1327
|
+
const rawDirents = await readDirWithFileTypes(uri);
|
|
1328
|
+
array(rawDirents);
|
|
1329
|
+
if (hasSymbolicLinks(rawDirents)) {
|
|
1330
|
+
return resolveSymbolicLinks(uri, rawDirents);
|
|
1331
|
+
}
|
|
1332
|
+
return rawDirents;
|
|
1333
|
+
};
|
|
1334
|
+
const getChildDirents = async (pathSeparator, parentDirent, excluded = []) => {
|
|
1335
|
+
string(pathSeparator);
|
|
1336
|
+
object(parentDirent);
|
|
1337
|
+
// TODO use event/actor based code instead, this is impossible to cancel right now
|
|
1338
|
+
// also cancel updating when opening new folder
|
|
1339
|
+
// const dispose = state => state.pendingRequests.forEach(cancelRequest)
|
|
1340
|
+
// TODO should use FileSystem directly in this case because it is globally available anyway
|
|
1341
|
+
// and more typesafe than Command.execute
|
|
1342
|
+
// and more performant
|
|
1343
|
+
const uri = parentDirent.path;
|
|
1344
|
+
const rawDirents = await getChildDirentsRaw(uri);
|
|
1345
|
+
const displayDirents = toDisplayDirents(pathSeparator, rawDirents, parentDirent, excluded);
|
|
1346
|
+
return displayDirents;
|
|
1347
|
+
};
|
|
1348
|
+
|
|
1349
|
+
const isTopLevel = dirent => {
|
|
1350
|
+
return dirent.depth === 1;
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1353
|
+
const orderDirents = dirents => {
|
|
1354
|
+
if (dirents.length === 0) {
|
|
1355
|
+
return dirents;
|
|
1356
|
+
}
|
|
1357
|
+
const withDeepChildren = (parent, processed) => {
|
|
1358
|
+
if (processed.has(parent.path)) {
|
|
1359
|
+
return [];
|
|
1360
|
+
}
|
|
1361
|
+
processed.add(parent.path);
|
|
1362
|
+
const children = [];
|
|
1363
|
+
for (const dirent of dirents) {
|
|
1364
|
+
if (dirent.depth === parent.depth + 1 && dirent.path.startsWith(parent.path)) {
|
|
1365
|
+
children.push(...withDeepChildren(dirent, processed));
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return [parent, ...children];
|
|
1369
|
+
};
|
|
1370
|
+
const topLevelDirents = dirents.filter(isTopLevel);
|
|
1371
|
+
const processed = new Set();
|
|
1372
|
+
const ordered = topLevelDirents.flatMap(dirent => withDeepChildren(dirent, processed));
|
|
1373
|
+
return ordered;
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1376
|
+
const getPathPartChildren = async pathPart => {
|
|
1377
|
+
const children = await getChildDirents(pathPart.pathSeparator, pathPart);
|
|
1378
|
+
return children;
|
|
1379
|
+
};
|
|
1380
|
+
const getPathPartsChildren = async pathparts => {
|
|
1381
|
+
const pathPartsChildren = await Promise.all(pathparts.map(getPathPartChildren));
|
|
1382
|
+
const pathPartsChildrenFlat = pathPartsChildren.flat();
|
|
1383
|
+
const orderedPathParts = orderDirents(pathPartsChildrenFlat);
|
|
1384
|
+
return orderedPathParts;
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1387
|
+
const mergeTrees = (a, b) => {
|
|
1251
1388
|
return {
|
|
1252
|
-
|
|
1253
|
-
|
|
1389
|
+
...a,
|
|
1390
|
+
...b
|
|
1391
|
+
};
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
const treeToArray = (map, root) => {
|
|
1395
|
+
const items = [];
|
|
1396
|
+
const processChildren = (path, depth) => {
|
|
1397
|
+
const children = map[path];
|
|
1398
|
+
if (!children) {
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
const count = children.length;
|
|
1402
|
+
for (let i = 0; i < count; i++) {
|
|
1403
|
+
const child = children[i];
|
|
1404
|
+
const childPath = join2(path, child.name);
|
|
1405
|
+
const absolutePath = `${root}${childPath}`;
|
|
1406
|
+
items.push({
|
|
1407
|
+
depth,
|
|
1408
|
+
posInSet: i + 1,
|
|
1409
|
+
setSize: count,
|
|
1410
|
+
icon: '',
|
|
1411
|
+
path: absolutePath,
|
|
1412
|
+
selected: false,
|
|
1413
|
+
name: child.name,
|
|
1414
|
+
type: child.type
|
|
1415
|
+
});
|
|
1416
|
+
processChildren(childPath, depth + 1);
|
|
1417
|
+
}
|
|
1254
1418
|
};
|
|
1419
|
+
processChildren('', 0);
|
|
1420
|
+
return items;
|
|
1255
1421
|
};
|
|
1256
1422
|
|
|
1257
1423
|
const acceptCreate = async (state, newDirentType, createFn) => {
|
|
@@ -1283,10 +1449,14 @@ const acceptCreate = async (state, newDirentType, createFn) => {
|
|
|
1283
1449
|
if (!successful) {
|
|
1284
1450
|
return state;
|
|
1285
1451
|
}
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1452
|
+
const pathPaths = getPathParts(root, absolutePath, pathSeparator);
|
|
1453
|
+
const children = await getPathPartsChildren(pathPaths);
|
|
1454
|
+
const tree = createTree(items, root);
|
|
1455
|
+
const childTree = createTree(children, root);
|
|
1456
|
+
const merged = mergeTrees(tree, childTree);
|
|
1457
|
+
const newItems = treeToArray(merged, root);
|
|
1458
|
+
const dirents = newItems;
|
|
1459
|
+
const newFocusedIndex = newItems.findIndex(dirent => dirent.path === absolutePath);
|
|
1290
1460
|
const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, dirents.length);
|
|
1291
1461
|
const visible = dirents.slice(minLineY, maxLineY);
|
|
1292
1462
|
const {
|
|
@@ -1413,7 +1583,7 @@ const createNewDirentsRename = async (renamedDirent, editingValue, pathSeparator
|
|
|
1413
1583
|
try {
|
|
1414
1584
|
// TODO this does not work with rename of nested file
|
|
1415
1585
|
const oldAbsolutePath = renamedDirent.path;
|
|
1416
|
-
const oldParentPath =
|
|
1586
|
+
const oldParentPath = dirname2(oldAbsolutePath);
|
|
1417
1587
|
const newAbsolutePath = join2(oldParentPath, editingValue);
|
|
1418
1588
|
await rename$1(oldAbsolutePath, newAbsolutePath);
|
|
1419
1589
|
} catch (error) {
|
|
@@ -1427,11 +1597,9 @@ const acceptRename = async state => {
|
|
|
1427
1597
|
const {
|
|
1428
1598
|
editingIndex,
|
|
1429
1599
|
editingValue,
|
|
1430
|
-
items
|
|
1431
|
-
pathSeparator
|
|
1432
|
-
} = state;
|
|
1600
|
+
items} = state;
|
|
1433
1601
|
const renamedDirent = items[editingIndex];
|
|
1434
|
-
const successful = await createNewDirentsRename(renamedDirent, editingValue
|
|
1602
|
+
const successful = await createNewDirentsRename(renamedDirent, editingValue);
|
|
1435
1603
|
if (!successful) {
|
|
1436
1604
|
return state;
|
|
1437
1605
|
}
|
|
@@ -1546,10 +1714,6 @@ const cancelTypeAhead = state => {
|
|
|
1546
1714
|
};
|
|
1547
1715
|
};
|
|
1548
1716
|
|
|
1549
|
-
const isTopLevel = dirent => {
|
|
1550
|
-
return dirent.depth === 1;
|
|
1551
|
-
};
|
|
1552
|
-
|
|
1553
1717
|
const toCollapsedDirent = dirent => {
|
|
1554
1718
|
if (dirent.type === DirectoryExpanded) {
|
|
1555
1719
|
return {
|
|
@@ -1827,120 +1991,6 @@ const diff2 = uid => {
|
|
|
1827
1991
|
return result;
|
|
1828
1992
|
};
|
|
1829
1993
|
|
|
1830
|
-
const isSymbolicLink = dirent => {
|
|
1831
|
-
return dirent.type === Symlink;
|
|
1832
|
-
};
|
|
1833
|
-
|
|
1834
|
-
const hasSymbolicLinks = rawDirents => {
|
|
1835
|
-
return rawDirents.some(isSymbolicLink);
|
|
1836
|
-
};
|
|
1837
|
-
|
|
1838
|
-
const ENOENT = 'ENOENT';
|
|
1839
|
-
|
|
1840
|
-
const getSymlinkType = type => {
|
|
1841
|
-
switch (type) {
|
|
1842
|
-
case File:
|
|
1843
|
-
return SymLinkFile;
|
|
1844
|
-
case Directory:
|
|
1845
|
-
return SymLinkFolder;
|
|
1846
|
-
default:
|
|
1847
|
-
return Symlink;
|
|
1848
|
-
}
|
|
1849
|
-
};
|
|
1850
|
-
|
|
1851
|
-
// TODO maybe resolving of symbolic links should happen in shared process?
|
|
1852
|
-
// so that there is less code and less work in the frontend
|
|
1853
|
-
const resolveSymbolicLink = async (uri, rawDirent) => {
|
|
1854
|
-
try {
|
|
1855
|
-
// TODO support windows paths
|
|
1856
|
-
const absolutePath = uri + '/' + rawDirent.name;
|
|
1857
|
-
const type = await stat(absolutePath);
|
|
1858
|
-
const symLinkType = getSymlinkType(type);
|
|
1859
|
-
return {
|
|
1860
|
-
name: rawDirent.name,
|
|
1861
|
-
type: symLinkType
|
|
1862
|
-
};
|
|
1863
|
-
} catch (error) {
|
|
1864
|
-
// @ts-ignore
|
|
1865
|
-
if (error && error.code === ENOENT) {
|
|
1866
|
-
return {
|
|
1867
|
-
name: rawDirent.name,
|
|
1868
|
-
type: SymLinkFile
|
|
1869
|
-
};
|
|
1870
|
-
}
|
|
1871
|
-
console.error(`Failed to resolve symbolic link for ${rawDirent.name}: ${error}`);
|
|
1872
|
-
return rawDirent;
|
|
1873
|
-
}
|
|
1874
|
-
};
|
|
1875
|
-
const resolveSymbolicLinks = async (uri, rawDirents) => {
|
|
1876
|
-
const promises = [];
|
|
1877
|
-
for (const rawDirent of rawDirents) {
|
|
1878
|
-
if (isSymbolicLink(rawDirent)) {
|
|
1879
|
-
const resolvedDirent = resolveSymbolicLink(uri, rawDirent);
|
|
1880
|
-
promises.push(resolvedDirent);
|
|
1881
|
-
} else {
|
|
1882
|
-
promises.push(rawDirent);
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
const resolvedDirents = await Promise.all(promises);
|
|
1886
|
-
return resolvedDirents;
|
|
1887
|
-
};
|
|
1888
|
-
|
|
1889
|
-
const sortExplorerItems = rawDirents => {
|
|
1890
|
-
return rawDirents.toSorted(compareDirent);
|
|
1891
|
-
};
|
|
1892
|
-
|
|
1893
|
-
const toDisplayDirents = (pathSeparator, rawDirents, parentDirent, excluded) => {
|
|
1894
|
-
rawDirents = sortExplorerItems(rawDirents);
|
|
1895
|
-
// TODO figure out whether this uses too much memory (name,path -> redundant, depth could be computed on demand)
|
|
1896
|
-
const toDisplayDirent = (rawDirent, index) => {
|
|
1897
|
-
const path = [parentDirent.path, rawDirent.name].join(pathSeparator);
|
|
1898
|
-
return {
|
|
1899
|
-
name: rawDirent.name,
|
|
1900
|
-
posInSet: index + 1,
|
|
1901
|
-
setSize: rawDirents.length,
|
|
1902
|
-
depth: parentDirent.depth + 1,
|
|
1903
|
-
type: rawDirent.type,
|
|
1904
|
-
path,
|
|
1905
|
-
// TODO storing absolute path might be too costly, could also store relative path here
|
|
1906
|
-
icon: ''
|
|
1907
|
-
};
|
|
1908
|
-
};
|
|
1909
|
-
const result = [];
|
|
1910
|
-
let i = 0;
|
|
1911
|
-
for (const rawDirent of rawDirents) {
|
|
1912
|
-
if (excluded.includes(rawDirent.name)) {
|
|
1913
|
-
continue;
|
|
1914
|
-
}
|
|
1915
|
-
result.push(toDisplayDirent(rawDirent, i));
|
|
1916
|
-
i++;
|
|
1917
|
-
}
|
|
1918
|
-
return result;
|
|
1919
|
-
};
|
|
1920
|
-
|
|
1921
|
-
const getChildDirentsRaw = async uri => {
|
|
1922
|
-
const rawDirents = await readDirWithFileTypes(uri);
|
|
1923
|
-
array(rawDirents);
|
|
1924
|
-
if (hasSymbolicLinks(rawDirents)) {
|
|
1925
|
-
return resolveSymbolicLinks(uri, rawDirents);
|
|
1926
|
-
}
|
|
1927
|
-
return rawDirents;
|
|
1928
|
-
};
|
|
1929
|
-
const getChildDirents = async (pathSeparator, parentDirent, excluded = []) => {
|
|
1930
|
-
string(pathSeparator);
|
|
1931
|
-
object(parentDirent);
|
|
1932
|
-
// TODO use event/actor based code instead, this is impossible to cancel right now
|
|
1933
|
-
// also cancel updating when opening new folder
|
|
1934
|
-
// const dispose = state => state.pendingRequests.forEach(cancelRequest)
|
|
1935
|
-
// TODO should use FileSystem directly in this case because it is globally available anyway
|
|
1936
|
-
// and more typesafe than Command.execute
|
|
1937
|
-
// and more performant
|
|
1938
|
-
const uri = parentDirent.path;
|
|
1939
|
-
const rawDirents = await getChildDirentsRaw(uri);
|
|
1940
|
-
const displayDirents = toDisplayDirents(pathSeparator, rawDirents, parentDirent, excluded);
|
|
1941
|
-
return displayDirents;
|
|
1942
|
-
};
|
|
1943
|
-
|
|
1944
1994
|
const expandAll = async state => {
|
|
1945
1995
|
const {
|
|
1946
1996
|
items,
|
|
@@ -4847,22 +4897,6 @@ const getIndex = (dirents, uri) => {
|
|
|
4847
4897
|
return -1;
|
|
4848
4898
|
};
|
|
4849
4899
|
|
|
4850
|
-
const getPathParts = (root, uri, pathSeparator) => {
|
|
4851
|
-
const parts = [];
|
|
4852
|
-
let index = root.length - 1;
|
|
4853
|
-
let depth = 0;
|
|
4854
|
-
while ((index = uri.indexOf('/', index + 1)) !== -1) {
|
|
4855
|
-
const partUri = uri.slice(0, index);
|
|
4856
|
-
parts.push({
|
|
4857
|
-
path: partUri,
|
|
4858
|
-
depth: depth++,
|
|
4859
|
-
root,
|
|
4860
|
-
pathSeparator
|
|
4861
|
-
});
|
|
4862
|
-
}
|
|
4863
|
-
return parts;
|
|
4864
|
-
};
|
|
4865
|
-
|
|
4866
4900
|
const getPathPartsToReveal = (root, pathParts, dirents) => {
|
|
4867
4901
|
for (let i = 0; i < pathParts.length; i++) {
|
|
4868
4902
|
const pathPart = pathParts[i];
|
|
@@ -4889,29 +4923,6 @@ const mergeVisibleWithHiddenItems = (visibleItems, hiddenItems) => {
|
|
|
4889
4923
|
return unique;
|
|
4890
4924
|
};
|
|
4891
4925
|
|
|
4892
|
-
const orderDirents = dirents => {
|
|
4893
|
-
if (dirents.length === 0) {
|
|
4894
|
-
return dirents;
|
|
4895
|
-
}
|
|
4896
|
-
const withDeepChildren = (parent, processed) => {
|
|
4897
|
-
if (processed.has(parent.path)) {
|
|
4898
|
-
return [];
|
|
4899
|
-
}
|
|
4900
|
-
processed.add(parent.path);
|
|
4901
|
-
const children = [];
|
|
4902
|
-
for (const dirent of dirents) {
|
|
4903
|
-
if (dirent.depth === parent.depth + 1 && dirent.path.startsWith(parent.path)) {
|
|
4904
|
-
children.push(...withDeepChildren(dirent, processed));
|
|
4905
|
-
}
|
|
4906
|
-
}
|
|
4907
|
-
return [parent, ...children];
|
|
4908
|
-
};
|
|
4909
|
-
const topLevelDirents = dirents.filter(isTopLevel);
|
|
4910
|
-
const processed = new Set();
|
|
4911
|
-
const ordered = topLevelDirents.flatMap(dirent => withDeepChildren(dirent, processed));
|
|
4912
|
-
return ordered;
|
|
4913
|
-
};
|
|
4914
|
-
|
|
4915
4926
|
const scrollInto = (index, minLineY, maxLineY) => {
|
|
4916
4927
|
const diff = maxLineY - minLineY;
|
|
4917
4928
|
const smallerHalf = Math.floor(diff / 2);
|
|
@@ -4934,11 +4945,6 @@ const scrollInto = (index, minLineY, maxLineY) => {
|
|
|
4934
4945
|
};
|
|
4935
4946
|
};
|
|
4936
4947
|
|
|
4937
|
-
const getPathPartChildren = async pathPart => {
|
|
4938
|
-
const children = await getChildDirents(pathPart.pathSeparator, pathPart);
|
|
4939
|
-
return children;
|
|
4940
|
-
};
|
|
4941
|
-
|
|
4942
4948
|
// TODO maybe just insert items into explorer and refresh whole explorer
|
|
4943
4949
|
const revealItemHidden = async (state, uri) => {
|
|
4944
4950
|
const {
|
|
@@ -4953,7 +4959,7 @@ const revealItemHidden = async (state, uri) => {
|
|
|
4953
4959
|
return state;
|
|
4954
4960
|
}
|
|
4955
4961
|
const pathPartsToReveal = getPathPartsToReveal(root, pathParts, items);
|
|
4956
|
-
const pathPartsChildren = await
|
|
4962
|
+
const pathPartsChildren = await getPathPartsChildren(pathPartsToReveal);
|
|
4957
4963
|
const pathPartsChildrenFlat = pathPartsChildren.flat();
|
|
4958
4964
|
const orderedPathParts = orderDirents(pathPartsChildrenFlat);
|
|
4959
4965
|
const mergedDirents = mergeVisibleWithHiddenItems(items, orderedPathParts);
|