@lvce-editor/explorer-view 6.13.0 → 6.14.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 +93 -45
- package/package.json +1 -1
|
@@ -1667,11 +1667,31 @@ const getChildDirentsRaw = async uri => {
|
|
|
1667
1667
|
};
|
|
1668
1668
|
|
|
1669
1669
|
const RE_CHARACTERS = /^[a-zA-Z.-]+$/;
|
|
1670
|
+
const RE_LEADING_DIGITS = /^\d+/;
|
|
1671
|
+
const compareLeadingDigits = (a, b) => {
|
|
1672
|
+
const normalizedA = a.replace(/^0+/, '') || '0';
|
|
1673
|
+
const normalizedB = b.replace(/^0+/, '') || '0';
|
|
1674
|
+
if (normalizedA.length !== normalizedB.length) {
|
|
1675
|
+
return normalizedA.length - normalizedB.length;
|
|
1676
|
+
}
|
|
1677
|
+
if (normalizedA !== normalizedB) {
|
|
1678
|
+
return normalizedA < normalizedB ? -1 : 1;
|
|
1679
|
+
}
|
|
1680
|
+
return a.length - b.length;
|
|
1681
|
+
};
|
|
1682
|
+
const compareLeadingNumbers = (a, b) => {
|
|
1683
|
+
const leadingDigitsA = a.match(RE_LEADING_DIGITS)?.[0];
|
|
1684
|
+
const leadingDigitsB = b.match(RE_LEADING_DIGITS)?.[0];
|
|
1685
|
+
if (leadingDigitsA && leadingDigitsB) {
|
|
1686
|
+
return compareLeadingDigits(leadingDigitsA, leadingDigitsB);
|
|
1687
|
+
}
|
|
1688
|
+
return 0;
|
|
1689
|
+
};
|
|
1670
1690
|
const compareStringNumeric = (a, b) => {
|
|
1671
1691
|
if (RE_CHARACTERS.test(a) && RE_CHARACTERS.test(b)) {
|
|
1672
1692
|
return a < b ? -1 : 1;
|
|
1673
1693
|
}
|
|
1674
|
-
return a.localeCompare(b, 'en', {
|
|
1694
|
+
return compareLeadingNumbers(a, b) || a.localeCompare(b, 'en', {
|
|
1675
1695
|
numeric: true
|
|
1676
1696
|
});
|
|
1677
1697
|
};
|
|
@@ -1739,14 +1759,11 @@ const getChildDirents = async (pathSeparator, parentDirentPath, parentDirentDept
|
|
|
1739
1759
|
return displayDirents;
|
|
1740
1760
|
};
|
|
1741
1761
|
|
|
1742
|
-
const isTopLevel = dirent => {
|
|
1743
|
-
return dirent.depth === 1;
|
|
1744
|
-
};
|
|
1745
|
-
|
|
1746
1762
|
const orderDirents = dirents => {
|
|
1747
1763
|
if (dirents.length === 0) {
|
|
1748
1764
|
return dirents;
|
|
1749
1765
|
}
|
|
1766
|
+
const minDepth = Math.min(...dirents.map(dirent => dirent.depth));
|
|
1750
1767
|
const withDeepChildren = (parent, processed) => {
|
|
1751
1768
|
if (processed.has(parent.path)) {
|
|
1752
1769
|
return [];
|
|
@@ -1760,7 +1777,7 @@ const orderDirents = dirents => {
|
|
|
1760
1777
|
}
|
|
1761
1778
|
return [parent, ...children];
|
|
1762
1779
|
};
|
|
1763
|
-
const topLevelDirents = dirents.filter(
|
|
1780
|
+
const topLevelDirents = dirents.filter(dirent => dirent.depth === minDepth);
|
|
1764
1781
|
const processed = new Set();
|
|
1765
1782
|
const ordered = topLevelDirents.flatMap(dirent => withDeepChildren(dirent, processed));
|
|
1766
1783
|
return ordered;
|
|
@@ -2060,14 +2077,23 @@ const computeExplorerRenamedDirentUpdate = (root, parentPath, oldUri, children,
|
|
|
2060
2077
|
const relativeOldPath = oldUri.slice(rootLength);
|
|
2061
2078
|
const relativeNewUri = newUri.slice(rootLength);
|
|
2062
2079
|
const update = Object.create(null);
|
|
2063
|
-
update[relativeDirname] = children;
|
|
2064
2080
|
const oldItems = tree[relativeOldPath] || [];
|
|
2081
|
+
update[relativeDirname] = children.map(child => {
|
|
2082
|
+
if (oldItems.length > 0 && child.path === newUri && child.type === Directory) {
|
|
2083
|
+
return {
|
|
2084
|
+
...child,
|
|
2085
|
+
type: DirectoryExpanded
|
|
2086
|
+
};
|
|
2087
|
+
}
|
|
2088
|
+
return child;
|
|
2089
|
+
});
|
|
2065
2090
|
update[relativeNewUri] = oldItems;
|
|
2066
2091
|
for (const [key, value] of Object.entries(tree)) {
|
|
2067
|
-
if (key.startsWith(`${relativeOldPath}/`)) {
|
|
2068
|
-
|
|
2069
|
-
update[newKey] = value;
|
|
2092
|
+
if (!key.startsWith(`${relativeOldPath}/`)) {
|
|
2093
|
+
continue;
|
|
2070
2094
|
}
|
|
2095
|
+
const newKey = relativeNewUri + key.slice(relativeOldPath.length);
|
|
2096
|
+
update[newKey] = value;
|
|
2071
2097
|
}
|
|
2072
2098
|
return update;
|
|
2073
2099
|
};
|
|
@@ -2244,6 +2270,10 @@ const cancelTypeAhead = state => {
|
|
|
2244
2270
|
};
|
|
2245
2271
|
};
|
|
2246
2272
|
|
|
2273
|
+
const isTopLevel = dirent => {
|
|
2274
|
+
return dirent.depth === 1;
|
|
2275
|
+
};
|
|
2276
|
+
|
|
2247
2277
|
const toCollapsedDirent = dirent => {
|
|
2248
2278
|
if (dirent.type === DirectoryExpanded) {
|
|
2249
2279
|
return {
|
|
@@ -2911,6 +2941,9 @@ const {
|
|
|
2911
2941
|
set,
|
|
2912
2942
|
wrapGetter
|
|
2913
2943
|
} = create$a();
|
|
2944
|
+
const hasSameVisibleExplorerItemInputs = (oldState, newState) => {
|
|
2945
|
+
return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.height === newState.height && oldState.itemHeight === newState.itemHeight && oldState.focusedIndex === newState.focusedIndex && oldState.editingIndex === newState.editingIndex && oldState.editingIcon === newState.editingIcon && oldState.cutItems === newState.cutItems && oldState.editingErrorMessage === newState.editingErrorMessage && oldState.dropTargets === newState.dropTargets && oldState.fileIconCache === newState.fileIconCache && oldState.decorations === newState.decorations && oldState.useChevrons === newState.useChevrons && oldState.sourceControlIgnoredUris === newState.sourceControlIgnoredUris;
|
|
2946
|
+
};
|
|
2914
2947
|
const wrapListItemCommand = fn => {
|
|
2915
2948
|
const wrappedCommand = async (id, ...args) => {
|
|
2916
2949
|
const {
|
|
@@ -2938,10 +2971,10 @@ const wrapListItemCommand = fn => {
|
|
|
2938
2971
|
} = updatedState;
|
|
2939
2972
|
const intermediate = get(id);
|
|
2940
2973
|
set(id, intermediate.oldState, updatedState);
|
|
2941
|
-
|
|
2942
|
-
if (items === intermediate.newState.items && minLineY === intermediate.newState.minLineY && height === intermediate.newState.height && itemHeight === intermediate.newState.itemHeight && editingIcon === intermediate.newState.editingIcon && cutItems === intermediate.newState.cutItems && editingErrorMessage === intermediate.newState.editingErrorMessage && dropTargets === intermediate.newState.dropTargets && fileIconCache === intermediate.newState.fileIconCache && decorations === intermediate.newState.decorations) {
|
|
2974
|
+
if (hasSameVisibleExplorerItemInputs(intermediate.newState, updatedState)) {
|
|
2943
2975
|
return;
|
|
2944
2976
|
}
|
|
2977
|
+
const maxLineY = getExplorerMaxLineY(minLineY, height, itemHeight, items.length);
|
|
2945
2978
|
const visible = items.slice(minLineY, maxLineY);
|
|
2946
2979
|
const {
|
|
2947
2980
|
icons,
|
|
@@ -3113,25 +3146,26 @@ const expandAll = async state => {
|
|
|
3113
3146
|
} = dirent;
|
|
3114
3147
|
const newDirents = [...items];
|
|
3115
3148
|
// TODO fetch child dirents in parallel
|
|
3116
|
-
for (const dirent of
|
|
3117
|
-
if (dirent.depth
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
// TODO avoid mutating state here
|
|
3131
|
-
// @ts-ignore
|
|
3132
|
-
dirent.type = DirectoryExpanded;
|
|
3133
|
-
// await expand(state, dirent.index)
|
|
3149
|
+
for (const dirent of items) {
|
|
3150
|
+
if (dirent.depth !== depth || dirent.type !== Directory) {
|
|
3151
|
+
continue;
|
|
3152
|
+
}
|
|
3153
|
+
// TODO expand
|
|
3154
|
+
// TODO avoid mutating state here
|
|
3155
|
+
// @ts-ignore
|
|
3156
|
+
dirent.type = DirectoryExpanding;
|
|
3157
|
+
// TODO handle error
|
|
3158
|
+
// TODO race condition
|
|
3159
|
+
const childDirents = await getChildDirents(pathSeparator, dirent.path, dirent.depth);
|
|
3160
|
+
const newIndex = newDirents.indexOf(dirent);
|
|
3161
|
+
if (newIndex === -1) {
|
|
3162
|
+
continue;
|
|
3134
3163
|
}
|
|
3164
|
+
newDirents.splice(newIndex + 1, 0, ...childDirents);
|
|
3165
|
+
// TODO avoid mutating state here
|
|
3166
|
+
// @ts-ignore
|
|
3167
|
+
dirent.type = DirectoryExpanded;
|
|
3168
|
+
// await expand(state, dirent.index)
|
|
3135
3169
|
}
|
|
3136
3170
|
return {
|
|
3137
3171
|
...state,
|
|
@@ -3290,11 +3324,7 @@ const lastIndex = array => {
|
|
|
3290
3324
|
return array.length - 1;
|
|
3291
3325
|
};
|
|
3292
3326
|
const fromAsync = async asyncIterable => {
|
|
3293
|
-
|
|
3294
|
-
for await (const value of asyncIterable) {
|
|
3295
|
-
children.push(value);
|
|
3296
|
-
}
|
|
3297
|
-
return children;
|
|
3327
|
+
return Array.fromAsync(asyncIterable);
|
|
3298
3328
|
};
|
|
3299
3329
|
|
|
3300
3330
|
const focusLast = state => {
|
|
@@ -4294,12 +4324,19 @@ const handleContextMenuAtIndex = async (state, index, x, y) => {
|
|
|
4294
4324
|
number(x);
|
|
4295
4325
|
number(y);
|
|
4296
4326
|
const {
|
|
4327
|
+
items,
|
|
4297
4328
|
uid
|
|
4298
4329
|
} = state;
|
|
4330
|
+
const contextMenuItem = items[index];
|
|
4331
|
+
const newItems = contextMenuItem && !contextMenuItem.selected ? items.map(item => ({
|
|
4332
|
+
...item,
|
|
4333
|
+
selected: false
|
|
4334
|
+
})) : items;
|
|
4299
4335
|
const newState = {
|
|
4300
4336
|
...state,
|
|
4301
4337
|
focused: false,
|
|
4302
|
-
focusedIndex: index
|
|
4338
|
+
focusedIndex: index,
|
|
4339
|
+
items: newItems
|
|
4303
4340
|
};
|
|
4304
4341
|
set(uid, state, newState);
|
|
4305
4342
|
await show2(uid, Explorer, x, y, {
|
|
@@ -5572,13 +5609,14 @@ const handleUpload = async (state, dirents) => {
|
|
|
5572
5609
|
// TODO switch
|
|
5573
5610
|
// TODO symlink might not be possible to be copied
|
|
5574
5611
|
// TODO create folder if type is 2
|
|
5575
|
-
if (dirent.type
|
|
5576
|
-
|
|
5577
|
-
// but not sure how else to send them via jsonrpc
|
|
5578
|
-
const content = await dirent.file.text();
|
|
5579
|
-
const absolutePath = [root, dirent.file.name].join(pathSeparator);
|
|
5580
|
-
await writeFile(absolutePath, content);
|
|
5612
|
+
if (dirent.type !== /* File */1) {
|
|
5613
|
+
continue;
|
|
5581
5614
|
}
|
|
5615
|
+
// TODO reading text might be inefficient for binary files
|
|
5616
|
+
// but not sure how else to send them via jsonrpc
|
|
5617
|
+
const content = await dirent.file.text();
|
|
5618
|
+
const absolutePath = [root, dirent.file.name].join(pathSeparator);
|
|
5619
|
+
await writeFile(absolutePath, content);
|
|
5582
5620
|
}
|
|
5583
5621
|
};
|
|
5584
5622
|
|
|
@@ -5661,7 +5699,7 @@ const confirmDelete = async paths => {
|
|
|
5661
5699
|
// TODO use i18n string
|
|
5662
5700
|
const message = paths.length === 1 ? `Are you sure you want to delete "${paths[0]}"?` : `Are you sure you want to delete ${paths.length} items?`;
|
|
5663
5701
|
const result = await confirm(message);
|
|
5664
|
-
return result
|
|
5702
|
+
return result;
|
|
5665
5703
|
};
|
|
5666
5704
|
|
|
5667
5705
|
const showErrorAlert = async errorMessage => {
|
|
@@ -6604,7 +6642,17 @@ const revealItemHidden = async (state, uri) => {
|
|
|
6604
6642
|
const pathPartsChildrenFlat = pathPartsChildren.flat();
|
|
6605
6643
|
const orderedPathParts = orderDirents(pathPartsChildrenFlat);
|
|
6606
6644
|
const mergedDirents = mergeVisibleWithHiddenItems(items, orderedPathParts);
|
|
6607
|
-
const
|
|
6645
|
+
const expandedPaths = new Set(pathPartsToReveal.map(pathPart => pathPart.path));
|
|
6646
|
+
const newDirents = mergedDirents.map(item => {
|
|
6647
|
+
if (expandedPaths.has(item.path) && item.type === Directory) {
|
|
6648
|
+
return {
|
|
6649
|
+
...item,
|
|
6650
|
+
type: DirectoryExpanded
|
|
6651
|
+
};
|
|
6652
|
+
}
|
|
6653
|
+
return item;
|
|
6654
|
+
});
|
|
6655
|
+
const index = getIndex(newDirents, uri);
|
|
6608
6656
|
if (index === -1) {
|
|
6609
6657
|
throw new Error(`File not found in explorer ${uri}`);
|
|
6610
6658
|
}
|
|
@@ -6616,7 +6664,7 @@ const revealItemHidden = async (state, uri) => {
|
|
|
6616
6664
|
...state,
|
|
6617
6665
|
focused: true,
|
|
6618
6666
|
focusedIndex: index,
|
|
6619
|
-
items:
|
|
6667
|
+
items: newDirents,
|
|
6620
6668
|
maxLineY: newMaxLineY,
|
|
6621
6669
|
minLineY: newMinLineY
|
|
6622
6670
|
};
|